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