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