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