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