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