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