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