non-PCH build fix (according to Tinderbox).
[wxWidgets.git] / samples / rotate / rotate.cpp
index 3a11213e83661f184d14e0668882f8ec5f3f77de..3b48a063ab2c9e089f57caa6284d0d3fc49f9d4f 100644 (file)
@@ -9,6 +9,14 @@
 // Licence:   wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 
 #include "wx/image.h"
 #include "wx/numdlg.h"
+#include "wx/dynarray.h"
 
-/* GRG: This is not ANSI standard, define M_PI explicitly
-#include <math.h>       // M_PI
-*/
-
-#ifndef M_PI
-#define M_PI 3.1415926535897932384626433832795
-#endif
-
+// ----------------------------------------------------------------------------
+// application class
+// ----------------------------------------------------------------------------
 
 class MyApp: public wxApp
 {
 public:
     virtual bool OnInit();
-
     const wxImage& GetImage() const { return m_image; }
 
 private:
     wxImage m_image;
 };
 
+// ----------------------------------------------------------------------------
+// data class for images that need to be rendered
+// ----------------------------------------------------------------------------
+
+class MyRenderedImage
+{
+public:
+    MyRenderedImage(const wxBitmap& bmp, int x, int y)
+        : m_bmp(bmp), m_x(x), m_y(y) { }
+    wxBitmap m_bmp;
+    int m_x, m_y;
+};
+
+// Declare a wxArray type to hold MyRenderedImages.
+WX_DECLARE_OBJARRAY(MyRenderedImage, ArrayOfImages);
+
+// ----------------------------------------------------------------------------
+// custom canvas control that we can draw on
+// ----------------------------------------------------------------------------
 
 class MyCanvas: public wxScrolledWindow
 {
 public:
     MyCanvas(wxWindow* parent);
 
+    void ClearImages();
+
     void OnMouseLeftUp (wxMouseEvent & event);
     void OnMouseRightUp (wxMouseEvent & event);
+    void OnPaint (wxPaintEvent & event);
 
 private:
+    ArrayOfImages m_images;
 
     DECLARE_EVENT_TABLE()
 };
 
+// ----------------------------------------------------------------------------
+// main frame
+// ----------------------------------------------------------------------------
+
 class MyFrame: public wxFrame
 {
 public:
@@ -64,61 +94,155 @@ public:
 
     void OnQuit (wxCommandEvent &);
     void OnAngle(wxCommandEvent &);
+    void OnClear(wxCommandEvent &);
 
     double  m_angle;
 
     DECLARE_EVENT_TABLE()
+
+private:
+    MyCanvas *m_canvas;
 };
 
+// ----------------------------------------------------------------------------
+// menu item identifiers
+// ----------------------------------------------------------------------------
+
 enum
 {
     ID_Quit = 1,
-    ID_Angle
+    ID_Angle,
+    ID_Clear
 };
 
-BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
-    EVT_LEFT_UP (MyCanvas::OnMouseLeftUp)
-    EVT_RIGHT_UP (MyCanvas::OnMouseRightUp)
-END_EVENT_TABLE()
+// ============================================================================
+// implementation
+// ============================================================================
 
-BEGIN_EVENT_TABLE(MyFrame, wxFrame)
-    EVT_MENU (ID_Quit, MyFrame::OnQuit)
-    EVT_MENU (ID_Angle, MyFrame::OnAngle)
-END_EVENT_TABLE()
+// ----------------------------------------------------------------------------
+// application class
+// ----------------------------------------------------------------------------
 
 IMPLEMENT_APP(MyApp)
 
 bool MyApp::OnInit()
 {
-    m_image = wxImage(_T("kclub.bmp"), wxBITMAP_TYPE_BMP);
+#if wxUSE_LIBPNG
+    wxImage::AddHandler( new wxPNGHandler );
+#endif
 
-    // any unused colour will do
-    m_image.SetMaskColour( 0, 255, 255 );
+    m_image = wxImage(_T("duck.png"), wxBITMAP_TYPE_PNG);
 
     if ( !m_image.Ok() )
     {
         wxLogError(wxT("Can't load the test image, please copy it to the ")
                    wxT("program directory"));
-        return FALSE;
+        return false;
     }
 
-    MyFrame *frame = new MyFrame (_T("wxWindows rotate sample"),
-                                  wxPoint(20,20), wxSize(600,450));
+    MyFrame *frame = new MyFrame (_T("wxWidgets rotate sample"),
+                                  wxPoint(20, 20), wxSize(600, 450));
 
-    frame->Show (TRUE);
+    frame->Show (true);
     SetTopWindow (frame);
-    return TRUE;
+    return true;
+}
+
+// ----------------------------------------------------------------------------
+// data class for images that need to be rendered
+// ----------------------------------------------------------------------------
+
+#include "wx/arrimpl.cpp"
+WX_DEFINE_OBJARRAY(ArrayOfImages)
+
+// ----------------------------------------------------------------------------
+// custom canvas control that we can draw on
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
+    EVT_LEFT_UP (MyCanvas::OnMouseLeftUp)
+    EVT_RIGHT_UP (MyCanvas::OnMouseRightUp)
+    EVT_PAINT (MyCanvas::OnPaint)
+END_EVENT_TABLE()
+
+MyCanvas::MyCanvas(wxWindow* parent):
+  wxScrolledWindow(parent, wxID_ANY)
+{
+    SetBackgroundColour (wxColour (0,80,60));
+    ClearBackground();
+}
+
+void MyCanvas::ClearImages ()
+{
+    m_images.Clear();
+    Refresh(true);
+}
+
+// Rotate with interpolation and with offset correction
+void MyCanvas::OnMouseLeftUp (wxMouseEvent & event)
+{
+    MyFrame* frame = (MyFrame*) GetParent();
+
+    wxPoint offset;
+    const wxImage& img = wxGetApp().GetImage();
+    wxImage img2 = img.Rotate(frame->m_angle,
+        wxPoint(img.GetWidth() / 2, img.GetHeight() / 2), true, &offset);
+
+    // Add the images to an array to be drawn later in OnPaint()
+    m_images.Add(new MyRenderedImage(wxBitmap(img2),
+        event.m_x + offset.x, event.m_y + offset.y));
+    Refresh(false);
+}
+
+// without interpolation, and without offset correction
+void MyCanvas::OnMouseRightUp (wxMouseEvent & event)
+{
+    MyFrame* frame = (MyFrame*) GetParent();
+
+    const wxImage& img = wxGetApp().GetImage();
+    wxImage img2 = img.Rotate(frame->m_angle,
+        wxPoint(img.GetWidth() / 2, img.GetHeight() / 2), false);
+
+    // Add the images to an array to be drawn later in OnPaint()
+    m_images.Add(new MyRenderedImage(wxBitmap(img2), event.m_x, event.m_y));
+    Refresh(false);
 }
 
