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