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