+void MyCanvas::OnPaint (wxPaintEvent &)
+{
+    size_t numImages = m_images.GetCount();
+
+    wxPaintDC dc(this);
+
+    dc.SetTextForeground(wxColour(255, 255, 255));
+    dc.DrawText(wxT("Click on the canvas to draw a duck."), 10, 10);
+
+    for (size_t i = 0; i < numImages; i++) {
+        MyRenderedImage & image = m_images.Item(i);
+        dc.DrawBitmap(image.m_bmp, image.m_x, image.m_y, true);
+    }
+}
+
+// ----------------------------------------------------------------------------
+// main frame
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+    EVT_MENU (ID_Quit, MyFrame::OnQuit)
+    EVT_MENU (ID_Angle, MyFrame::OnAngle)
+    EVT_MENU (ID_Clear, MyFrame::OnClear)
+END_EVENT_TABLE()
+
 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
-    : wxFrame((wxFrame *)NULL, -1, title, pos, size)
+    : wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size)
 {
     m_angle = 0.1;
 
-    new MyCanvas(this);
+    m_canvas = new MyCanvas(this);
 
     wxMenu *menuFile = new wxMenu;
-    menuFile->Append (ID_Angle, _T("Set &angle\tCtrl-A"));
+    menuFile->Append (ID_Angle, _T("Set &angle...\tCtrl-A"));
+    menuFile->Append (ID_Clear, _T("&Clear all ducks\tCtrl-C"));
     menuFile->AppendSeparator();
     menuFile->Append (ID_Quit, _T("E&xit\tAlt-X"));
 
@@ -133,7 +257,7 @@ void MyFrame::OnAngle (wxCommandEvent &)
     long degrees = (long)((180*m_angle)/M_PI);
     degrees = wxGetNumberFromUser(_T("Change the image rotation angle"),
                                   _T("Angle in degrees:"),
-                                  _T("wxWindows rotate sample"),
+                                  _T("wxWidgets rotate sample"),
                                   degrees,
                                   -180, +180,
                                   this);
@@ -143,41 +267,11 @@ void MyFrame::OnAngle (wxCommandEvent &)
 
 void MyFrame::OnQuit (wxCommandEvent &)
 {
-    Close (TRUE);
-}
-
-MyCanvas::MyCanvas(wxWindow* parent):
-  wxScrolledWindow(parent, -1)
-{
-    SetBackgroundColour (wxColour (0,80,60));
-    ClearBackground();
+    Close (true);
 }
 
-// Rotate with interpolation and with offset correction
-void MyCanvas::OnMouseLeftUp (wxMouseEvent & event)
+void MyFrame::OnClear (wxCommandEvent &)
 {
-    MyFrame* frame = (MyFrame*) GetParent();
-
-    wxPoint offset;
-    const wxImage& img = wxGetApp().GetImage();
-    wxImage img2 = img.Rotate(frame->m_angle, wxPoint(img.GetWidth()/2, img.GetHeight()/2), TRUE, &offset);
-
-    wxBitmap bmp(img2);
-
-    wxClientDC dc (this);
-    dc.DrawBitmap (bmp, event.m_x + offset.x, event.m_y + offset.y, TRUE);
+    m_canvas->ClearImages ();
 }
 
-// without interpolation, and without offset correction
-void MyCanvas::OnMouseRightUp (wxMouseEvent & event)
-{
-    MyFrame* frame = (MyFrame*) GetParent();
-
-    const wxImage& img = wxGetApp().GetImage();
-    wxImage img2 = img.Rotate(frame->m_angle, wxPoint(img.GetWidth()/2, img.GetHeight()/2), FALSE);
-
-    wxBitmap bmp(img2);
-
-    wxClientDC dc (this);
-    dc.DrawBitmap (bmp, event.m_x, event.m_y, TRUE);
-}