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