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