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