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