home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / samples / drawing / drawing.cpp < prev    next >
C/C++ Source or Header  |  2002-12-16  |  40KB  |  1,256 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        drawing.cpp
  3. // Purpose:     shows and tests wxDC features
  4. // Author:      Robert Roebling
  5. // Modified by:
  6. // Created:     04/01/98
  7. // RCS-ID:      $Id: drawing.cpp,v 1.65.2.1 2002/12/14 18:19:45 MBN Exp $
  8. // Copyright:   (c) Robert Roebling
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #if defined(__GNUG__) && !defined(__APPLE__)
  21.     #pragma implementation "drawing.cpp"
  22.     #pragma interface "drawing.cpp"
  23. #endif
  24.  
  25. // For compilers that support precompilation, includes "wx/wx.h".
  26. #include "wx/wxprec.h"
  27.  
  28. #ifdef __BORLANDC__
  29.     #pragma hdrstop
  30. #endif
  31.  
  32. // for all others, include the necessary headers (this file is usually all you
  33. // need because it includes almost all "standard" wxWindows headers
  34. #ifndef WX_PRECOMP
  35.     #include "wx/wx.h"
  36. #endif
  37.  
  38. #include "wx/colordlg.h"
  39. #include "wx/image.h"
  40. #include "wx/artprov.h"
  41.  
  42. // ----------------------------------------------------------------------------
  43. // ressources
  44. // ----------------------------------------------------------------------------
  45.  
  46. // the application icon
  47. #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
  48.     #include "mondrian.xpm"
  49. #endif
  50.  
  51. // ----------------------------------------------------------------------------
  52. // constants
  53. // ----------------------------------------------------------------------------
  54.  
  55. // what do we show on screen (there are too many shapes to put them all on
  56. // screen simultaneously)
  57. enum ScreenToShow
  58. {
  59.     Show_Default,
  60.     Show_Text,
  61.     Show_Lines,
  62.     Show_Brushes,
  63.     Show_Polygons,
  64.     Show_Mask,
  65.     Show_Ops,
  66.     Show_Regions,
  67.     Show_Circles
  68. };
  69.  
  70. // ----------------------------------------------------------------------------
  71. // global variables
  72. // ----------------------------------------------------------------------------
  73.  
  74. static wxBitmap *gs_bmpNoMask = NULL,
  75.                 *gs_bmpWithColMask = NULL,
  76.                 *gs_bmpMask = NULL,
  77.                 *gs_bmpWithMask = NULL,
  78.                 *gs_bmp4 = NULL,
  79.                 *gs_bmp4_mono = NULL,
  80.                 *gs_bmp36 = NULL;
  81.  
  82. // ----------------------------------------------------------------------------
  83. // private classes
  84. // ----------------------------------------------------------------------------
  85.  
  86. // Define a new application type, each program should derive a class from wxApp
  87. class MyApp : public wxApp
  88. {
  89. public:
  90.     // override base class virtuals
  91.     // ----------------------------
  92.  
  93.     // this one is called on application startup and is a good place for the app
  94.     // initialization (doing it here and not in the ctor allows to have an error
  95.     // return: if OnInit() returns false, the application terminates)
  96.     virtual bool OnInit();
  97.  
  98.     virtual int OnExit() { DeleteBitmaps(); return 0; }
  99.  
  100. protected:
  101.     void DeleteBitmaps();
  102.  
  103.     bool LoadImages();
  104. };
  105.  
  106. class MyCanvas;
  107.  
  108. // Define a new frame type: this is going to be our main frame
  109. class MyFrame : public wxFrame
  110. {
  111. public:
  112.     // ctor(s)
  113.     MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
  114.  
  115.     // event handlers (these functions should _not_ be virtual)
  116.     void OnQuit(wxCommandEvent& event);
  117.     void OnAbout(wxCommandEvent& event);
  118.     void OnClip(wxCommandEvent& event);
  119.     void OnShow(wxCommandEvent &event);
  120.     void OnOption(wxCommandEvent &event);
  121.  
  122.     wxColour SelectColour();
  123.     void PrepareDC(wxDC& dc);
  124.  
  125.     int         m_backgroundMode;
  126.     int         m_textureBackground;
  127.     int         m_mapMode;
  128.     double      m_xUserScale;
  129.     double      m_yUserScale;
  130.     int         m_xLogicalOrigin;
  131.     int         m_yLogicalOrigin;
  132.     bool        m_xAxisReversed,
  133.                 m_yAxisReversed;
  134.     wxColour    m_colourForeground,    // these are _text_ colours
  135.                 m_colourBackground;
  136.     wxBrush     m_backgroundBrush;
  137.     MyCanvas   *m_canvas;
  138.  
  139. private:
  140.     // any class wishing to process wxWindows events must use this macro
  141.     DECLARE_EVENT_TABLE()
  142. };
  143.  
  144. // define a scrollable canvas for drawing onto
  145. class MyCanvas: public wxScrolledWindow
  146. {
  147. public:
  148.     MyCanvas( MyFrame *parent );
  149.  
  150.     void OnPaint(wxPaintEvent &event);
  151.     void OnMouseMove(wxMouseEvent &event);
  152.  
  153.     void Show(ScreenToShow show) { m_show = show; Refresh(); }
  154.  
  155.     // set or remove the clipping region
  156.     void Clip(bool clip) { m_clip = clip; Refresh(); }
  157.  
  158. protected:
  159.     void DrawTestLines( int x, int y, int width, wxDC &dc );
  160.     void DrawTestPoly(wxDC& dc);
  161.     void DrawTestBrushes(wxDC& dc);
  162.     void DrawText(wxDC& dc);
  163.     void DrawImages(wxDC& dc);
  164.     void DrawWithLogicalOps(wxDC& dc);
  165.     void DrawRegions(wxDC& dc);
  166.     void DrawCircles(wxDC& dc);
  167.     void DrawDefault(wxDC& dc);
  168.  
  169.     void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime);
  170.  
  171. private:
  172.     MyFrame *m_owner;
  173.  
  174.     ScreenToShow m_show;
  175.     wxBitmap     m_smile_bmp;
  176.     wxIcon       m_std_icon;
  177.     bool         m_clip;
  178.  
  179.     DECLARE_EVENT_TABLE()
  180. };
  181.  
  182. // ----------------------------------------------------------------------------
  183. // constants
  184. // ----------------------------------------------------------------------------
  185.  
  186. // IDs for the controls and the menu commands
  187. enum
  188. {
  189.     // menu items
  190.     File_Quit = 1,
  191.     File_About,
  192.  
  193.     MenuShow_First,
  194.     File_ShowDefault = MenuShow_First,
  195.     File_ShowText,
  196.     File_ShowLines,
  197.     File_ShowBrushes,
  198.     File_ShowPolygons,
  199.     File_ShowMask,
  200.     File_ShowOps,
  201.     File_ShowRegions,
  202.     File_ShowCircles,
  203.     MenuShow_Last = File_ShowCircles,
  204.  
  205.     File_Clip,
  206.  
  207.     MenuOption_First,
  208.  
  209.     MapMode_Text = MenuOption_First,
  210.     MapMode_Lometric,
  211.     MapMode_Twips,
  212.     MapMode_Points,
  213.     MapMode_Metric,
  214.  
  215.     UserScale_StretchHoriz,
  216.     UserScale_ShrinkHoriz,
  217.     UserScale_StretchVertic,
  218.     UserScale_ShrinkVertic,
  219.     UserScale_Restore,
  220.  
  221.     AxisMirror_Horiz,
  222.     AxisMirror_Vertic,
  223.  
  224.     LogicalOrigin_MoveDown,
  225.     LogicalOrigin_MoveUp,
  226.     LogicalOrigin_MoveLeft,
  227.     LogicalOrigin_MoveRight,
  228.     LogicalOrigin_Set,
  229.     LogicalOrigin_Restore,
  230.  
  231.     Colour_TextForeground,
  232.     Colour_TextBackground,
  233.     Colour_Background,
  234.     Colour_BackgroundMode,
  235.     Colour_TextureBackgound,
  236.  
  237.     MenuOption_Last = Colour_TextureBackgound
  238. };
  239.  
  240. // ----------------------------------------------------------------------------
  241. // event tables and other macros for wxWindows
  242. // ----------------------------------------------------------------------------
  243.  
  244.  
  245. // Create a new application object: this macro will allow wxWindows to create
  246. // the application object during program execution (it's better than using a
  247. // static object for many reasons) and also declares the accessor function
  248. // wxGetApp() which will return the reference of the right type (i.e. MyApp and
  249. // not wxApp)
  250. IMPLEMENT_APP(MyApp)
  251.  
  252. // ============================================================================
  253. // implementation
  254. // ============================================================================
  255.  
  256. // ----------------------------------------------------------------------------
  257. // the application class
  258. // ----------------------------------------------------------------------------
  259.  
  260. bool MyApp::LoadImages()
  261. {
  262.     gs_bmpNoMask = new wxBitmap;
  263.     gs_bmpWithColMask = new wxBitmap;
  264.     gs_bmpMask = new wxBitmap;
  265.     gs_bmpWithMask = new wxBitmap;
  266.     gs_bmp4 = new wxBitmap;
  267.     gs_bmp4_mono = new wxBitmap;
  268.     gs_bmp36 = new wxBitmap;
  269.  
  270.     wxPathList pathList;
  271.     pathList.Add(_T("."));
  272.     pathList.Add(_T(".."));
  273.  
  274.     wxString path = pathList.FindValidPath(_T("pat4.bmp"));
  275.     if ( !path )
  276.         return FALSE;
  277.  
  278.     /* 4 colour bitmap */
  279.     gs_bmp4->LoadFile(path, wxBITMAP_TYPE_BMP);
  280.     /* turn into mono-bitmap */
  281.     gs_bmp4_mono->LoadFile(path, wxBITMAP_TYPE_BMP);
  282.     wxMask* mask4 = new wxMask(*gs_bmp4_mono, *wxBLACK);
  283.     gs_bmp4_mono->SetMask(mask4);
  284.  
  285.     path = pathList.FindValidPath(_T("pat36.bmp"));
  286.     if ( !path )
  287.         return FALSE;
  288.     gs_bmp36->LoadFile(path, wxBITMAP_TYPE_BMP);
  289.     wxMask* mask36 = new wxMask(*gs_bmp36, *wxBLACK);
  290.     gs_bmp36->SetMask(mask36);
  291.  
  292.     path = pathList.FindValidPath(_T("image.bmp"));
  293.     if ( !path )
  294.         return FALSE;
  295.     gs_bmpNoMask->LoadFile(path, wxBITMAP_TYPE_BMP);
  296.     gs_bmpWithMask->LoadFile(path, wxBITMAP_TYPE_BMP);
  297.     gs_bmpWithColMask->LoadFile(path, wxBITMAP_TYPE_BMP);
  298.  
  299.     path = pathList.FindValidPath(_T("mask.bmp"));
  300.     if ( !path )
  301.         return FALSE;
  302.     gs_bmpMask->LoadFile(path, wxBITMAP_TYPE_BMP);
  303.  
  304.     wxMask *mask = new wxMask(*gs_bmpMask, *wxBLACK);
  305.     gs_bmpWithMask->SetMask(mask);
  306.  
  307.     mask = new wxMask(*gs_bmpWithColMask, *wxWHITE);
  308.     gs_bmpWithColMask->SetMask(mask);
  309.  
  310.     return TRUE;
  311. }
  312.  
  313. // `Main program' equivalent: the program execution "starts" here
  314. bool MyApp::OnInit()
  315. {
  316.     // Create the main application window
  317.     MyFrame *frame = new MyFrame(_T("Drawing sample"),
  318.                                  wxPoint(50, 50), wxSize(550, 340));
  319.  
  320.     // Show it and tell the application that it's our main window
  321.     frame->Show(TRUE);
  322.     SetTopWindow(frame);
  323.  
  324.     if ( !LoadImages() )
  325.     {
  326.         wxLogError(wxT("Can't load one of the bitmap files needed ")
  327.                    wxT("for this sample from the current or parent ")
  328.                    wxT("directory, please copy them there."));
  329.  
  330.         // stop here
  331.         DeleteBitmaps();
  332.  
  333.         return FALSE;
  334.     }
  335.  
  336.     // ok, continue
  337.     return TRUE;
  338. }
  339.  
  340. void MyApp::DeleteBitmaps()
  341. {
  342.     delete gs_bmpNoMask;
  343.     delete gs_bmpWithColMask;
  344.     delete gs_bmpMask;
  345.     delete gs_bmpWithMask;
  346.     delete gs_bmp4;
  347.     delete gs_bmp4_mono;
  348.     delete gs_bmp36;
  349.  
  350.     gs_bmpNoMask = NULL;
  351.     gs_bmpWithColMask = NULL;
  352.     gs_bmpMask = NULL;
  353.     gs_bmpWithMask = NULL;
  354.     gs_bmp4 = NULL;
  355.     gs_bmp4_mono = NULL;
  356.     gs_bmp36 = NULL;
  357. }
  358.  
  359. // ----------------------------------------------------------------------------
  360. // MyCanvas
  361. // ----------------------------------------------------------------------------
  362.  
  363. // the event tables connect the wxWindows events with the functions (event
  364. // handlers) which process them.
  365. BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
  366.     EVT_PAINT  (MyCanvas::OnPaint)
  367.     EVT_MOTION (MyCanvas::OnMouseMove)
  368. END_EVENT_TABLE()
  369.  
  370. #include "smile.xpm"
  371.  
  372. MyCanvas::MyCanvas(MyFrame *parent)
  373.         : wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize,
  374.                            wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
  375. {
  376.     m_owner = parent;
  377.     m_show = Show_Default;
  378.     m_smile_bmp = wxBitmap(smile_xpm);
  379.     m_std_icon = wxArtProvider::GetIcon(wxART_INFORMATION);
  380.     m_clip = FALSE;
  381. }
  382.  
  383. void MyCanvas::DrawTestBrushes(wxDC& dc)
  384. {
  385.     static const wxCoord WIDTH = 200;
  386.     static const wxCoord HEIGHT = 80;
  387.  
  388.     wxCoord x = 10,
  389.             y = 10;
  390.  
  391.     dc.SetBrush(wxBrush(*wxGREEN, wxSOLID));
  392.     dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  393.     dc.DrawText(_T("Solid green"), x + 10, y + 10);
  394.  
  395.     y += HEIGHT;
  396.     dc.SetBrush(wxBrush(*wxRED, wxCROSSDIAG_HATCH));
  397.     dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  398.     dc.DrawText(_T("Hatched red"), x + 10, y + 10);
  399.  
  400.     y += HEIGHT;
  401.     dc.SetBrush(wxBrush(*gs_bmpMask));
  402.     dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  403.     dc.DrawText(_T("Stipple mono"), x + 10, y + 10);
  404.  
  405.     y += HEIGHT;
  406.     dc.SetBrush(wxBrush(*gs_bmpNoMask));
  407.     dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  408.     dc.DrawText(_T("Stipple colour"), x + 10, y + 10);
  409. }
  410.  
  411. void MyCanvas::DrawTestPoly(wxDC& dc)
  412. {
  413.     wxBrush brushHatch(*wxRED, wxFDIAGONAL_HATCH);
  414.     dc.SetBrush(brushHatch);
  415.  
  416.     wxPoint star[5];
  417.     star[0] = wxPoint(100, 60);
  418.     star[1] = wxPoint(60, 150);
  419.     star[2] = wxPoint(160, 100);
  420.     star[3] = wxPoint(40, 100);
  421.     star[4] = wxPoint(140, 150);
  422.  
  423.     dc.DrawText(_T("You should see two (irregular) stars below, the left one ")
  424.                 _T("hatched"), 10, 10);
  425.     dc.DrawText(_T("except for the central region and the right ")
  426.                 _T("one entirely hatched"), 10, 30);
  427.  
  428.     dc.DrawPolygon(WXSIZEOF(star), star);
  429.     dc.DrawPolygon(WXSIZEOF(star), star, 160, 0, wxWINDING_RULE);
  430. }
  431.  
  432. void MyCanvas::DrawTestLines( int x, int y, int width, wxDC &dc )
  433. {
  434.     dc.SetPen( wxPen( wxT("black"), width, wxSOLID) );
  435.     dc.SetBrush( *wxRED_BRUSH );
  436.     dc.DrawText(wxString::Format(wxT("Testing lines of width %d"), width), x + 10, y - 10);
  437.     dc.DrawRectangle( x+10, y+10, 100, 190 );
  438.  
  439.     dc.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x + 150, y + 10);
  440.     dc.SetPen( wxPen( wxT("black"), width, wxSOLID) );
  441.     dc.DrawLine( x+20, y+20, 100, y+20 );
  442.     dc.SetPen( wxPen( wxT("black"), width, wxDOT) );
  443.     dc.DrawLine( x+20, y+30, 100, y+30 );
  444.     dc.SetPen( wxPen( wxT("black"), width, wxSHORT_DASH) );
  445.     dc.DrawLine( x+20, y+40, 100, y+40 );
  446.     dc.SetPen( wxPen( wxT("black"), width, wxLONG_DASH) );
  447.     dc.DrawLine( x+20, y+50, 100, y+50 );
  448.     dc.SetPen( wxPen( wxT("black"), width, wxDOT_DASH) );
  449.     dc.DrawLine( x+20, y+60, 100, y+60 );
  450.  
  451.     dc.DrawText(_T("Misc hatches"), x + 150, y + 70);
  452.     dc.SetPen( wxPen( wxT("black"), width, wxBDIAGONAL_HATCH) );
  453.     dc.DrawLine( x+20, y+70, 100, y+70 );
  454.     dc.SetPen( wxPen( wxT("black"), width, wxCROSSDIAG_HATCH) );
  455.     dc.DrawLine( x+20, y+80, 100, y+80 );
  456.     dc.SetPen( wxPen( wxT("black"), width, wxFDIAGONAL_HATCH) );
  457.     dc.DrawLine( x+20, y+90, 100, y+90 );
  458.     dc.SetPen( wxPen( wxT("black"), width, wxCROSS_HATCH) );
  459.     dc.DrawLine( x+20, y+100, 100, y+100 );
  460.     dc.SetPen( wxPen( wxT("black"), width, wxHORIZONTAL_HATCH) );
  461.     dc.DrawLine( x+20, y+110, 100, y+110 );
  462.     dc.SetPen( wxPen( wxT("black"), width, wxVERTICAL_HATCH) );
  463.     dc.DrawLine( x+20, y+120, 100, y+120 );
  464.  
  465.     dc.DrawText(_T("User dash"), x + 150, y + 140);
  466.     wxPen ud( wxT("black"), width, wxUSER_DASH );
  467.     wxDash dash1[1];
  468.     dash1[0] = 0;
  469.     ud.SetDashes( 1, dash1 );
  470.     dc.DrawLine( x+20, y+140, 100, y+140 );
  471.     dash1[0] = 1;
  472.     ud.SetDashes( 1, dash1 );
  473.     dc.DrawLine( x+20, y+150, 100, y+150 );
  474.     dash1[0] = 2;
  475.     ud.SetDashes( 1, dash1 );
  476.     dc.DrawLine( x+20, y+160, 100, y+160 );
  477.     dash1[0] = 0x7F;
  478.     ud.SetDashes( 1, dash1 );
  479.     dc.DrawLine( x+20, y+170, 100, y+170 );
  480. }
  481.  
  482. void MyCanvas::DrawDefault(wxDC& dc)
  483. {
  484.     // mark the origin
  485.     dc.DrawCircle(0, 0, 10);
  486.  
  487.     //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
  488.     dc.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID));
  489.     wxColour tmpColour ;
  490.     dc.GetPixel(1,1, &tmpColour);
  491.     dc.FloodFill(1,1, tmpColour, wxFLOOD_SURFACE);
  492.  
  493.     dc.DrawCheckMark(5, 80, 15, 15);
  494.     dc.DrawCheckMark(25, 80, 30, 30);
  495.     dc.DrawCheckMark(60, 80, 60, 60);
  496.  
  497.     // this is the test for "blitting bitmap into DC damages selected brush" bug
  498.     wxCoord rectSize = m_std_icon.GetWidth() + 10;
  499.     wxCoord x = 100;
  500.     dc.SetPen(*wxTRANSPARENT_PEN);
  501.     dc.SetBrush( *wxGREEN_BRUSH );
  502.     dc.DrawRectangle(x, 10, rectSize, rectSize);
  503.     dc.DrawBitmap(m_std_icon, x + 5, 15, TRUE);
  504.     x += rectSize + 10;
  505.     dc.DrawRectangle(x, 10, rectSize, rectSize);
  506.     dc.DrawIcon(m_std_icon, x + 5, 15);
  507.     x += rectSize + 10;
  508.     dc.DrawRectangle(x, 10, rectSize, rectSize);
  509.  
  510.     // test for "transparent" bitmap drawing (it intersects with the last
  511.     // rectangle above)
  512.     //dc.SetBrush( *wxTRANSPARENT_BRUSH );
  513.  
  514.     if (m_smile_bmp.Ok())
  515.         dc.DrawBitmap(m_smile_bmp, x + rectSize - 20, rectSize - 10, TRUE);
  516.  
  517.     dc.SetBrush( *wxBLACK_BRUSH );
  518.     dc.DrawRectangle( 0, 160, 1000, 300 );
  519.  
  520.     // draw lines
  521.     wxBitmap bitmap(20,70);
  522.     wxMemoryDC memdc;
  523.     memdc.SelectObject( bitmap );
  524.     memdc.SetBrush( *wxBLACK_BRUSH );
  525.     memdc.SetPen( *wxWHITE_PEN );
  526.     memdc.DrawRectangle(0,0,20,70);
  527.     memdc.DrawLine( 10,0,10,70 );
  528.  
  529.     // to the right
  530.     wxPen pen = *wxRED_PEN;
  531.     memdc.SetPen(pen);
  532.     memdc.DrawLine( 10, 5,10, 5 );
  533.     memdc.DrawLine( 10,10,11,10 );
  534.     memdc.DrawLine( 10,15,12,15 );
  535.     memdc.DrawLine( 10,20,13,20 );
  536.  
  537. /*
  538.     memdc.SetPen(*wxRED_PEN);
  539.     memdc.DrawLine( 12, 5,12, 5 );
  540.     memdc.DrawLine( 12,10,13,10 );
  541.     memdc.DrawLine( 12,15,14,15 );
  542.     memdc.DrawLine( 12,20,15,20 );
  543. */
  544.  
  545.     // same to the left
  546.     memdc.DrawLine( 10,25,10,25 );
  547.     memdc.DrawLine( 10,30, 9,30 );
  548.     memdc.DrawLine( 10,35, 8,35 );
  549.     memdc.DrawLine( 10,40, 7,40 );
  550.  
  551.     // XOR draw lines
  552.     dc.SetPen(*wxWHITE_PEN);
  553.     memdc.SetLogicalFunction( wxINVERT );
  554.     memdc.SetPen( *wxWHITE_PEN );
  555.     memdc.DrawLine( 10,50,10,50 );
  556.     memdc.DrawLine( 10,55,11,55 );
  557.     memdc.DrawLine( 10,60,12,60 );
  558.     memdc.DrawLine( 10,65,13,65 );
  559.  
  560.     memdc.DrawLine( 12,50,12,50 );
  561.     memdc.DrawLine( 12,55,13,55 );
  562.     memdc.DrawLine( 12,60,14,60 );
  563.     memdc.DrawLine( 12,65,15,65 );
  564.  
  565.     memdc.SelectObject( wxNullBitmap );
  566.     dc.DrawBitmap( bitmap, 10, 170 );
  567.     wxImage image = bitmap.ConvertToImage();
  568.     image.Rescale( 60,210 );
  569.     bitmap = wxBitmap(image);
  570.     dc.DrawBitmap( bitmap, 50, 170 );
  571.  
  572.     // test the rectangle outline drawing - there should be one pixel between
  573.     // the rect and the lines
  574.     dc.SetPen(*wxWHITE_PEN);
  575.     dc.SetBrush( *wxTRANSPARENT_BRUSH );
  576.     dc.DrawRectangle(150, 170, 49, 29);
  577.     dc.DrawRectangle(200, 170, 49, 29);
  578.     dc.SetPen(*wxWHITE_PEN);
  579.     dc.DrawLine(250, 210, 250, 170);
  580.     dc.DrawLine(260, 200, 150, 200);
  581.  
  582.     // test the rectangle filled drawing - there should be one pixel between
  583.     // the rect and the lines
  584.     dc.SetPen(*wxTRANSPARENT_PEN);
  585.     dc.SetBrush( *wxWHITE_BRUSH );
  586.     dc.DrawRectangle(300, 170, 49, 29);
  587.     dc.DrawRectangle(350, 170, 49, 29);
  588.     dc.SetPen(*wxWHITE_PEN);
  589.     dc.DrawLine(400, 170, 400, 210);
  590.     dc.DrawLine(300, 200, 410, 200);
  591.  
  592.     // a few more tests of this kind
  593.     dc.SetPen(*wxRED_PEN);
  594.     dc.SetBrush( *wxWHITE_BRUSH );
  595.     dc.DrawRectangle(300, 220, 1, 1);
  596.     dc.DrawRectangle(310, 220, 2, 2);
  597.     dc.DrawRectangle(320, 220, 3, 3);
  598.     dc.DrawRectangle(330, 220, 4, 4);
  599.  
  600.     dc.SetPen(*wxTRANSPARENT_PEN);
  601.     dc.SetBrush( *wxWHITE_BRUSH );
  602.     dc.DrawRectangle(300, 230, 1, 1);
  603.     dc.DrawRectangle(310, 230, 2, 2);
  604.     dc.DrawRectangle(320, 230, 3, 3);
  605.     dc.DrawRectangle(330, 230, 4, 4);
  606.  
  607.     // and now for filled rect with outline
  608.     dc.SetPen(*wxRED_PEN);
  609.     dc.SetBrush( *wxWHITE_BRUSH );
  610.     dc.DrawRectangle(500, 170, 49, 29);
  611.     dc.DrawRectangle(550, 170, 49, 29);
  612.     dc.SetPen(*wxWHITE_PEN);
  613.     dc.DrawLine(600, 170, 600, 210);
  614.     dc.DrawLine(500, 200, 610, 200);
  615.  
  616.     // test the rectangle outline drawing - there should be one pixel between
  617.     // the rect and the lines
  618.     dc.SetPen(*wxWHITE_PEN);
  619.     dc.SetBrush( *wxTRANSPARENT_BRUSH );
  620.     dc.DrawRoundedRectangle(150, 270, 49, 29, 6);
  621.     dc.DrawRoundedRectangle(200, 270, 49, 29, 6);
  622.     dc.SetPen(*wxWHITE_PEN);
  623.     dc.DrawLine(250, 270, 250, 310);
  624.     dc.DrawLine(150, 300, 260, 300);
  625.  
  626.     // test the rectangle filled drawing - there should be one pixel between
  627.     // the rect and the lines
  628.     dc.SetPen(*wxTRANSPARENT_PEN);
  629.     dc.SetBrush( *wxWHITE_BRUSH );
  630.     dc.DrawRoundedRectangle(300, 270, 49, 29, 6);
  631.     dc.DrawRoundedRectangle(350, 270, 49, 29, 6);
  632.     dc.SetPen(*wxWHITE_PEN);
  633.     dc.DrawLine(400, 270, 400, 310);
  634.     dc.DrawLine(300, 300, 410, 300);
  635.  
  636.     // Added by JACS to demonstrate bizarre behaviour.
  637.     // With a size of 70, we get a missing red RHS,
  638.     // and the hight is too small, so we get yellow
  639.     // showing. With a size of 40, it draws as expected:
  640.     // it just shows a white rectangle with red outline.
  641.     int totalWidth = 70;
  642.     int totalHeight = 70;
  643.     wxBitmap bitmap2(totalWidth, totalHeight);
  644.  
  645.     wxMemoryDC memdc2;
  646.     memdc2.SelectObject(bitmap2);
  647.  
  648.     wxBrush yellowBrush(wxColour(255, 255, 0), wxSOLID);
  649.     memdc2.SetBackground(yellowBrush);
  650.     memdc2.Clear();
  651.  
  652.     wxPen yellowPen(wxColour(255, 255, 0), 1, wxSOLID);
  653.  
  654.     // Now draw a white rectangle with red outline. It should
  655.     // entirely eclipse the yellow background.
  656.     memdc2.SetPen(*wxRED_PEN);
  657.     memdc2.SetBrush(*wxWHITE_BRUSH);
  658.  
  659.     memdc2.DrawRectangle(0, 0, totalWidth, totalHeight);
  660.  
  661.     memdc2.SetPen(wxNullPen);
  662.     memdc2.SetBrush(wxNullBrush);
  663.     memdc2.SelectObject(wxNullBitmap);
  664.  
  665.     dc.DrawBitmap(bitmap2, 500, 270);
  666.  
  667.     // Repeat, but draw directly on dc
  668.     // Draw a yellow rectangle filling the bitmap
  669.  
  670.     x = 600; int y = 270;
  671.     dc.SetPen(yellowPen);
  672.     dc.SetBrush(yellowBrush);
  673.     dc.DrawRectangle(x, y, totalWidth, totalHeight);
  674.  
  675.     // Now draw a white rectangle with red outline. It should
  676.     // entirely eclipse the yellow background.
  677.     dc.SetPen(*wxRED_PEN);
  678.     dc.SetBrush(*wxWHITE_BRUSH);
  679.  
  680.     dc.DrawRectangle(x, y, totalWidth, totalHeight);
  681. }
  682.  
  683. void MyCanvas::DrawText(wxDC& dc)
  684. {
  685.     // set underlined font for testing
  686.     dc.SetFont( wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, TRUE) );
  687.     dc.DrawText( _T("This is text"), 110, 10 );
  688.     dc.DrawRotatedText( _T("That is text"), 20, 10, -45 );
  689.  
  690.     // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
  691.     // under Win9x (it is not TrueType)
  692.     dc.SetFont( *wxSWISS_FONT );
  693.  
  694.     wxString text;
  695.     dc.SetBackgroundMode(wxTRANSPARENT);
  696.  
  697.     for ( int n = -180; n < 180; n += 30 )
  698.     {
  699.         text.Printf(wxT("     %d rotated text"), n);
  700.         dc.DrawRotatedText(text , 400, 400, n);
  701.     }
  702.  
  703.     dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
  704.  
  705.     dc.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
  706.  
  707.     long length;
  708.     long height;
  709.     long descent;
  710.     dc.GetTextExtent( _T("This is Swiss 18pt text."), &length, &height, &descent );
  711.     text.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length, height, descent );
  712.     dc.DrawText( text, 110, 80 );
  713.  
  714.     text.Printf( wxT("CharHeight() returns: %d"), dc.GetCharHeight() );
  715.     dc.DrawText( text, 110, 120 );
  716.  
  717.     dc.DrawRectangle( 100, 40, 4, height );
  718.  
  719.     // test the logical function effect
  720.     wxCoord y = 150;
  721.     dc.SetLogicalFunction(wxINVERT);
  722.     dc.DrawText( _T("There should be no text below"), 110, 150 );
  723.     dc.DrawRectangle( 110, y, 100, height );
  724.  
  725.     // twice drawn inverted should result in invisible
  726.     y += height;
  727.     dc.DrawText( _T("Invisible text"), 110, y );
  728.     dc.DrawRectangle( 110, y, 100, height );
  729.     dc.DrawText( _T("Invisible text"), 110, y );
  730.     dc.DrawRectangle( 110, y, 100, height );
  731.     dc.SetLogicalFunction(wxCOPY);
  732.  
  733.     y += height;
  734.     dc.DrawRectangle( 110, y, 100, height );
  735.     dc.DrawText( _T("Visible text"), 110, y );
  736. }
  737.  
  738. static const struct
  739. {
  740.     const wxChar *name;
  741.     int           rop;
  742. } rasterOperations[] =
  743. {
  744.     { wxT("wxAND"),          wxAND           },
  745.     { wxT("wxAND_INVERT"),   wxAND_INVERT    },
  746.     { wxT("wxAND_REVERSE"),  wxAND_REVERSE   },
  747.     { wxT("wxCLEAR"),        wxCLEAR         },
  748.     { wxT("wxCOPY"),         wxCOPY          },
  749.     { wxT("wxEQUIV"),        wxEQUIV         },
  750.     { wxT("wxINVERT"),       wxINVERT        },
  751.     { wxT("wxNAND"),         wxNAND          },
  752.     { wxT("wxNO_OP"),        wxNO_OP         },
  753.     { wxT("wxOR"),           wxOR            },
  754.     { wxT("wxOR_INVERT"),    wxOR_INVERT     },
  755.     { wxT("wxOR_REVERSE"),   wxOR_REVERSE    },
  756.     { wxT("wxSET"),          wxSET           },
  757.     { wxT("wxSRC_INVERT"),   wxSRC_INVERT    },
  758.     { wxT("wxXOR"),          wxXOR           },
  759. };
  760.  
  761. void MyCanvas::DrawImages(wxDC& dc)
  762. {
  763.     dc.DrawText(_T("original image"), 0, 0);
  764.     dc.DrawBitmap(*gs_bmpNoMask, 0, 20, 0);
  765.     dc.DrawText(_T("with colour mask"), 0, 100);
  766.     dc.DrawBitmap(*gs_bmpWithColMask, 0, 120, TRUE);
  767.     dc.DrawText(_T("the mask image"), 0, 200);
  768.     dc.DrawBitmap(*gs_bmpMask, 0, 220, 0);
  769.     dc.DrawText(_T("masked image"), 0, 300);
  770.     dc.DrawBitmap(*gs_bmpWithMask, 0, 320, TRUE);
  771.  
  772.     int cx = gs_bmpWithColMask->GetWidth(),
  773.         cy = gs_bmpWithColMask->GetHeight();
  774.  
  775.     wxMemoryDC memDC;
  776.     for ( size_t n = 0; n < WXSIZEOF(rasterOperations); n++ )
  777.     {
  778.         wxCoord x = 120 + 150*(n%4),
  779.                 y =  20 + 100*(n/4);
  780.  
  781.         dc.DrawText(rasterOperations[n].name, x, y - 20);
  782.         memDC.SelectObject(*gs_bmpWithColMask);
  783.         dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, TRUE);
  784.     }
  785. }
  786.  
  787. void MyCanvas::DrawWithLogicalOps(wxDC& dc)
  788. {
  789.     static const wxCoord w = 60;
  790.     static const wxCoord h = 60;
  791.  
  792.     // reuse the text colour here
  793.     dc.SetPen(wxPen(m_owner->m_colourForeground, 1, wxSOLID));
  794.     dc.SetBrush(*wxTRANSPARENT_BRUSH);
  795.  
  796.     size_t n;
  797.     for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
  798.     {
  799.         wxCoord x = 20 + 150*(n%4),
  800.                 y = 20 + 100*(n/4);
  801.  
  802.         dc.DrawText(rasterOperations[n].name, x, y - 20);
  803.         dc.SetLogicalFunction(rasterOperations[n].rop);
  804.         dc.DrawRectangle(x, y, w, h);
  805.         dc.DrawLine(x, y, x + w, y + h);
  806.         dc.DrawLine(x + w, y, x, y + h);
  807.     }
  808.  
  809.     // now some filled rectangles
  810.     dc.SetBrush(wxBrush(m_owner->m_colourForeground, wxSOLID));
  811.  
  812.     for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
  813.     {
  814.         wxCoord x = 20 + 150*(n%4),
  815.                 y = 500 + 100*(n/4);
  816.  
  817.         dc.DrawText(rasterOperations[n].name, x, y - 20);
  818.         dc.SetLogicalFunction(rasterOperations[n].rop);
  819.         dc.DrawRectangle(x, y, w, h);
  820.     }
  821. }
  822.  
  823. void MyCanvas::DrawCircles(wxDC& dc)
  824. {
  825.     int x = 100,
  826.         y = 100,
  827.         r = 20;
  828.  
  829.     dc.DrawText(_T("Some circles"), 0, y);
  830.     dc.DrawCircle(x, y, r);
  831.     dc.DrawCircle(x + 2*r, y, r);
  832.     dc.DrawCircle(x + 4*r, y, r);
  833.  
  834.     y += 2*r;
  835.     dc.DrawText(_T("And ellipses"), 0, y);
  836.     dc.DrawEllipse(x - r, y, 2*r, r);
  837.     dc.DrawEllipse(x + r, y, 2*r, r);
  838.     dc.DrawEllipse(x + 3*r, y, 2*r, r);
  839.  
  840.     y += 2*r;
  841.     dc.DrawText(_T("And arcs"), 0, y);
  842.     dc.DrawArc(x - r, y, x + r, y, x, y);
  843.     dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
  844.     dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
  845.  
  846.     y += 2*r;
  847.     dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
  848.     dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
  849.     dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
  850.     dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
  851. }
  852.  
  853. void MyCanvas::DrawRegions(wxDC& dc)
  854. {
  855.     dc.DrawText(_T("You should see a red rect partly covered by a cyan one ")
  856.                 _T("on the left"), 10, 5);
  857.     dc.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
  858.                 10, 5 + dc.GetCharHeight());
  859.     dc.DrawText(_T("The second copy should be identical but right part of it ")
  860.                 _T("should be offset by 10 pixels."),
  861.                 10, 5 + 2*dc.GetCharHeight());
  862.  
  863.     DrawRegionsHelper(dc, 10, TRUE);
  864.     DrawRegionsHelper(dc, 350, FALSE);
  865. }
  866.  
  867. void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime)
  868. {
  869.     wxCoord y = 100;
  870.  
  871.     dc.DestroyClippingRegion();
  872.     dc.SetBrush( *wxWHITE_BRUSH );
  873.     dc.SetPen( *wxTRANSPARENT_PEN );
  874.     dc.DrawRectangle( x, y, 310, 310 );
  875.  
  876.     dc.SetClippingRegion( x + 10, y + 10, 100, 270 );
  877.  
  878.     dc.SetBrush( *wxRED_BRUSH );
  879.     dc.DrawRectangle( x, y, 310, 310 );
  880.  
  881.     dc.SetClippingRegion( x + 10, y + 10, 100, 100 );
  882.  
  883.     dc.SetBrush( *wxCYAN_BRUSH );
  884.     dc.DrawRectangle( x, y, 310, 310 );
  885.  
  886.     dc.DestroyClippingRegion();
  887.  
  888.     wxRegion region(x + 110, y + 20, 100, 270);
  889. #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
  890.     if ( !firstTime )
  891.         region.Offset(10, 10);
  892. #endif
  893.     dc.SetClippingRegion(region);
  894.  
  895.     dc.SetBrush( *wxGREY_BRUSH );
  896.     dc.DrawRectangle( x, y, 310, 310 );
  897.  
  898.     if (m_smile_bmp.Ok())
  899.     {
  900.         dc.DrawBitmap( m_smile_bmp, x + 150, y + 150, TRUE );
  901.         dc.DrawBitmap( m_smile_bmp, x + 130, y + 10,  TRUE );
  902.         dc.DrawBitmap( m_smile_bmp, x + 130, y + 280, TRUE );
  903.         dc.DrawBitmap( m_smile_bmp, x + 100, y + 70,  TRUE );
  904.         dc.DrawBitmap( m_smile_bmp, x + 200, y + 70,  TRUE );
  905.     }
  906. }
  907.  
  908. void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
  909. {
  910.     wxPaintDC dc(this);
  911.     PrepareDC(dc);
  912.  
  913.     m_owner->PrepareDC(dc);
  914.  
  915.     dc.SetBackgroundMode( m_owner->m_backgroundMode );
  916.     if ( m_owner->m_backgroundBrush.Ok() )
  917.         dc.SetBackground( m_owner->m_backgroundBrush );
  918.     if ( m_owner->m_colourForeground.Ok() )
  919.         dc.SetTextForeground( m_owner->m_colourForeground );
  920.     if ( m_owner->m_colourBackground.Ok() )
  921.         dc.SetTextBackground( m_owner->m_colourBackground );
  922.  
  923.     if ( m_owner->m_textureBackground) {
  924.         if ( ! m_owner->m_backgroundBrush.Ok() ) {
  925.             wxBrush b(wxColour(0,128,0), wxSOLID);
  926.             dc.SetBackground(b);
  927.         }
  928.     }
  929.  
  930.     if ( m_clip )
  931.         dc.SetClippingRegion(100, 100, 100, 100);
  932.  
  933.     dc.Clear();
  934.  
  935.     if ( m_owner->m_textureBackground )
  936.     {
  937.         dc.SetPen(*wxMEDIUM_GREY_PEN);
  938.         for ( int i = 0; i < 200; i++ )
  939.             dc.DrawLine(0, i*10, i*10, 0);
  940.     }
  941.  
  942.     switch ( m_show )
  943.     {
  944.         case Show_Default:
  945.             DrawDefault(dc);
  946.             break;
  947.  
  948.         case Show_Circles:
  949.             DrawCircles(dc);
  950.             break;
  951.  
  952.         case Show_Regions:
  953.             DrawRegions(dc);
  954.             break;
  955.  
  956.         case Show_Text:
  957.             DrawText(dc);
  958.             break;
  959.  
  960.         case Show_Lines:
  961.             DrawTestLines( 0, 100, 0, dc );
  962.             DrawTestLines( 0, 320, 1, dc );
  963.             DrawTestLines( 0, 540, 2, dc );
  964.             DrawTestLines( 0, 760, 6, dc );
  965.             break;
  966.  
  967.         case Show_Brushes:
  968.             DrawTestBrushes(dc);
  969.             break;
  970.  
  971.         case Show_Polygons:
  972.             DrawTestPoly(dc);
  973.             break;
  974.  
  975.         case Show_Mask:
  976.             DrawImages(dc);
  977.             break;
  978.  
  979.         case Show_Ops:
  980.             DrawWithLogicalOps(dc);
  981.             break;
  982.     }
  983. }
  984.  
  985. void MyCanvas::OnMouseMove(wxMouseEvent &event)
  986. {
  987.     wxClientDC dc(this);
  988.     PrepareDC(dc);
  989.     m_owner->PrepareDC(dc);
  990.  
  991.     wxPoint pos = event.GetPosition();
  992.     long x = dc.DeviceToLogicalX( pos.x );
  993.     long y = dc.DeviceToLogicalY( pos.y );
  994.     wxString str;
  995.     str.Printf( wxT("Current mouse position: %d,%d"), (int)x, (int)y );
  996.     m_owner->SetStatusText( str );
  997. }
  998.  
  999. // ----------------------------------------------------------------------------
  1000. // MyFrame
  1001. // ----------------------------------------------------------------------------
  1002.  
  1003. // the event tables connect the wxWindows events with the functions (event
  1004. // handlers) which process them. It can be also done at run-time, but for the
  1005. // simple menu events like this the static method is much simpler.
  1006. BEGIN_EVENT_TABLE(MyFrame, wxFrame)
  1007.     EVT_MENU      (File_Quit,     MyFrame::OnQuit)
  1008.     EVT_MENU      (File_About,    MyFrame::OnAbout)
  1009.     EVT_MENU      (File_Clip,     MyFrame::OnClip)
  1010.  
  1011.     EVT_MENU_RANGE(MenuShow_First,   MenuShow_Last,   MyFrame::OnShow)
  1012.  
  1013.     EVT_MENU_RANGE(MenuOption_First, MenuOption_Last, MyFrame::OnOption)
  1014. END_EVENT_TABLE()
  1015.  
  1016. // frame constructor
  1017. MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
  1018.        : wxFrame((wxFrame *)NULL, -1, title, pos, size,
  1019.                  wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
  1020. {
  1021.     // set the frame icon
  1022.     SetIcon(wxICON(mondrian));
  1023.  
  1024.     wxMenu *menuFile = new wxMenu;
  1025.     menuFile->Append(File_ShowDefault, _T("&Default screen\tF1"));
  1026.     menuFile->Append(File_ShowText, _T("&Text screen\tF2"));
  1027.     menuFile->Append(File_ShowLines, _T("&Lines screen\tF3"));
  1028.     menuFile->Append(File_ShowBrushes, _T("&Brushes screen\tF4"));
  1029.     menuFile->Append(File_ShowPolygons, _T("&Polygons screen\tF5"));
  1030.     menuFile->Append(File_ShowMask, _T("&Mask screen\tF6"));
  1031.     menuFile->Append(File_ShowOps, _T("&ROP screen\tF7"));
  1032.     menuFile->Append(File_ShowRegions, _T("Re&gions screen\tF8"));
  1033.     menuFile->Append(File_ShowCircles, _T("&Circles screen\tF9"));
  1034.     menuFile->AppendSeparator();
  1035.     menuFile->AppendCheckItem(File_Clip, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
  1036.     menuFile->AppendSeparator();
  1037.     menuFile->Append(File_About, _T("&About...\tCtrl-A"), _T("Show about dialog"));
  1038.     menuFile->AppendSeparator();
  1039.     menuFile->Append(File_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
  1040.  
  1041.     wxMenu *menuMapMode = new wxMenu;
  1042.     menuMapMode->Append( MapMode_Text, _T("&TEXT map mode") );
  1043.     menuMapMode->Append( MapMode_Lometric, _T("&LOMETRIC map mode") );
  1044.     menuMapMode->Append( MapMode_Twips, _T("T&WIPS map mode") );
  1045.     menuMapMode->Append( MapMode_Points, _T("&POINTS map mode") );
  1046.     menuMapMode->Append( MapMode_Metric, _T("&METRIC map mode") );
  1047.  
  1048.     wxMenu *menuUserScale = new wxMenu;
  1049.     menuUserScale->Append( UserScale_StretchHoriz, _T("Stretch &horizontally\tCtrl-H") );
  1050.     menuUserScale->Append( UserScale_ShrinkHoriz, _T("Shrin&k horizontally\tCtrl-G") );
  1051.     menuUserScale->Append( UserScale_StretchVertic, _T("Stretch &vertically\tCtrl-V") );
  1052.     menuUserScale->Append( UserScale_ShrinkVertic, _T("&Shrink vertically\tCtrl-W") );
  1053.     menuUserScale->AppendSeparator();
  1054.     menuUserScale->Append( UserScale_Restore, _T("&Restore to normal\tCtrl-0") );
  1055.  
  1056.     wxMenu *menuAxis = new wxMenu;
  1057.     menuAxis->Append( AxisMirror_Horiz, _T("Mirror horizontally\tCtrl-M"), _T(""), TRUE );
  1058.     menuAxis->Append( AxisMirror_Vertic, _T("Mirror vertically\tCtrl-N"), _T(""), TRUE );
  1059.  
  1060.     wxMenu *menuLogical = new wxMenu;
  1061.     menuLogical->Append( LogicalOrigin_MoveDown, _T("Move &down\tCtrl-D") );
  1062.     menuLogical->Append( LogicalOrigin_MoveUp, _T("Move &up\tCtrl-U") );
  1063.     menuLogical->Append( LogicalOrigin_MoveLeft, _T("Move &right\tCtrl-L") );
  1064.     menuLogical->Append( LogicalOrigin_MoveRight, _T("Move &left\tCtrl-R") );
  1065.     menuLogical->AppendSeparator();
  1066.     menuLogical->Append( LogicalOrigin_Set, _T("Set to (&100, 100)\tShift-Ctrl-1") );
  1067.     menuLogical->Append( LogicalOrigin_Restore, _T("&Restore to normal\tShift-Ctrl-0") );
  1068.  
  1069.     wxMenu *menuColour = new wxMenu;
  1070.     menuColour->Append( Colour_TextForeground, _T("Text &foreground...") );
  1071.     menuColour->Append( Colour_TextBackground, _T("Text &background...") );
  1072.     menuColour->Append( Colour_Background, _T("Background &colour...") );
  1073.     menuColour->Append( Colour_BackgroundMode, _T("&Opaque/transparent\tCtrl-B"), _T(""), TRUE );
  1074.     menuColour->Append( Colour_TextureBackgound, _T("Draw textured back&ground\tCtrl-T"), _T(""), TRUE);
  1075.  
  1076.     // now append the freshly created menu to the menu bar...
  1077.     wxMenuBar *menuBar = new wxMenuBar;
  1078.     menuBar->Append(menuFile, _T("&File"));
  1079.     menuBar->Append(menuMapMode, _T("&Mode"));
  1080.     menuBar->Append(menuUserScale, _T("&Scale"));
  1081.     menuBar->Append(menuAxis, _T("&Axis"));
  1082.     menuBar->Append(menuLogical, _T("&Origin"));
  1083.     menuBar->Append(menuColour, _T("&Colours"));
  1084.  
  1085.     // ... and attach this menu bar to the frame
  1086.     SetMenuBar(menuBar);
  1087.  
  1088.     // create a status bar just for fun (by default with 1 pane only)
  1089.     CreateStatusBar(2);
  1090.     SetStatusText(_T("Welcome to wxWindows!"));
  1091.  
  1092.     m_mapMode = wxMM_TEXT;
  1093.     m_xUserScale = 1.0;
  1094.     m_yUserScale = 1.0;
  1095.     m_xLogicalOrigin = 0;
  1096.     m_yLogicalOrigin = 0;
  1097.     m_xAxisReversed =
  1098.     m_yAxisReversed = FALSE;
  1099.     m_backgroundMode = wxSOLID;
  1100.     m_colourForeground = *wxRED;
  1101.     m_colourBackground = *wxBLUE;
  1102.     m_textureBackground = FALSE;
  1103.  
  1104.     m_canvas = new MyCanvas( this );
  1105.     m_canvas->SetScrollbars( 10, 10, 100, 240 );
  1106. }
  1107.  
  1108. // event handlers
  1109.  
  1110. void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  1111. {
  1112.     // TRUE is to force the frame to close
  1113.     Close(TRUE);
  1114. }
  1115.  
  1116. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  1117. {
  1118.     wxString msg;
  1119.     msg.Printf( wxT("This is the about dialog of the drawing sample.\n")
  1120.                 wxT("This sample tests various primitive drawing functions\n")
  1121.                 wxT("(without any attempts to prevent flicker).\n")
  1122.                 wxT("Copyright (c) Robert Roebling 1999")
  1123.               );
  1124.  
  1125.     wxMessageBox(msg, _T("About Drawing"), wxOK | wxICON_INFORMATION, this);
  1126. }
  1127.  
  1128. void MyFrame::OnClip(wxCommandEvent& event)
  1129. {
  1130.     m_canvas->Clip(event.IsChecked());
  1131. }
  1132.  
  1133. void MyFrame::OnShow(wxCommandEvent& event)
  1134. {
  1135.     m_canvas->Show((ScreenToShow)(event.GetId() - MenuShow_First));
  1136. }
  1137.  
  1138. void MyFrame::OnOption(wxCommandEvent& event)
  1139. {
  1140.     switch (event.GetId())
  1141.     {
  1142.         case MapMode_Text:
  1143.             m_mapMode = wxMM_TEXT;
  1144.             break;
  1145.         case MapMode_Lometric:
  1146.             m_mapMode = wxMM_LOMETRIC;
  1147.             break;
  1148.         case MapMode_Twips:
  1149.             m_mapMode = wxMM_TWIPS;
  1150.             break;
  1151.         case MapMode_Points:
  1152.             m_mapMode = wxMM_POINTS;
  1153.             break;
  1154.         case MapMode_Metric:
  1155.             m_mapMode = wxMM_METRIC;
  1156.             break;
  1157.  
  1158.         case LogicalOrigin_MoveDown:
  1159.             m_yLogicalOrigin += 10;
  1160.             break;
  1161.         case LogicalOrigin_MoveUp:
  1162.             m_yLogicalOrigin -= 10;
  1163.             break;
  1164.         case LogicalOrigin_MoveLeft:
  1165.             m_xLogicalOrigin += 10;
  1166.             break;
  1167.         case LogicalOrigin_MoveRight:
  1168.             m_xLogicalOrigin -= 10;
  1169.             break;
  1170.         case LogicalOrigin_Set:
  1171.             m_xLogicalOrigin =
  1172.             m_yLogicalOrigin = -100;
  1173.             break;
  1174.         case LogicalOrigin_Restore:
  1175.             m_xLogicalOrigin =
  1176.             m_yLogicalOrigin = 0;
  1177.             break;
  1178.  
  1179.         case UserScale_StretchHoriz:
  1180.             m_xUserScale *= 1.10;
  1181.             break;
  1182.         case UserScale_ShrinkHoriz:
  1183.             m_xUserScale /= 1.10;
  1184.             break;
  1185.         case UserScale_StretchVertic:
  1186.             m_yUserScale *= 1.10;
  1187.             break;
  1188.         case UserScale_ShrinkVertic:
  1189.             m_yUserScale /= 1.10;
  1190.             break;
  1191.         case UserScale_Restore:
  1192.             m_xUserScale =
  1193.             m_yUserScale = 1.0;
  1194.             break;
  1195.  
  1196.         case AxisMirror_Vertic:
  1197.             m_yAxisReversed = !m_yAxisReversed;
  1198.             break;
  1199.         case AxisMirror_Horiz:
  1200.             m_xAxisReversed = !m_xAxisReversed;
  1201.             break;
  1202.  
  1203.         case Colour_TextForeground:
  1204.             m_colourForeground = SelectColour();
  1205.             break;
  1206.         case Colour_TextBackground:
  1207.             m_colourBackground = SelectColour();
  1208.             break;
  1209.         case Colour_Background:
  1210.             {
  1211.                 wxColour col = SelectColour();
  1212.                 if ( col.Ok() )
  1213.                 {
  1214.                     m_backgroundBrush.SetColour(col);
  1215.                 }
  1216.             }
  1217.             break;
  1218.         case Colour_BackgroundMode:
  1219.             m_backgroundMode = m_backgroundMode == wxSOLID ? wxTRANSPARENT
  1220.                                                            : wxSOLID;
  1221.             break;
  1222.  
  1223.         case Colour_TextureBackgound:
  1224.             m_textureBackground = ! m_textureBackground;
  1225.             break;
  1226.  
  1227.         default:
  1228.             // skip Refresh()
  1229.             return;
  1230.     }
  1231.  
  1232.     m_canvas->Refresh();
  1233. }
  1234.  
  1235. void MyFrame::PrepareDC(wxDC& dc)
  1236. {
  1237.     dc.SetLogicalOrigin( m_xLogicalOrigin, m_yLogicalOrigin );
  1238.     dc.SetAxisOrientation( !m_xAxisReversed, m_yAxisReversed );
  1239.     dc.SetUserScale( m_xUserScale, m_yUserScale );
  1240.     dc.SetMapMode( m_mapMode );
  1241. }
  1242.  
  1243. wxColour MyFrame::SelectColour()
  1244. {
  1245.     wxColour col;
  1246.     wxColourData data;
  1247.     wxColourDialog dialog(this, &data);
  1248.  
  1249.     if ( dialog.ShowModal() == wxID_OK )
  1250.     {
  1251.         col = dialog.GetColourData().GetColour();
  1252.     }
  1253.  
  1254.     return col;
  1255. }
  1256.