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