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