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