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