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