DC reorganization
[wxWidgets.git] / samples / drawing / drawing.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/drawing/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 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers
29 #ifndef WX_PRECOMP
30 #include "wx/wx.h"
31 #endif
32
33 #include "wx/colordlg.h"
34 #include "wx/image.h"
35 #include "wx/artprov.h"
36 #include "wx/dcgraph.h"
37
38 #define wxTEST_GRAPHICS 1
39
40 #if wxTEST_GRAPHICS
41 #include "wx/graphics.h"
42 #if wxUSE_GRAPHICS_CONTEXT == 0
43 #undef wxTEST_GRAPHICS
44 #define wxTEST_GRAPHICS 0
45 #endif
46 #else
47 #undef wxUSE_GRAPHICS_CONTEXT
48 #define wxUSE_GRAPHICS_CONTEXT 0
49 #endif
50
51 // ----------------------------------------------------------------------------
52 // ressources
53 // ----------------------------------------------------------------------------
54
55 // the application icon
56 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
57 #include "mondrian.xpm"
58 #endif
59
60 // ----------------------------------------------------------------------------
61 // constants
62 // ----------------------------------------------------------------------------
63
64 // what do we show on screen (there are too many shapes to put them all on
65 // screen simultaneously)
66 enum ScreenToShow
67 {
68 Show_Default,
69 Show_Text,
70 Show_Lines,
71 Show_Brushes,
72 Show_Polygons,
73 Show_Mask,
74 Show_Mask_Stretch,
75 Show_Ops,
76 Show_Regions,
77 Show_Circles,
78 Show_Splines,
79 #if wxUSE_GRAPHICS_CONTEXT
80 Show_Alpha,
81 Show_Graphics,
82 #endif
83 Show_Gradient,
84 Show_Max
85 };
86
87 // ----------------------------------------------------------------------------
88 // global variables
89 // ----------------------------------------------------------------------------
90
91 static wxBitmap *gs_bmpNoMask = NULL,
92 *gs_bmpWithColMask = NULL,
93 *gs_bmpMask = NULL,
94 *gs_bmpWithMask = NULL,
95 *gs_bmp4 = NULL,
96 *gs_bmp4_mono = NULL,
97 *gs_bmp36 = NULL;
98
99 // ----------------------------------------------------------------------------
100 // private classes
101 // ----------------------------------------------------------------------------
102
103 // Define a new application type, each program should derive a class from wxApp
104 class MyApp : public wxApp
105 {
106 public:
107 // override base class virtuals
108 // ----------------------------
109
110 // this one is called on application startup and is a good place for the app
111 // initialization (doing it here and not in the ctor allows to have an error
112 // return: if OnInit() returns false, the application terminates)
113 virtual bool OnInit();
114
115 virtual int OnExit() { DeleteBitmaps(); return 0; }
116
117 protected:
118 void DeleteBitmaps();
119
120 bool LoadImages();
121 };
122
123 class MyCanvas;
124
125 // Define a new frame type: this is going to be our main frame
126 class MyFrame : public wxFrame
127 {
128 public:
129 // ctor(s)
130 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
131
132 // event handlers (these functions should _not_ be virtual)
133 void OnQuit(wxCommandEvent& event);
134 void OnAbout(wxCommandEvent& event);
135 void OnClip(wxCommandEvent& event);
136 #if wxUSE_GRAPHICS_CONTEXT
137 void OnGraphicContext(wxCommandEvent& event);
138 #endif
139 void OnShow(wxCommandEvent &event);
140 void OnOption(wxCommandEvent &event);
141
142 #if wxUSE_COLOURDLG
143 wxColour SelectColour();
144 #endif // wxUSE_COLOURDLG
145 void PrepareDC(wxDC& dc);
146
147 int m_backgroundMode;
148 int m_textureBackground;
149 int m_mapMode;
150 double m_xUserScale;
151 double m_yUserScale;
152 int m_xLogicalOrigin;
153 int m_yLogicalOrigin;
154 bool m_xAxisReversed,
155 m_yAxisReversed;
156 wxColour m_colourForeground, // these are _text_ colours
157 m_colourBackground;
158 wxBrush m_backgroundBrush;
159 MyCanvas *m_canvas;
160
161 private:
162 // any class wishing to process wxWidgets events must use this macro
163 DECLARE_EVENT_TABLE()
164 };
165
166 // define a scrollable canvas for drawing onto
167 class MyCanvas: public wxScrolledWindow
168 {
169 public:
170 MyCanvas( MyFrame *parent );
171
172 void OnPaint(wxPaintEvent &event);
173 void OnMouseMove(wxMouseEvent &event);
174
175 void ToShow(ScreenToShow show) { m_show = show; Refresh(); }
176
177 // set or remove the clipping region
178 void Clip(bool clip) { m_clip = clip; Refresh(); }
179 #if wxUSE_GRAPHICS_CONTEXT
180 void UseGraphicContext(bool use) { m_useContext = use; Refresh(); }
181 #endif
182
183 protected:
184 enum DrawMode
185 {
186 Draw_Normal,
187 Draw_Stretch
188 };
189
190 void DrawTestLines( int x, int y, int width, wxDC &dc );
191 void DrawTestPoly(wxDC& dc);
192 void DrawTestBrushes(wxDC& dc);
193 void DrawText(wxDC& dc);
194 void DrawImages(wxDC& dc, DrawMode mode);
195 void DrawWithLogicalOps(wxDC& dc);
196 #if wxUSE_GRAPHICS_CONTEXT
197 void DrawAlpha(wxDC& dc);
198 void DrawGraphics(wxGraphicsContext* gc);
199 #endif
200 void DrawRegions(wxDC& dc);
201 void DrawCircles(wxDC& dc);
202 void DrawSplines(wxDC& dc);
203 void DrawDefault(wxDC& dc);
204 void DrawGradients(wxDC& dc);
205
206 void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime);
207
208 private:
209 MyFrame *m_owner;
210
211 ScreenToShow m_show;
212 wxBitmap m_smile_bmp;
213 wxIcon m_std_icon;
214 bool m_clip;
215 #if wxUSE_GRAPHICS_CONTEXT
216 bool m_useContext ;
217 #endif
218
219 DECLARE_EVENT_TABLE()
220 };
221
222 // ----------------------------------------------------------------------------
223 // constants
224 // ----------------------------------------------------------------------------
225
226 // IDs for the controls and the menu commands
227 enum
228 {
229 // menu items
230 File_Quit = wxID_EXIT,
231 File_About = wxID_ABOUT,
232
233 MenuShow_First = wxID_HIGHEST,
234 File_ShowDefault = MenuShow_First,
235 File_ShowText,
236 File_ShowLines,
237 File_ShowBrushes,
238 File_ShowPolygons,
239 File_ShowMask,
240 File_ShowMaskStretch,
241 File_ShowOps,
242 File_ShowRegions,
243 File_ShowCircles,
244 File_ShowSplines,
245 #if wxUSE_GRAPHICS_CONTEXT
246 File_ShowAlpha,
247 File_ShowGraphics,
248 #endif
249 File_ShowGradients,
250 MenuShow_Last = File_ShowGradients,
251
252 File_Clip,
253 #if wxUSE_GRAPHICS_CONTEXT
254 File_GraphicContext,
255 #endif
256
257 MenuOption_First,
258
259 MapMode_Text = MenuOption_First,
260 MapMode_Lometric,
261 MapMode_Twips,
262 MapMode_Points,
263 MapMode_Metric,
264
265 UserScale_StretchHoriz,
266 UserScale_ShrinkHoriz,
267 UserScale_StretchVertic,
268 UserScale_ShrinkVertic,
269 UserScale_Restore,
270
271 AxisMirror_Horiz,
272 AxisMirror_Vertic,
273
274 LogicalOrigin_MoveDown,
275 LogicalOrigin_MoveUp,
276 LogicalOrigin_MoveLeft,
277 LogicalOrigin_MoveRight,
278 LogicalOrigin_Set,
279 LogicalOrigin_Restore,
280
281 #if wxUSE_COLOURDLG
282 Colour_TextForeground,
283 Colour_TextBackground,
284 Colour_Background,
285 #endif // wxUSE_COLOURDLG
286 Colour_BackgroundMode,
287 Colour_TextureBackgound,
288
289 MenuOption_Last = Colour_TextureBackgound
290 };
291
292 // ----------------------------------------------------------------------------
293 // event tables and other macros for wxWidgets
294 // ----------------------------------------------------------------------------
295
296
297 // Create a new application object: this macro will allow wxWidgets to create
298 // the application object during program execution (it's better than using a
299 // static object for many reasons) and also declares the accessor function
300 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
301 // not wxApp)
302 IMPLEMENT_APP(MyApp)
303
304 // ============================================================================
305 // implementation
306 // ============================================================================
307
308 // ----------------------------------------------------------------------------
309 // the application class
310 // ----------------------------------------------------------------------------
311
312 bool MyApp::LoadImages()
313 {
314 gs_bmpNoMask = new wxBitmap;
315 gs_bmpWithColMask = new wxBitmap;
316 gs_bmpMask = new wxBitmap;
317 gs_bmpWithMask = new wxBitmap;
318 gs_bmp4 = new wxBitmap;
319 gs_bmp4_mono = new wxBitmap;
320 gs_bmp36 = new wxBitmap;
321
322 wxPathList pathList;
323 pathList.Add(_T("."));
324 pathList.Add(_T(".."));
325 pathList.Add(_T("../.."));
326
327 wxString path = pathList.FindValidPath(_T("pat4.bmp"));
328 if ( !path )
329 return false;
330
331 /* 4 colour bitmap */
332 gs_bmp4->LoadFile(path, wxBITMAP_TYPE_BMP);
333 /* turn into mono-bitmap */
334 gs_bmp4_mono->LoadFile(path, wxBITMAP_TYPE_BMP);
335 wxMask* mask4 = new wxMask(*gs_bmp4_mono, *wxBLACK);
336 gs_bmp4_mono->SetMask(mask4);
337
338 path = pathList.FindValidPath(_T("pat36.bmp"));
339 if ( !path )
340 return false;
341 gs_bmp36->LoadFile(path, wxBITMAP_TYPE_BMP);
342 wxMask* mask36 = new wxMask(*gs_bmp36, *wxBLACK);
343 gs_bmp36->SetMask(mask36);
344
345 path = pathList.FindValidPath(_T("image.bmp"));
346 if ( !path )
347 return false;
348 gs_bmpNoMask->LoadFile(path, wxBITMAP_TYPE_BMP);
349 gs_bmpWithMask->LoadFile(path, wxBITMAP_TYPE_BMP);
350 gs_bmpWithColMask->LoadFile(path, wxBITMAP_TYPE_BMP);
351
352 path = pathList.FindValidPath(_T("mask.bmp"));
353 if ( !path )
354 return false;
355 gs_bmpMask->LoadFile(path, wxBITMAP_TYPE_BMP);
356
357 wxMask *mask = new wxMask(*gs_bmpMask, *wxBLACK);
358 gs_bmpWithMask->SetMask(mask);
359
360 mask = new wxMask(*gs_bmpWithColMask, *wxWHITE);
361 gs_bmpWithColMask->SetMask(mask);
362
363 return true;
364 }
365
366 // `Main program' equivalent: the program execution "starts" here
367 bool MyApp::OnInit()
368 {
369 if ( !wxApp::OnInit() )
370 return false;
371
372 // Create the main application window
373 MyFrame *frame = new MyFrame(_T("Drawing sample"),
374 wxPoint(50, 50), wxSize(550, 340));
375
376 // Show it and tell the application that it's our main window
377 frame->Show(true);
378 SetTopWindow(frame);
379
380 if ( !LoadImages() )
381 {
382 wxLogError(wxT("Can't load one of the bitmap files needed ")
383 wxT("for this sample from the current or parent ")
384 wxT("directory, please copy them there."));
385
386 // stop here
387 DeleteBitmaps();
388
389 return false;
390 }
391
392 // ok, continue
393 return true;
394 }
395
396 void MyApp::DeleteBitmaps()
397 {
398 delete gs_bmpNoMask;
399 delete gs_bmpWithColMask;
400 delete gs_bmpMask;
401 delete gs_bmpWithMask;
402 delete gs_bmp4;
403 delete gs_bmp4_mono;
404 delete gs_bmp36;
405
406 gs_bmpNoMask = NULL;
407 gs_bmpWithColMask = NULL;
408 gs_bmpMask = NULL;
409 gs_bmpWithMask = NULL;
410 gs_bmp4 = NULL;
411 gs_bmp4_mono = NULL;
412 gs_bmp36 = NULL;
413 }
414
415 // ----------------------------------------------------------------------------
416 // MyCanvas
417 // ----------------------------------------------------------------------------
418
419 // the event tables connect the wxWidgets events with the functions (event
420 // handlers) which process them.
421 BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
422 EVT_PAINT (MyCanvas::OnPaint)
423 EVT_MOTION (MyCanvas::OnMouseMove)
424 END_EVENT_TABLE()
425
426 #include "smile.xpm"
427
428 MyCanvas::MyCanvas(MyFrame *parent)
429 : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
430 wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
431 {
432 m_owner = parent;
433 m_show = Show_Default;
434 m_smile_bmp = wxBitmap(smile_xpm);
435 m_std_icon = wxArtProvider::GetIcon(wxART_INFORMATION);
436 m_clip = false;
437 #if wxUSE_GRAPHICS_CONTEXT
438 m_useContext = false;
439 #endif
440 }
441
442 void MyCanvas::DrawTestBrushes(wxDC& dc)
443 {
444 static const wxCoord WIDTH = 200;
445 static const wxCoord HEIGHT = 80;
446
447 wxCoord x = 10,
448 y = 10;
449
450 dc.SetBrush(wxBrush(*wxGREEN, wxSOLID));
451 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
452 dc.DrawText(_T("Solid green"), x + 10, y + 10);
453
454 y += HEIGHT;
455 dc.SetBrush(wxBrush(*wxRED, wxCROSSDIAG_HATCH));
456 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
457 dc.DrawText(_T("Hatched red"), x + 10, y + 10);
458
459 y += HEIGHT;
460 dc.SetBrush(wxBrush(*gs_bmpMask));
461 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
462 dc.DrawText(_T("Stipple mono"), x + 10, y + 10);
463
464 y += HEIGHT;
465 dc.SetBrush(wxBrush(*gs_bmpNoMask));
466 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
467 dc.DrawText(_T("Stipple colour"), x + 10, y + 10);
468 }
469
470 void MyCanvas::DrawTestPoly(wxDC& dc)
471 {
472 wxBrush brushHatch(*wxRED, wxFDIAGONAL_HATCH);
473 dc.SetBrush(brushHatch);
474
475 wxPoint star[5];
476 star[0] = wxPoint(100, 60);
477 star[1] = wxPoint(60, 150);
478 star[2] = wxPoint(160, 100);
479 star[3] = wxPoint(40, 100);
480 star[4] = wxPoint(140, 150);
481
482 dc.DrawText(_T("You should see two (irregular) stars below, the left one ")
483 _T("hatched"), 10, 10);
484 dc.DrawText(_T("except for the central region and the right ")
485 _T("one entirely hatched"), 10, 30);
486 dc.DrawText(_T("The third star only has a hatched outline"), 10, 50);
487
488 dc.DrawPolygon(WXSIZEOF(star), star, 0, 30);
489 dc.DrawPolygon(WXSIZEOF(star), star, 160, 30, wxWINDING_RULE);
490
491 wxPoint star2[10];
492 star2[0] = wxPoint(0, 100);
493 star2[1] = wxPoint(-59, -81);
494 star2[2] = wxPoint(95, 31);
495 star2[3] = wxPoint(-95, 31);
496 star2[4] = wxPoint(59, -81);
497 star2[5] = wxPoint(0, 80);
498 star2[6] = wxPoint(-47, -64);
499 star2[7] = wxPoint(76, 24);
500 star2[8] = wxPoint(-76, 24);
501 star2[9] = wxPoint(47, -64);
502 int count[2] = {5, 5};
503
504 dc.DrawPolyPolygon(WXSIZEOF(count), count, star2, 450, 150);
505 }
506
507 void MyCanvas::DrawTestLines( int x, int y, int width, wxDC &dc )
508 {
509 dc.SetPen( wxPen( wxT("black"), width, wxSOLID) );
510 dc.SetBrush( *wxRED_BRUSH );
511 dc.DrawText(wxString::Format(wxT("Testing lines of width %d"), width), x + 10, y - 10);
512 dc.DrawRectangle( x+10, y+10, 100, 190 );
513
514 dc.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x + 150, y + 10);
515 dc.SetPen( wxPen( wxT("black"), width, wxSOLID) );
516 dc.DrawLine( x+20, y+20, 100, y+20 );
517 dc.SetPen( wxPen( wxT("black"), width, wxDOT) );
518 dc.DrawLine( x+20, y+30, 100, y+30 );
519 dc.SetPen( wxPen( wxT("black"), width, wxSHORT_DASH) );
520 dc.DrawLine( x+20, y+40, 100, y+40 );
521 dc.SetPen( wxPen( wxT("black"), width, wxLONG_DASH) );
522 dc.DrawLine( x+20, y+50, 100, y+50 );
523 dc.SetPen( wxPen( wxT("black"), width, wxDOT_DASH) );
524 dc.DrawLine( x+20, y+60, 100, y+60 );
525
526 dc.DrawText(_T("Misc hatches"), x + 150, y + 70);
527 dc.SetPen( wxPen( wxT("black"), width, wxBDIAGONAL_HATCH) );
528 dc.DrawLine( x+20, y+70, 100, y+70 );
529 dc.SetPen( wxPen( wxT("black"), width, wxCROSSDIAG_HATCH) );
530 dc.DrawLine( x+20, y+80, 100, y+80 );
531 dc.SetPen( wxPen( wxT("black"), width, wxFDIAGONAL_HATCH) );
532 dc.DrawLine( x+20, y+90, 100, y+90 );
533 dc.SetPen( wxPen( wxT("black"), width, wxCROSS_HATCH) );
534 dc.DrawLine( x+20, y+100, 100, y+100 );
535 dc.SetPen( wxPen( wxT("black"), width, wxHORIZONTAL_HATCH) );
536 dc.DrawLine( x+20, y+110, 100, y+110 );
537 dc.SetPen( wxPen( wxT("black"), width, wxVERTICAL_HATCH) );
538 dc.DrawLine( x+20, y+120, 100, y+120 );
539
540 dc.DrawText(_T("User dash"), x + 150, y + 140);
541 wxPen ud( wxT("black"), width, wxUSER_DASH );
542 wxDash dash1[6];
543 dash1[0] = 8; // Long dash <---------+
544 dash1[1] = 2; // Short gap |
545 dash1[2] = 3; // Short dash |
546 dash1[3] = 2; // Short gap |
547 dash1[4] = 3; // Short dash |
548 dash1[5] = 2; // Short gap and repeat +
549 ud.SetDashes( 6, dash1 );
550 dc.SetPen( ud );
551 dc.DrawLine( x+20, y+140, 100, y+140 );
552 dash1[0] = 5; // Make first dash shorter
553 ud.SetDashes( 6, dash1 );
554 dc.SetPen( ud );
555 dc.DrawLine( x+20, y+150, 100, y+150 );
556 dash1[2] = 5; // Make second dash longer
557 ud.SetDashes( 6, dash1 );
558 dc.SetPen( ud );
559 dc.DrawLine( x+20, y+160, 100, y+160 );
560 dash1[4] = 5; // Make third dash longer
561 ud.SetDashes( 6, dash1 );
562 dc.SetPen( ud );
563 dc.DrawLine( x+20, y+170, 100, y+170 );
564 }
565
566 void MyCanvas::DrawDefault(wxDC& dc)
567 {
568 // mark the origin
569 dc.DrawCircle(0, 0, 10);
570
571 #if !defined(wxMAC_USE_CORE_GRAPHICS) || !wxMAC_USE_CORE_GRAPHICS
572 // GetPixel and FloodFill not supported by Mac OS X CoreGraphics
573 // (FloodFill uses Blit from a non-wxMemoryDC)
574 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
575 dc.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID));
576
577 wxColour tmpColour ;
578 dc.GetPixel(1,1, &tmpColour);
579 dc.FloodFill(1,1, tmpColour, wxFLOOD_SURFACE);
580 #endif
581
582 dc.DrawCheckMark(5, 80, 15, 15);
583 dc.DrawCheckMark(25, 80, 30, 30);
584 dc.DrawCheckMark(60, 80, 60, 60);
585
586 // this is the test for "blitting bitmap into DC damages selected brush" bug
587 wxCoord rectSize = m_std_icon.GetWidth() + 10;
588 wxCoord x = 100;
589 dc.SetPen(*wxTRANSPARENT_PEN);
590 dc.SetBrush( *wxGREEN_BRUSH );
591 dc.DrawRectangle(x, 10, rectSize, rectSize);
592 dc.DrawBitmap(m_std_icon, x + 5, 15, true);
593 x += rectSize + 10;
594 dc.DrawRectangle(x, 10, rectSize, rectSize);
595 dc.DrawIcon(m_std_icon, x + 5, 15);
596 x += rectSize + 10;
597 dc.DrawRectangle(x, 10, rectSize, rectSize);
598
599 // test for "transparent" bitmap drawing (it intersects with the last
600 // rectangle above)
601 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
602
603 if (m_smile_bmp.Ok())
604 dc.DrawBitmap(m_smile_bmp, x + rectSize - 20, rectSize - 10, true);
605
606 dc.SetBrush( *wxBLACK_BRUSH );
607 dc.DrawRectangle( 0, 160, 1000, 300 );
608
609 // draw lines
610 wxBitmap bitmap(20,70);
611 wxMemoryDC memdc;
612 memdc.SelectObject( bitmap );
613 memdc.SetBrush( *wxBLACK_BRUSH );
614 memdc.SetPen( *wxWHITE_PEN );
615 memdc.DrawRectangle(0,0,20,70);
616 memdc.DrawLine( 10,0,10,70 );
617
618 // to the right
619 wxPen pen = *wxRED_PEN;
620 memdc.SetPen(pen);
621 memdc.DrawLine( 10, 5,10, 5 );
622 memdc.DrawLine( 10,10,11,10 );
623 memdc.DrawLine( 10,15,12,15 );
624 memdc.DrawLine( 10,20,13,20 );
625
626 /*
627 memdc.SetPen(*wxRED_PEN);
628 memdc.DrawLine( 12, 5,12, 5 );
629 memdc.DrawLine( 12,10,13,10 );
630 memdc.DrawLine( 12,15,14,15 );
631 memdc.DrawLine( 12,20,15,20 );
632 */
633
634 // same to the left
635 memdc.DrawLine( 10,25,10,25 );
636 memdc.DrawLine( 10,30, 9,30 );
637 memdc.DrawLine( 10,35, 8,35 );
638 memdc.DrawLine( 10,40, 7,40 );
639
640 // XOR draw lines
641 dc.SetPen(*wxWHITE_PEN);
642 memdc.SetLogicalFunction( wxINVERT );
643 memdc.SetPen( *wxWHITE_PEN );
644 memdc.DrawLine( 10,50,10,50 );
645 memdc.DrawLine( 10,55,11,55 );
646 memdc.DrawLine( 10,60,12,60 );
647 memdc.DrawLine( 10,65,13,65 );
648
649 memdc.DrawLine( 12,50,12,50 );
650 memdc.DrawLine( 12,55,13,55 );
651 memdc.DrawLine( 12,60,14,60 );
652 memdc.DrawLine( 12,65,15,65 );
653
654 memdc.SelectObject( wxNullBitmap );
655 dc.DrawBitmap( bitmap, 10, 170 );
656 wxImage image = bitmap.ConvertToImage();
657 image.Rescale( 60,210 );
658 bitmap = wxBitmap(image);
659 dc.DrawBitmap( bitmap, 50, 170 );
660
661 // test the rectangle outline drawing - there should be one pixel between
662 // the rect and the lines
663 dc.SetPen(*wxWHITE_PEN);
664 dc.SetBrush( *wxTRANSPARENT_BRUSH );
665 dc.DrawRectangle(150, 170, 49, 29);
666 dc.DrawRectangle(200, 170, 49, 29);
667 dc.SetPen(*wxWHITE_PEN);
668 dc.DrawLine(250, 210, 250, 170);
669 dc.DrawLine(260, 200, 150, 200);
670
671 // test the rectangle filled drawing - there should be one pixel between
672 // the rect and the lines
673 dc.SetPen(*wxTRANSPARENT_PEN);
674 dc.SetBrush( *wxWHITE_BRUSH );
675 dc.DrawRectangle(300, 170, 49, 29);
676 dc.DrawRectangle(350, 170, 49, 29);
677 dc.SetPen(*wxWHITE_PEN);
678 dc.DrawLine(400, 170, 400, 210);
679 dc.DrawLine(300, 200, 410, 200);
680
681 // a few more tests of this kind
682 dc.SetPen(*wxRED_PEN);
683 dc.SetBrush( *wxWHITE_BRUSH );
684 dc.DrawRectangle(300, 220, 1, 1);
685 dc.DrawRectangle(310, 220, 2, 2);
686 dc.DrawRectangle(320, 220, 3, 3);
687 dc.DrawRectangle(330, 220, 4, 4);
688
689 dc.SetPen(*wxTRANSPARENT_PEN);
690 dc.SetBrush( *wxWHITE_BRUSH );
691 dc.DrawRectangle(300, 230, 1, 1);
692 dc.DrawRectangle(310, 230, 2, 2);
693 dc.DrawRectangle(320, 230, 3, 3);
694 dc.DrawRectangle(330, 230, 4, 4);
695
696 // and now for filled rect with outline
697 dc.SetPen(*wxRED_PEN);
698 dc.SetBrush( *wxWHITE_BRUSH );
699 dc.DrawRectangle(500, 170, 49, 29);
700 dc.DrawRectangle(550, 170, 49, 29);
701 dc.SetPen(*wxWHITE_PEN);
702 dc.DrawLine(600, 170, 600, 210);
703 dc.DrawLine(500, 200, 610, 200);
704
705 // test the rectangle outline drawing - there should be one pixel between
706 // the rect and the lines
707 dc.SetPen(*wxWHITE_PEN);
708 dc.SetBrush( *wxTRANSPARENT_BRUSH );
709 dc.DrawRoundedRectangle(150, 270, 49, 29, 6);
710 dc.DrawRoundedRectangle(200, 270, 49, 29, 6);
711 dc.SetPen(*wxWHITE_PEN);
712 dc.DrawLine(250, 270, 250, 310);
713 dc.DrawLine(150, 300, 260, 300);
714
715 // test the rectangle filled drawing - there should be one pixel between
716 // the rect and the lines
717 dc.SetPen(*wxTRANSPARENT_PEN);
718 dc.SetBrush( *wxWHITE_BRUSH );
719 dc.DrawRoundedRectangle(300, 270, 49, 29, 6);
720 dc.DrawRoundedRectangle(350, 270, 49, 29, 6);
721 dc.SetPen(*wxWHITE_PEN);
722 dc.DrawLine(400, 270, 400, 310);
723 dc.DrawLine(300, 300, 410, 300);
724
725 // Added by JACS to demonstrate bizarre behaviour.
726 // With a size of 70, we get a missing red RHS,
727 // and the height is too small, so we get yellow
728 // showing. With a size of 40, it draws as expected:
729 // it just shows a white rectangle with red outline.
730 int totalWidth = 70;
731 int totalHeight = 70;
732 wxBitmap bitmap2(totalWidth, totalHeight);
733
734 wxMemoryDC memdc2;
735 memdc2.SelectObject(bitmap2);
736
737 wxColour clr(255, 255, 0);
738 wxBrush yellowBrush(clr, wxSOLID);
739 memdc2.SetBackground(yellowBrush);
740 memdc2.Clear();
741
742 wxPen yellowPen(clr, 1, wxSOLID);
743
744 // Now draw a white rectangle with red outline. It should
745 // entirely eclipse the yellow background.
746 memdc2.SetPen(*wxRED_PEN);
747 memdc2.SetBrush(*wxWHITE_BRUSH);
748
749 memdc2.DrawRectangle(0, 0, totalWidth, totalHeight);
750
751 memdc2.SetPen(wxNullPen);
752 memdc2.SetBrush(wxNullBrush);
753 memdc2.SelectObject(wxNullBitmap);
754
755 dc.DrawBitmap(bitmap2, 500, 270);
756
757 // Repeat, but draw directly on dc
758 // Draw a yellow rectangle filling the bitmap
759
760 x = 600; int y = 270;
761 dc.SetPen(yellowPen);
762 dc.SetBrush(yellowBrush);
763 dc.DrawRectangle(x, y, totalWidth, totalHeight);
764
765 // Now draw a white rectangle with red outline. It should
766 // entirely eclipse the yellow background.
767 dc.SetPen(*wxRED_PEN);
768 dc.SetBrush(*wxWHITE_BRUSH);
769
770 dc.DrawRectangle(x, y, totalWidth, totalHeight);
771 }
772
773 void MyCanvas::DrawText(wxDC& dc)
774 {
775 // set underlined font for testing
776 dc.SetFont( wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, true) );
777 dc.DrawText( _T("This is text"), 110, 10 );
778 dc.DrawRotatedText( _T("That is text"), 20, 10, -45 );
779
780 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
781 // under Win9x (it is not TrueType)
782 dc.SetFont( *wxSWISS_FONT );
783
784 wxString text;
785 dc.SetBackgroundMode(wxTRANSPARENT);
786
787 for ( int n = -180; n < 180; n += 30 )
788 {
789 text.Printf(wxT(" %d rotated text"), n);
790 dc.DrawRotatedText(text , 400, 400, n);
791 }
792
793 dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
794
795 dc.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
796
797 wxCoord length;
798 wxCoord height;
799 wxCoord descent;
800 dc.GetTextExtent( _T("This is Swiss 18pt text."), &length, &height, &descent );
801 text.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length, height, descent );
802 dc.DrawText( text, 110, 80 );
803
804 text.Printf( wxT("CharHeight() returns: %d"), dc.GetCharHeight() );
805 dc.DrawText( text, 110, 120 );
806
807 dc.DrawRectangle( 100, 40, 4, height );
808
809 // test the logical function effect
810 wxCoord y = 150;
811 dc.SetLogicalFunction(wxINVERT);
812 dc.DrawText( _T("There should be no text below"), 110, 150 );
813 dc.DrawRectangle( 110, y, 100, height );
814
815 // twice drawn inverted should result in invisible
816 y += height;
817 dc.DrawText( _T("Invisible text"), 110, y );
818 dc.DrawRectangle( 110, y, 100, height );
819 dc.DrawText( _T("Invisible text"), 110, y );
820 dc.DrawRectangle( 110, y, 100, height );
821 dc.SetLogicalFunction(wxCOPY);
822
823 y += height;
824 dc.DrawRectangle( 110, y, 100, height );
825 dc.DrawText( _T("Visible text"), 110, y );
826 }
827
828 static const struct
829 {
830 const wxChar *name;
831 int rop;
832 } rasterOperations[] =
833 {
834 { wxT("wxAND"), wxAND },
835 { wxT("wxAND_INVERT"), wxAND_INVERT },
836 { wxT("wxAND_REVERSE"), wxAND_REVERSE },
837 { wxT("wxCLEAR"), wxCLEAR },
838 { wxT("wxCOPY"), wxCOPY },
839 { wxT("wxEQUIV"), wxEQUIV },
840 { wxT("wxINVERT"), wxINVERT },
841 { wxT("wxNAND"), wxNAND },
842 { wxT("wxNO_OP"), wxNO_OP },
843 { wxT("wxOR"), wxOR },
844 { wxT("wxOR_INVERT"), wxOR_INVERT },
845 { wxT("wxOR_REVERSE"), wxOR_REVERSE },
846 { wxT("wxSET"), wxSET },
847 { wxT("wxSRC_INVERT"), wxSRC_INVERT },
848 { wxT("wxXOR"), wxXOR },
849 };
850
851 void MyCanvas::DrawImages(wxDC& dc, DrawMode mode)
852 {
853 dc.DrawText(_T("original image"), 0, 0);
854 dc.DrawBitmap(*gs_bmpNoMask, 0, 20, 0);
855 dc.DrawText(_T("with colour mask"), 0, 100);
856 dc.DrawBitmap(*gs_bmpWithColMask, 0, 120, true);
857 dc.DrawText(_T("the mask image"), 0, 200);
858 dc.DrawBitmap(*gs_bmpMask, 0, 220, 0);
859 dc.DrawText(_T("masked image"), 0, 300);
860 dc.DrawBitmap(*gs_bmpWithMask, 0, 320, true);
861
862 int cx = gs_bmpWithColMask->GetWidth(),
863 cy = gs_bmpWithColMask->GetHeight();
864
865 wxMemoryDC memDC;
866 for ( size_t n = 0; n < WXSIZEOF(rasterOperations); n++ )
867 {
868 wxCoord x = 120 + 150*(n%4),
869 y = 20 + 100*(n/4);
870
871 dc.DrawText(rasterOperations[n].name, x, y - 20);
872 memDC.SelectObject(*gs_bmpWithColMask);
873 if ( mode == Draw_Stretch )
874 {
875 dc.StretchBlit(x, y, cx, cy, &memDC, 0, 0, cx/2, cy/2,
876 rasterOperations[n].rop, true);
877 }
878 else
879 {
880 dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, true);
881 }
882 }
883 }
884
885 void MyCanvas::DrawWithLogicalOps(wxDC& dc)
886 {
887 static const wxCoord w = 60;
888 static const wxCoord h = 60;
889
890 // reuse the text colour here
891 dc.SetPen(wxPen(m_owner->m_colourForeground, 1, wxSOLID));
892 dc.SetBrush(*wxTRANSPARENT_BRUSH);
893
894 size_t n;
895 for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
896 {
897 wxCoord x = 20 + 150*(n%4),
898 y = 20 + 100*(n/4);
899
900 dc.DrawText(rasterOperations[n].name, x, y - 20);
901 dc.SetLogicalFunction(rasterOperations[n].rop);
902 dc.DrawRectangle(x, y, w, h);
903 dc.DrawLine(x, y, x + w, y + h);
904 dc.DrawLine(x + w, y, x, y + h);
905 }
906
907 // now some filled rectangles
908 dc.SetBrush(wxBrush(m_owner->m_colourForeground, wxSOLID));
909
910 for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
911 {
912 wxCoord x = 20 + 150*(n%4),
913 y = 500 + 100*(n/4);
914
915 dc.DrawText(rasterOperations[n].name, x, y - 20);
916 dc.SetLogicalFunction(rasterOperations[n].rop);
917 dc.DrawRectangle(x, y, w, h);
918 }
919 }
920
921 #if wxUSE_GRAPHICS_CONTEXT
922 #ifdef __WXGTK20__
923 void MyCanvas::DrawAlpha(wxDC& no_dc)
924 #else
925 void MyCanvas::DrawAlpha(wxDC& dc)
926 #endif
927 {
928 #ifdef __WXGTK__
929 wxGCDC dc( this );
930 PrepareDC( dc );
931 #endif
932
933 wxDouble margin = 20 ;
934 wxDouble width = 180 ;
935 wxDouble radius = 30 ;
936
937 dc.SetPen( wxPen( wxColour( 128, 0, 0, 255 ),12, wxSOLID));
938 dc.SetBrush( wxBrush( wxColour( 255, 0, 0, 255),wxSOLID));
939
940 wxRect r(margin,margin+width*0.66,width,width) ;
941
942 dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
943
944 dc.SetPen( wxPen( wxColour( 0, 0, 128, 255 ),12, wxSOLID));
945 dc.SetBrush( wxBrush( wxColour( 0, 0, 255, 255),wxSOLID));
946
947 r.Offset( width * 0.8 , - width * 0.66 ) ;
948
949 dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
950
951 dc.SetPen( wxPen( wxColour( 128, 128, 0, 255 ),12, wxSOLID));
952 dc.SetBrush( wxBrush( wxColour( 192, 192, 0, 255),wxSOLID));
953
954 r.Offset( width * 0.8 , width *0.5 ) ;
955
956 dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
957
958 dc.SetPen( *wxTRANSPARENT_PEN ) ;
959 dc.SetBrush( wxBrush( wxColour(255,255,128,128) ) );
960 dc.DrawRoundedRectangle( 0 , margin + width / 2 , width * 3 , 100 , radius) ;
961
962 dc.SetTextForeground( wxColour(255,255,0,128) );
963 dc.SetFont( wxFont( 40, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL ) );
964 dc.DrawText( wxT("Hello!"), 120, 80 );
965 }
966
967 #endif
968
969 #if wxUSE_GRAPHICS_CONTEXT
970
971 const int BASE = 80.0;
972 const int BASE2 = BASE/2;
973 const int BASE4 = BASE/4;
974
975 static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
976
977
978 // modeled along Robin Dunn's GraphicsContext.py sample
979
980 void MyCanvas::DrawGraphics(wxGraphicsContext* gc)
981 {
982 wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
983 gc->SetFont(font,*wxBLACK);
984
985 // make a path that contains a circle and some lines, centered at 0,0
986 wxGraphicsPath path = gc->CreatePath() ;
987 path.AddCircle( 0, 0, BASE2 );
988 path.MoveToPoint(0, -BASE2);
989 path.AddLineToPoint(0, BASE2);
990 path.MoveToPoint(-BASE2, 0);
991 path.AddLineToPoint(BASE2, 0);
992 path.CloseSubpath();
993 path.AddRectangle(-BASE4, -BASE4/2, BASE2, BASE4);
994
995 // Now use that path to demonstrate various capbilites of the grpahics context
996 gc->PushState(); // save current translation/scale/other state
997 gc->Translate(60, 75); // reposition the context origin
998
999 gc->SetPen(wxPen("navy", 1));
1000 gc->SetBrush(wxBrush("pink"));
1001
1002 for( int i = 0 ; i < 3 ; ++i )
1003 {
1004 wxString label;
1005 switch( i )
1006 {
1007 case 0 :
1008 label = "StrokePath";
1009 break;
1010 case 1 :
1011 label = "FillPath";
1012 break;
1013 case 2 :
1014 label = "DrawPath";
1015 break;
1016 }
1017 wxDouble w, h;
1018 gc->GetTextExtent(label, &w, &h, NULL, NULL);
1019 gc->DrawText(label, -w/2, -BASE2-h-4);
1020 switch( i )
1021 {
1022 case 0 :
1023 gc->StrokePath(path);
1024 break;
1025 case 1 :
1026 gc->FillPath(path);
1027 break;
1028 case 2 :
1029 gc->DrawPath(path);
1030 break;
1031 }
1032 gc->Translate(2*BASE, 0);
1033 }
1034
1035 gc->PopState(); // restore saved state
1036 gc->PushState(); // save it again
1037 gc->Translate(60, 200); // offset to the lower part of the window
1038
1039 gc->DrawText("Scale", 0, -BASE2);
1040 gc->Translate(0, 20);
1041
1042 gc->SetBrush(wxBrush(wxColour(178, 34, 34, 128)));// 128 == half transparent
1043 for( int i = 0 ; i < 8 ; ++i )
1044 {
1045 gc->Scale(1.08, 1.08); // increase scale by 8%
1046 gc->Translate(5,5);
1047 gc->DrawPath(path);
1048 }
1049
1050 gc->PopState(); // restore saved state
1051 gc->PushState(); // save it again
1052 gc->Translate(400, 200);
1053
1054 gc->DrawText("Rotate", 0, -BASE2);
1055
1056 // Move the origin over to the next location
1057 gc->Translate(0, 75);
1058
1059 // draw our path again, rotating it about the central point,
1060 // and changing colors as we go
1061 for ( int angle = 0 ; angle < 360 ; angle += 30 )
1062 {
1063 gc->PushState(); // save this new current state so we can
1064 // pop back to it at the end of the loop
1065 wxImage::RGBValue val = wxImage::HSVtoRGB(wxImage::HSVValue(float(angle)/360, 1, 1));
1066 gc->SetBrush(wxBrush(wxColour(val.red, val.green, val.blue, 64)));
1067 gc->SetPen(wxPen(wxColour(val.red, val.green, val.blue, 128)));
1068
1069 // use translate to artfully reposition each drawn path
1070 gc->Translate(1.5 * BASE2 * cos(DegToRad(angle)),
1071 1.5 * BASE2 * sin(DegToRad(angle)));
1072
1073 // use Rotate to rotate the path
1074 gc->Rotate(DegToRad(angle));
1075
1076 // now draw it
1077 gc->DrawPath(path);
1078 gc->PopState();
1079 }
1080 gc->PopState();
1081 }
1082 #endif
1083
1084 void MyCanvas::DrawCircles(wxDC& dc)
1085 {
1086 int x = 100,
1087 y = 100,
1088 r = 20;
1089
1090 dc.SetPen( *wxRED_PEN );
1091 dc.SetBrush( *wxGREEN_BRUSH );
1092
1093 dc.DrawText(_T("Some circles"), 0, y);
1094 dc.DrawCircle(x, y, r);
1095 dc.DrawCircle(x + 2*r, y, r);
1096 dc.DrawCircle(x + 4*r, y, r);
1097
1098 y += 2*r;
1099 dc.DrawText(_T("And ellipses"), 0, y);
1100 dc.DrawEllipse(x - r, y, 2*r, r);
1101 dc.DrawEllipse(x + r, y, 2*r, r);
1102 dc.DrawEllipse(x + 3*r, y, 2*r, r);
1103
1104 y += 2*r;
1105 dc.DrawText(_T("And arcs"), 0, y);
1106 dc.DrawArc(x - r, y, x + r, y, x, y);
1107 dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
1108 dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
1109
1110 y += 2*r;
1111 dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
1112 dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
1113 dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
1114 dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
1115
1116 // same as above, just transparent brush
1117
1118 dc.SetPen( *wxRED_PEN );
1119 dc.SetBrush( *wxTRANSPARENT_BRUSH );
1120
1121 y += 2*r;
1122 dc.DrawText(_T("Some circles"), 0, y);
1123 dc.DrawCircle(x, y, r);
1124 dc.DrawCircle(x + 2*r, y, r);
1125 dc.DrawCircle(x + 4*r, y, r);
1126
1127 y += 2*r;
1128 dc.DrawText(_T("And ellipses"), 0, y);
1129 dc.DrawEllipse(x - r, y, 2*r, r);
1130 dc.DrawEllipse(x + r, y, 2*r, r);
1131 dc.DrawEllipse(x + 3*r, y, 2*r, r);
1132
1133 y += 2*r;
1134 dc.DrawText(_T("And arcs"), 0, y);
1135 dc.DrawArc(x - r, y, x + r, y, x, y);
1136 dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
1137 dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
1138
1139 y += 2*r;
1140 dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
1141 dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
1142 dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
1143 dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
1144
1145 }
1146
1147 void MyCanvas::DrawSplines(wxDC& dc)
1148 {
1149 #if wxUSE_SPLINES
1150 dc.DrawText(_T("Some splines"), 10, 5);
1151
1152 // values are hardcoded rather than randomly generated
1153 // so the output can be compared between native
1154 // implementations on platforms with different random
1155 // generators
1156
1157 const int R = 300;
1158 const wxPoint center( R + 20, R + 20 );
1159 const int angles[7] = { 0, 10, 33, 77, 13, 145, 90 };
1160 const int radii[5] = { 100 , 59, 85, 33, 90 };
1161 const int n = 200;
1162 wxPoint pts[n];
1163
1164 // background spline calculation
1165 unsigned int radius_pos = 0;
1166 unsigned int angle_pos = 0;
1167 int angle = 0;
1168 for ( int i = 0; i < n; i++ )
1169 {
1170 angle += angles[ angle_pos ];
1171 int r = R * radii[ radius_pos ] / 100;
1172 pts[ i ].x = center.x + (wxCoord)( r * cos( M_PI * angle / 180.0) );
1173 pts[ i ].y = center.y + (wxCoord)( r * sin( M_PI * angle / 180.0) );
1174
1175 angle_pos++;
1176 if ( angle_pos >= WXSIZEOF(angles) ) angle_pos = 0;
1177
1178 radius_pos++;
1179 if ( radius_pos >= WXSIZEOF(radii) ) radius_pos = 0;
1180 }
1181
1182 // background spline drawing
1183 dc.SetPen(*wxRED_PEN);
1184 dc.DrawSpline(WXSIZEOF(pts), pts);
1185
1186 // less detailed spline calculation
1187 wxPoint letters[4][5];
1188 // w
1189 letters[0][0] = wxPoint( 0,1); // O O
1190 letters[0][1] = wxPoint( 1,3); // * *
1191 letters[0][2] = wxPoint( 2,2); // * O *
1192 letters[0][3] = wxPoint( 3,3); // * * * *
1193 letters[0][4] = wxPoint( 4,1); // O O
1194 // x1
1195 letters[1][0] = wxPoint( 5,1); // O*O
1196 letters[1][1] = wxPoint( 6,1); // *
1197 letters[1][2] = wxPoint( 7,2); // O
1198 letters[1][3] = wxPoint( 8,3); // *
1199 letters[1][4] = wxPoint( 9,3); // O*O
1200 // x2
1201 letters[2][0] = wxPoint( 5,3); // O*O
1202 letters[2][1] = wxPoint( 6,3); // *
1203 letters[2][2] = wxPoint( 7,2); // O
1204 letters[2][3] = wxPoint( 8,1); // *
1205 letters[2][4] = wxPoint( 9,1); // O*O
1206 // W
1207 letters[3][0] = wxPoint(10,0); // O O
1208 letters[3][1] = wxPoint(11,3); // * *
1209 letters[3][2] = wxPoint(12,1); // * O *
1210 letters[3][3] = wxPoint(13,3); // * * * *
1211 letters[3][4] = wxPoint(14,0); // O O
1212
1213 const int dx = 2 * R / letters[3][4].x;
1214 const int h[4] = { -R/2, 0, R/4, R/2 };
1215
1216 for ( int m = 0; m < 4; m++ )
1217 {
1218 for ( int n = 0; n < 5; n++ )
1219 {
1220 letters[m][n].x = center.x - R + letters[m][n].x * dx;
1221 letters[m][n].y = center.y + h[ letters[m][n].y ];
1222 }
1223
1224 dc.SetPen( wxPen( wxT("blue"), 1, wxDOT) );
1225 dc.DrawLines(5, letters[m]);
1226 dc.SetPen( wxPen( wxT("black"), 4, wxSOLID) );
1227 dc.DrawSpline(5, letters[m]);
1228 }
1229
1230 #else
1231 dc.DrawText(_T("Splines not supported."), 10, 5);
1232 #endif
1233 }
1234
1235 void MyCanvas::DrawGradients(wxDC& dc)
1236 {
1237 static const int TEXT_HEIGHT = 15;
1238
1239 // LHS: linear
1240 wxRect r(10, 10, 50, 50);
1241 dc.DrawText(_T("wxRIGHT"), r.x, r.y);
1242 r.Offset(0, TEXT_HEIGHT);
1243 dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxRIGHT);
1244
1245 r.Offset(0, r.height + 10);
1246 dc.DrawText(_T("wxLEFT"), r.x, r.y);
1247 r.Offset(0, TEXT_HEIGHT);
1248 dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxLEFT);
1249
1250 r.Offset(0, r.height + 10);
1251 dc.DrawText(_T("wxDOWN"), r.x, r.y);
1252 r.Offset(0, TEXT_HEIGHT);
1253 dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxDOWN);
1254
1255 r.Offset(0, r.height + 10);
1256 dc.DrawText(_T("wxUP"), r.x, r.y);
1257 r.Offset(0, TEXT_HEIGHT);
1258 dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxUP);
1259
1260
1261 // RHS: concentric
1262 r = wxRect(200, 10, 50, 50);
1263 dc.DrawText(_T("Blue inside"), r.x, r.y);
1264 r.Offset(0, TEXT_HEIGHT);
1265 dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE);
1266
1267 r.Offset(0, r.height + 10);
1268 dc.DrawText(_T("White inside"), r.x, r.y);
1269 r.Offset(0, TEXT_HEIGHT);
1270 dc.GradientFillConcentric(r, *wxWHITE, *wxBLUE);
1271
1272 r.Offset(0, r.height + 10);
1273 dc.DrawText(_T("Blue in top left corner"), r.x, r.y);
1274 r.Offset(0, TEXT_HEIGHT);
1275 dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(0, 0));
1276
1277 r.Offset(0, r.height + 10);
1278 dc.DrawText(_T("Blue in bottom right corner"), r.x, r.y);
1279 r.Offset(0, TEXT_HEIGHT);
1280 dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(r.width, r.height));
1281
1282 // check that the area filled by the gradient is exactly the interior of
1283 // the rectangle
1284 r.x = 350;
1285 r.y = 30;
1286 dc.DrawText("The interior should be filled but", r.x, r.y);
1287 r.y += 15;
1288 dc.DrawText(" the red border should remain visible:", r.x, r.y);
1289 r.y += 15;
1290
1291 r.width =
1292 r.height = 50;
1293 wxRect r2 = r;
1294 r2.x += 60;
1295 wxRect r3 = r;
1296 r3.y += 60;
1297 wxRect r4 = r2;
1298 r4.y += 60;
1299 dc.SetPen(wxPen(wxColour(255, 0, 0)));
1300 dc.DrawRectangle(r);
1301 r.Deflate(1);
1302 dc.GradientFillLinear(r, wxColour(0,255,0), wxColour(0,0,0), wxNORTH);
1303 dc.DrawRectangle(r2);
1304 r2.Deflate(1);
1305 dc.GradientFillLinear(r2, wxColour(0,0,0), wxColour(0,255,0), wxSOUTH);
1306 dc.DrawRectangle(r3);
1307 r3.Deflate(1);
1308 dc.GradientFillLinear(r3, wxColour(0,255,0), wxColour(0,0,0), wxEAST);
1309 dc.DrawRectangle(r4);
1310 r4.Deflate(1);
1311 dc.GradientFillLinear(r4, wxColour(0,0,0), wxColour(0,255,0), wxWEST);
1312 }
1313
1314 void MyCanvas::DrawRegions(wxDC& dc)
1315 {
1316 dc.DrawText(_T("You should see a red rect partly covered by a cyan one ")
1317 _T("on the left"), 10, 5);
1318 dc.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
1319 10, 5 + dc.GetCharHeight());
1320 dc.DrawText(_T("The second copy should be identical but right part of it ")
1321 _T("should be offset by 10 pixels."),
1322 10, 5 + 2*dc.GetCharHeight());
1323
1324 DrawRegionsHelper(dc, 10, true);
1325 DrawRegionsHelper(dc, 350, false);
1326 }
1327
1328 void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime)
1329 {
1330 wxCoord y = 100;
1331
1332 dc.DestroyClippingRegion();
1333 dc.SetBrush( *wxWHITE_BRUSH );
1334 dc.SetPen( *wxTRANSPARENT_PEN );
1335 dc.DrawRectangle( x, y, 310, 310 );
1336
1337 dc.SetClippingRegion( x + 10, y + 10, 100, 270 );
1338
1339 dc.SetBrush( *wxRED_BRUSH );
1340 dc.DrawRectangle( x, y, 310, 310 );
1341
1342 dc.SetClippingRegion( x + 10, y + 10, 100, 100 );
1343
1344 dc.SetBrush( *wxCYAN_BRUSH );
1345 dc.DrawRectangle( x, y, 310, 310 );
1346
1347 dc.DestroyClippingRegion();
1348
1349 wxRegion region(x + 110, y + 20, 100, 270);
1350 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
1351 if ( !firstTime )
1352 region.Offset(10, 10);
1353 #endif
1354 dc.SetClippingRegion(region);
1355
1356 dc.SetBrush( *wxGREY_BRUSH );
1357 dc.DrawRectangle( x, y, 310, 310 );
1358
1359 if (m_smile_bmp.Ok())
1360 {
1361 dc.DrawBitmap( m_smile_bmp, x + 150, y + 150, true );
1362 dc.DrawBitmap( m_smile_bmp, x + 130, y + 10, true );
1363 dc.DrawBitmap( m_smile_bmp, x + 130, y + 280, true );
1364 dc.DrawBitmap( m_smile_bmp, x + 100, y + 70, true );
1365 dc.DrawBitmap( m_smile_bmp, x + 200, y + 70, true );
1366 }
1367 }
1368
1369 void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
1370 {
1371 wxPaintDC pdc(this);
1372
1373 #if wxUSE_GRAPHICS_CONTEXT
1374 wxGCDC gdc( pdc ) ;
1375 wxDC &dc = m_useContext ? (wxDC&) gdc : (wxDC&) pdc ;
1376 #else
1377 wxDC &dc = pdc ;
1378 #endif
1379
1380 PrepareDC(dc);
1381
1382 m_owner->PrepareDC(dc);
1383
1384 dc.SetBackgroundMode( m_owner->m_backgroundMode );
1385 if ( m_owner->m_backgroundBrush.Ok() )
1386 dc.SetBackground( m_owner->m_backgroundBrush );
1387 if ( m_owner->m_colourForeground.Ok() )
1388 dc.SetTextForeground( m_owner->m_colourForeground );
1389 if ( m_owner->m_colourBackground.Ok() )
1390 dc.SetTextBackground( m_owner->m_colourBackground );
1391
1392 if ( m_owner->m_textureBackground) {
1393 if ( ! m_owner->m_backgroundBrush.Ok() ) {
1394 wxColour clr(0,128,0);
1395 wxBrush b(clr, wxSOLID);
1396 dc.SetBackground(b);
1397 }
1398 }
1399
1400 if ( m_clip )
1401 dc.SetClippingRegion(100, 100, 100, 100);
1402
1403 dc.Clear();
1404
1405 if ( m_owner->m_textureBackground )
1406 {
1407 dc.SetPen(*wxMEDIUM_GREY_PEN);
1408 for ( int i = 0; i < 200; i++ )
1409 dc.DrawLine(0, i*10, i*10, 0);
1410 }
1411
1412 switch ( m_show )
1413 {
1414 case Show_Default:
1415 DrawDefault(dc);
1416 break;
1417
1418 case Show_Circles:
1419 DrawCircles(dc);
1420 break;
1421
1422 case Show_Splines:
1423 DrawSplines(dc);
1424 break;
1425
1426 case Show_Regions:
1427 DrawRegions(dc);
1428 break;
1429
1430 case Show_Text:
1431 DrawText(dc);
1432 break;
1433
1434 case Show_Lines:
1435 DrawTestLines( 0, 100, 0, dc );
1436 DrawTestLines( 0, 320, 1, dc );
1437 DrawTestLines( 0, 540, 2, dc );
1438 DrawTestLines( 0, 760, 6, dc );
1439 break;
1440
1441 case Show_Brushes:
1442 DrawTestBrushes(dc);
1443 break;
1444
1445 case Show_Polygons:
1446 DrawTestPoly(dc);
1447 break;
1448
1449 case Show_Mask:
1450 DrawImages(dc, Draw_Normal);
1451 break;
1452
1453 case Show_Mask_Stretch:
1454 DrawImages(dc, Draw_Stretch);
1455 break;
1456
1457 case Show_Ops:
1458 DrawWithLogicalOps(dc);
1459 break;
1460
1461 #if wxUSE_GRAPHICS_CONTEXT
1462 case Show_Alpha:
1463 DrawAlpha(dc);
1464 break;
1465 case Show_Graphics:
1466 DrawGraphics(gdc.GetGraphicsContext());
1467 break;
1468 #endif
1469
1470 case Show_Gradient:
1471 DrawGradients(dc);
1472 break;
1473
1474 default:
1475 break;
1476 }
1477 }
1478
1479 void MyCanvas::OnMouseMove(wxMouseEvent &event)
1480 {
1481 #if wxUSE_STATUSBAR
1482 wxClientDC dc(this);
1483 PrepareDC(dc);
1484 m_owner->PrepareDC(dc);
1485
1486 wxPoint pos = event.GetPosition();
1487 long x = dc.DeviceToLogicalX( pos.x );
1488 long y = dc.DeviceToLogicalY( pos.y );
1489 wxString str;
1490 str.Printf( wxT("Current mouse position: %d,%d"), (int)x, (int)y );
1491 m_owner->SetStatusText( str );
1492 #else
1493 wxUnusedVar(event);
1494 #endif // wxUSE_STATUSBAR
1495 }
1496
1497 // ----------------------------------------------------------------------------
1498 // MyFrame
1499 // ----------------------------------------------------------------------------
1500
1501 // the event tables connect the wxWidgets events with the functions (event
1502 // handlers) which process them. It can be also done at run-time, but for the
1503 // simple menu events like this the static method is much simpler.
1504 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
1505 EVT_MENU (File_Quit, MyFrame::OnQuit)
1506 EVT_MENU (File_About, MyFrame::OnAbout)
1507 EVT_MENU (File_Clip, MyFrame::OnClip)
1508 #if wxUSE_GRAPHICS_CONTEXT
1509 EVT_MENU (File_GraphicContext, MyFrame::OnGraphicContext)
1510 #endif
1511
1512 EVT_MENU_RANGE(MenuShow_First, MenuShow_Last, MyFrame::OnShow)
1513
1514 EVT_MENU_RANGE(MenuOption_First, MenuOption_Last, MyFrame::OnOption)
1515 END_EVENT_TABLE()
1516
1517 // frame constructor
1518 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
1519 : wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size,
1520 wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
1521 {
1522 // set the frame icon
1523 SetIcon(wxICON(mondrian));
1524
1525 wxMenu *menuFile = new wxMenu;
1526 menuFile->Append(File_ShowDefault, _T("&Default screen\tF1"));
1527 menuFile->Append(File_ShowText, _T("&Text screen\tF2"));
1528 menuFile->Append(File_ShowLines, _T("&Lines screen\tF3"));
1529 menuFile->Append(File_ShowBrushes, _T("&Brushes screen\tF4"));
1530 menuFile->Append(File_ShowPolygons, _T("&Polygons screen\tF5"));
1531 menuFile->Append(File_ShowMask, _T("&Mask screen\tF6"));
1532 menuFile->Append(File_ShowMaskStretch, _T("1/&2 scaled mask\tShift-F6"));
1533 menuFile->Append(File_ShowOps, _T("&ROP screen\tF7"));
1534 menuFile->Append(File_ShowRegions, _T("Re&gions screen\tF8"));
1535 menuFile->Append(File_ShowCircles, _T("&Circles screen\tF9"));
1536 #if wxUSE_GRAPHICS_CONTEXT
1537 menuFile->Append(File_ShowAlpha, _T("&Alpha screen\tF10"));
1538 #endif
1539 menuFile->Append(File_ShowSplines, _T("&Splines screen\tF11"));
1540 menuFile->Append(File_ShowGradients, _T("&Gradients screen\tF12"));
1541 #if wxUSE_GRAPHICS_CONTEXT
1542 menuFile->Append(File_ShowGraphics, _T("&Graphics screen\tF13"));
1543 #endif
1544 menuFile->AppendSeparator();
1545 menuFile->AppendCheckItem(File_Clip, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
1546 #if wxUSE_GRAPHICS_CONTEXT
1547 menuFile->AppendCheckItem(File_GraphicContext, _T("&Use GraphicContext\tCtrl-Y"), _T("Use GraphicContext"));
1548 #endif
1549 menuFile->AppendSeparator();
1550 menuFile->Append(File_About, _T("&About...\tCtrl-A"), _T("Show about dialog"));
1551 menuFile->AppendSeparator();
1552 menuFile->Append(File_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
1553
1554 wxMenu *menuMapMode = new wxMenu;
1555 menuMapMode->Append( MapMode_Text, _T("&TEXT map mode") );
1556 menuMapMode->Append( MapMode_Lometric, _T("&LOMETRIC map mode") );
1557 menuMapMode->Append( MapMode_Twips, _T("T&WIPS map mode") );
1558 menuMapMode->Append( MapMode_Points, _T("&POINTS map mode") );
1559 menuMapMode->Append( MapMode_Metric, _T("&METRIC map mode") );
1560
1561 wxMenu *menuUserScale = new wxMenu;
1562 menuUserScale->Append( UserScale_StretchHoriz, _T("Stretch &horizontally\tCtrl-H") );
1563 menuUserScale->Append( UserScale_ShrinkHoriz, _T("Shrin&k horizontally\tCtrl-G") );
1564 menuUserScale->Append( UserScale_StretchVertic, _T("Stretch &vertically\tCtrl-V") );
1565 menuUserScale->Append( UserScale_ShrinkVertic, _T("&Shrink vertically\tCtrl-W") );
1566 menuUserScale->AppendSeparator();
1567 menuUserScale->Append( UserScale_Restore, _T("&Restore to normal\tCtrl-0") );
1568
1569 wxMenu *menuAxis = new wxMenu;
1570 menuAxis->AppendCheckItem( AxisMirror_Horiz, _T("Mirror horizontally\tCtrl-M") );
1571 menuAxis->AppendCheckItem( AxisMirror_Vertic, _T("Mirror vertically\tCtrl-N") );
1572
1573 wxMenu *menuLogical = new wxMenu;
1574 menuLogical->Append( LogicalOrigin_MoveDown, _T("Move &down\tCtrl-D") );
1575 menuLogical->Append( LogicalOrigin_MoveUp, _T("Move &up\tCtrl-U") );
1576 menuLogical->Append( LogicalOrigin_MoveLeft, _T("Move &right\tCtrl-L") );
1577 menuLogical->Append( LogicalOrigin_MoveRight, _T("Move &left\tCtrl-R") );
1578 menuLogical->AppendSeparator();
1579 menuLogical->Append( LogicalOrigin_Set, _T("Set to (&100, 100)\tShift-Ctrl-1") );
1580 menuLogical->Append( LogicalOrigin_Restore, _T("&Restore to normal\tShift-Ctrl-0") );
1581
1582 wxMenu *menuColour = new wxMenu;
1583 #if wxUSE_COLOURDLG
1584 menuColour->Append( Colour_TextForeground, _T("Text &foreground...") );
1585 menuColour->Append( Colour_TextBackground, _T("Text &background...") );
1586 menuColour->Append( Colour_Background, _T("Background &colour...") );
1587 #endif // wxUSE_COLOURDLG
1588 menuColour->AppendCheckItem( Colour_BackgroundMode, _T("&Opaque/transparent\tCtrl-B") );
1589 menuColour->AppendCheckItem( Colour_TextureBackgound, _T("Draw textured back&ground\tCtrl-T") );
1590
1591 // now append the freshly created menu to the menu bar...
1592 wxMenuBar *menuBar = new wxMenuBar;
1593 menuBar->Append(menuFile, _T("&File"));
1594 menuBar->Append(menuMapMode, _T("&Mode"));
1595 menuBar->Append(menuUserScale, _T("&Scale"));
1596 menuBar->Append(menuAxis, _T("&Axis"));
1597 menuBar->Append(menuLogical, _T("&Origin"));
1598 menuBar->Append(menuColour, _T("&Colours"));
1599
1600 // ... and attach this menu bar to the frame
1601 SetMenuBar(menuBar);
1602
1603 #if wxUSE_STATUSBAR
1604 CreateStatusBar(2);
1605 SetStatusText(_T("Welcome to wxWidgets!"));
1606 #endif // wxUSE_STATUSBAR
1607
1608 m_mapMode = wxMM_TEXT;
1609 m_xUserScale = 1.0;
1610 m_yUserScale = 1.0;
1611 m_xLogicalOrigin = 0;
1612 m_yLogicalOrigin = 0;
1613 m_xAxisReversed =
1614 m_yAxisReversed = false;
1615 m_backgroundMode = wxSOLID;
1616 m_colourForeground = *wxRED;
1617 m_colourBackground = *wxBLUE;
1618 m_textureBackground = false;
1619
1620 m_canvas = new MyCanvas( this );
1621 m_canvas->SetScrollbars( 10, 10, 100, 240 );
1622 }
1623
1624 // event handlers
1625
1626 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1627 {
1628 // true is to force the frame to close
1629 Close(true);
1630 }
1631
1632 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1633 {
1634 wxString msg;
1635 msg.Printf( wxT("This is the about dialog of the drawing sample.\n")
1636 wxT("This sample tests various primitive drawing functions\n")
1637 wxT("(without any attempts to prevent flicker).\n")
1638 wxT("Copyright (c) Robert Roebling 1999")
1639 );
1640
1641 wxMessageBox(msg, _T("About Drawing"), wxOK | wxICON_INFORMATION, this);
1642 }
1643
1644 void MyFrame::OnClip(wxCommandEvent& event)
1645 {
1646 m_canvas->Clip(event.IsChecked());
1647 }
1648
1649 #if wxUSE_GRAPHICS_CONTEXT
1650 void MyFrame::OnGraphicContext(wxCommandEvent& event)
1651 {
1652 m_canvas->UseGraphicContext(event.IsChecked());
1653 }
1654 #endif
1655
1656 void MyFrame::OnShow(wxCommandEvent& event)
1657 {
1658 m_canvas->ToShow((ScreenToShow)(event.GetId() - MenuShow_First));
1659 }
1660
1661 void MyFrame::OnOption(wxCommandEvent& event)
1662 {
1663 switch (event.GetId())
1664 {
1665 case MapMode_Text:
1666 m_mapMode = wxMM_TEXT;
1667 break;
1668 case MapMode_Lometric:
1669 m_mapMode = wxMM_LOMETRIC;
1670 break;
1671 case MapMode_Twips:
1672 m_mapMode = wxMM_TWIPS;
1673 break;
1674 case MapMode_Points:
1675 m_mapMode = wxMM_POINTS;
1676 break;
1677 case MapMode_Metric:
1678 m_mapMode = wxMM_METRIC;
1679 break;
1680
1681 case LogicalOrigin_MoveDown:
1682 m_yLogicalOrigin += 10;
1683 break;
1684 case LogicalOrigin_MoveUp:
1685 m_yLogicalOrigin -= 10;
1686 break;
1687 case LogicalOrigin_MoveLeft:
1688 m_xLogicalOrigin += 10;
1689 break;
1690 case LogicalOrigin_MoveRight:
1691 m_xLogicalOrigin -= 10;
1692 break;
1693 case LogicalOrigin_Set:
1694 m_xLogicalOrigin =
1695 m_yLogicalOrigin = -100;
1696 break;
1697 case LogicalOrigin_Restore:
1698 m_xLogicalOrigin =
1699 m_yLogicalOrigin = 0;
1700 break;
1701
1702 case UserScale_StretchHoriz:
1703 m_xUserScale *= 1.10;
1704 break;
1705 case UserScale_ShrinkHoriz:
1706 m_xUserScale /= 1.10;
1707 break;
1708 case UserScale_StretchVertic:
1709 m_yUserScale *= 1.10;
1710 break;
1711 case UserScale_ShrinkVertic:
1712 m_yUserScale /= 1.10;
1713 break;
1714 case UserScale_Restore:
1715 m_xUserScale =
1716 m_yUserScale = 1.0;
1717 break;
1718
1719 case AxisMirror_Vertic:
1720 m_yAxisReversed = !m_yAxisReversed;
1721 break;
1722 case AxisMirror_Horiz:
1723 m_xAxisReversed = !m_xAxisReversed;
1724 break;
1725
1726 #if wxUSE_COLOURDLG
1727 case Colour_TextForeground:
1728 m_colourForeground = SelectColour();
1729 break;
1730 case Colour_TextBackground:
1731 m_colourBackground = SelectColour();
1732 break;
1733 case Colour_Background:
1734 {
1735 wxColour col = SelectColour();
1736 if ( col.Ok() )
1737 {
1738 m_backgroundBrush.SetColour(col);
1739 }
1740 }
1741 break;
1742 #endif // wxUSE_COLOURDLG
1743
1744 case Colour_BackgroundMode:
1745 m_backgroundMode = m_backgroundMode == wxSOLID ? wxTRANSPARENT
1746 : wxSOLID;
1747 break;
1748
1749 case Colour_TextureBackgound:
1750 m_textureBackground = ! m_textureBackground;
1751 break;
1752
1753 default:
1754 // skip Refresh()
1755 return;
1756 }
1757
1758 m_canvas->Refresh();
1759 }
1760
1761 void MyFrame::PrepareDC(wxDC& dc)
1762 {
1763 dc.SetLogicalOrigin( m_xLogicalOrigin, m_yLogicalOrigin );
1764 dc.SetAxisOrientation( !m_xAxisReversed, m_yAxisReversed );
1765 dc.SetUserScale( m_xUserScale, m_yUserScale );
1766 dc.SetMapMode( m_mapMode );
1767 }
1768
1769 #if wxUSE_COLOURDLG
1770 wxColour MyFrame::SelectColour()
1771 {
1772 wxColour col;
1773 wxColourData data;
1774 wxColourDialog dialog(this, &data);
1775
1776 if ( dialog.ShowModal() == wxID_OK )
1777 {
1778 col = dialog.GetColourData().GetColour();
1779 }
1780
1781 return col;
1782 }
1783 #endif // wxUSE_COLOURDLG