// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#endif
#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
{
void OnQuit (wxCommandEvent &);
void OnAngle(wxCommandEvent &);
- void OnMouseLeftUp (wxMouseEvent & event);
- void OnMouseRightUp (wxMouseEvent & event);
+ void OnClear(wxCommandEvent &);
-private:
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(MyFrame, wxFrame)
- EVT_MENU (ID_Quit, MyFrame::OnQuit)
- EVT_MENU (ID_Angle, MyFrame::OnAngle)
- EVT_LEFT_UP (MyFrame::OnMouseLeftUp)
- EVT_RIGHT_UP (MyFrame::OnMouseRightUp)
-END_EVENT_TABLE()
+// ============================================================================
+// implementation
+// ============================================================================
-IMPLEMENT_APP(MyApp)
+// ----------------------------------------------------------------------------
+// application class
+// ----------------------------------------------------------------------------
+IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
- m_image = wxImage("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("Can't load the test image, please copy it to the "
- "program directory");
- return FALSE;
+ wxLogError(wxT("Can't load the test image, please copy it to the ")
+ wxT("program directory"));
+ return false;
}
- MyFrame *frame = new MyFrame ("wxWindows rotate sample",
- wxPoint(20,20), wxSize(600,450));
+ MyFrame *frame = new MyFrame (_T("wxWidgets rotate sample"),
+ wxPoint(20, 20), wxSize(600, 450));
- frame->SetBackgroundColour (wxColour (0,80,60));
- frame->Clear();
- 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.BeginDrawing();
+
+ 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);
+ }
+
+ dc.EndDrawing();
+}
+
+// ----------------------------------------------------------------------------
+// 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;
+ m_canvas = new MyCanvas(this);
+
wxMenu *menuFile = new wxMenu;
- menuFile->Append (ID_Angle, "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, "E&xit\tAlt-X");
+ menuFile->Append (ID_Quit, _T("E&xit\tAlt-X"));
wxMenuBar *menuBar = new wxMenuBar;
- menuBar->Append (menuFile, "&File");
+ menuBar->Append (menuFile, _T("&File"));
SetMenuBar (menuBar);
}
void MyFrame::OnAngle (wxCommandEvent &)
{
long degrees = (long)((180*m_angle)/M_PI);
- degrees = wxGetNumberFromUser("Change the image rotation angle",
- "Angle in degrees:",
- "wxWindows rotate sample",
+ degrees = wxGetNumberFromUser(_T("Change the image rotation angle"),
+ _T("Angle in degrees:"),
+ _T("wxWidgets rotate sample"),
degrees,
-180, +180,
this);
- m_angle = (degrees * M_PI) / 180.0;
+ if ( degrees != -1 )
+ m_angle = (degrees * M_PI) / 180.0;
}
void MyFrame::OnQuit (wxCommandEvent &)
{
- Close (TRUE);
+ Close (true);
}
-
-// Rotate with interpolation and with offset correction
-void MyFrame::OnMouseLeftUp (wxMouseEvent & event)
+void MyFrame::OnClear (wxCommandEvent &)
{
- wxPoint offset;
- const wxImage& img = wxGetApp().GetImage();
- wxImage img2 = img.Rotate(m_angle, wxPoint(img.GetWidth()/2, img.GetHeight()/2), TRUE, &offset);
-
- wxBitmap bmp = img2.ConvertToBitmap ();
-
- wxClientDC dc (this);
- dc.DrawBitmap (img2.ConvertToBitmap(), event.m_x + offset.x, event.m_y + offset.y, TRUE);
+ m_canvas->ClearImages ();
}
-// without interpolation, and without offset correction
-void MyFrame::OnMouseRightUp (wxMouseEvent & event)
-{
- const wxImage& img = wxGetApp().GetImage();
- wxImage img2 = img.Rotate(m_angle, wxPoint(img.GetWidth()/2, img.GetHeight()/2), FALSE);
-
- wxBitmap bmp = img2.ConvertToBitmap ();
-
- wxClientDC dc (this);
- dc.DrawBitmap (bmp, event.m_x, event.m_y, TRUE);
-}