]> git.saurik.com Git - wxWidgets.git/blob - samples/drawing/drawing.cpp
drag-and-drop adding of controls to test window
[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
37 #define wxTEST_GRAPHICS 1
38
39 #if wxTEST_GRAPHICS
40 #include "wx/graphics.h"
41 #if wxUSE_GRAPHICS_CONTEXT == 0
42 #undef wxTEST_GRAPHICS
43 #define wxTEST_GRAPHICS 0
44 #endif
45 #else
46 #undef wxUSE_GRAPHICS_CONTEXT
47 #define wxUSE_GRAPHICS_CONTEXT 0
48 #endif
49
50 // ----------------------------------------------------------------------------
51 // ressources
52 // ----------------------------------------------------------------------------
53
54 // the application icon
55 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
56 #include "mondrian.xpm"
57 #endif
58
59 // ----------------------------------------------------------------------------
60 // constants
61 // ----------------------------------------------------------------------------
62
63 // what do we show on screen (there are too many shapes to put them all on
64 // screen simultaneously)
65 enum ScreenToShow
66 {
67 Show_Default,
68 Show_Text,
69 Show_Lines,
70 Show_Brushes,
71 Show_Polygons,
72 Show_Mask,
73 Show_Mask_Stretch,
74 Show_Ops,
75 Show_Regions,
76 Show_Circles,
77 Show_Splines,
78 #if wxUSE_GRAPHICS_CONTEXT
79 Show_Alpha,
80 #endif
81 Show_Gradient,
82 Show_Max
83 };
84
85 // ----------------------------------------------------------------------------
86 // global variables
87 // ----------------------------------------------------------------------------
88
89 static wxBitmap *gs_bmpNoMask = NULL,
90 *gs_bmpWithColMask = NULL,
91 *gs_bmpMask = NULL,
92 *gs_bmpWithMask = NULL,
93 *gs_bmp4 = NULL,
94 *gs_bmp4_mono = NULL,
95 *gs_bmp36 = NULL;
96
97 // ----------------------------------------------------------------------------
98 // private classes
99 // ----------------------------------------------------------------------------
100
101 // Define a new application type, each program should derive a class from wxApp
102 class MyApp : public wxApp
103 {
104 public:
105 // override base class virtuals
106 // ----------------------------
107
108 // this one is called on application startup and is a good place for the app
109 // initialization (doing it here and not in the ctor allows to have an error
110 // return: if OnInit() returns false, the application terminates)
111 virtual bool OnInit();
112
113 virtual int OnExit() { DeleteBitmaps(); return 0; }
114
115 protected:
116 void DeleteBitmaps();
117
118 bool LoadImages();
119 };
120
121 class MyCanvas;
122
123 // Define a new frame type: this is going to be our main frame
124 class MyFrame : public wxFrame
125 {
126 public:
127 // ctor(s)
128 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
129
130 // event handlers (these functions should _not_ be virtual)
131 void OnQuit(wxCommandEvent& event);
132 void OnAbout(wxCommandEvent& event);
133 void OnClip(wxCommandEvent& event);
134 #if wxUSE_GRAPHICS_CONTEXT
135 void OnGraphicContext(wxCommandEvent& event);
136 #endif
137 void OnShow(wxCommandEvent &event);
138 void OnOption(wxCommandEvent &event);
139
140 #if wxUSE_COLOURDLG
141 wxColour SelectColour();
142 #endif // wxUSE_COLOURDLG
143 void PrepareDC(wxDC& dc);
144
145 int m_backgroundMode;
146 int m_textureBackground;
147 int m_mapMode;
148 double m_xUserScale;
149 double m_yUserScale;
150 int m_xLogicalOrigin;
151 int m_yLogicalOrigin;
152 bool m_xAxisReversed,
153 m_yAxisReversed;
154 wxColour m_colourForeground, // these are _text_ colours
155 m_colourBackground;
156 wxBrush m_backgroundBrush;
157 MyCanvas *m_canvas;
158
159 private:
160 // any class wishing to process wxWidgets events must use this macro
161 DECLARE_EVENT_TABLE()
162 };
163
164 // define a scrollable canvas for drawing onto
165 class MyCanvas: public wxScrolledWindow
166 {
167 public:
168 MyCanvas( MyFrame *parent );
169
170 void OnPaint(wxPaintEvent &event);
171 void OnMouseMove(wxMouseEvent &event);
172
173 void ToShow(ScreenToShow show) { m_show = show; Refresh(); }
174
175 // set or remove the clipping region
176 void Clip(bool clip) { m_clip = clip; Refresh(); }
177 #if wxUSE_GRAPHICS_CONTEXT
178 void UseGraphicContext(bool use) { m_useContext = use; Refresh(); }
179 #endif
180
181 protected:
182 enum DrawMode
183 {
184 Draw_Normal,
185 Draw_Stretch
186 };
187
188 void DrawTestLines( int x, int y, int width, wxDC &dc );
189 void DrawTestPoly(wxDC& dc);
190 void DrawTestBrushes(wxDC& dc);
191 void DrawText(wxDC& dc);
192 void DrawImages(wxDC& dc, DrawMode mode);
193 void DrawWithLogicalOps(wxDC& dc);
194 #if wxUSE_GRAPHICS_CONTEXT
195 void DrawAlpha(wxDC& dc);
196 #endif
197 void DrawRegions(wxDC& dc);
198 void DrawCircles(wxDC& dc);
199 void DrawSplines(wxDC& dc);
200 void DrawDefault(wxDC& dc);
201 void DrawGradients(wxDC& dc);
202
203 void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime);
204
205 private:
206 MyFrame *m_owner;
207
208 ScreenToShow m_show;
209 wxBitmap m_smile_bmp;
210 wxIcon m_std_icon;
211 bool m_clip;
212 #if wxUSE_GRAPHICS_CONTEXT
213 bool m_useContext ;
214 #endif
215
216 DECLARE_EVENT_TABLE()
217 };
218
219 // ----------------------------------------------------------------------------
220 // constants
221 // ----------------------------------------------------------------------------
222
223 // IDs for the controls and the menu commands
224 enum
225 {
226 // menu items
227 File_Quit = wxID_EXIT,
228 File_About = wxID_ABOUT,
229
230 MenuShow_First = wxID_HIGHEST,
231 File_ShowDefault = MenuShow_First,
232 File_ShowText,
233 File_ShowLines,
234 File_ShowBrushes,
235 File_ShowPolygons,
236 File_ShowMask,
237 File_ShowMaskStretch,
238 File_ShowOps,
239 File_ShowRegions,
240 File_ShowCircles,
241 File_ShowSplines,
242 #if wxUSE_GRAPHICS_CONTEXT
243 File_ShowAlpha,
244 #endif
245 File_ShowGradients,
246 MenuShow_Last = File_ShowGradients,
247
248 File_Clip,
249 #if wxUSE_GRAPHICS_CONTEXT
250 File_GraphicContext,
251 #endif
252
253 MenuOption_First,
254
255 MapMode_Text = MenuOption_First,
256 MapMode_Lometric,
257 MapMode_Twips,
258 MapMode_Points,
259 MapMode_Metric,
260
261 UserScale_StretchHoriz,
262 UserScale_ShrinkHoriz,
263 UserScale_StretchVertic,
264 UserScale_ShrinkVertic,
265 UserScale_Restore,
266
267 AxisMirror_Horiz,
268 AxisMirror_Vertic,
269
270 LogicalOrigin_MoveDown,
271 LogicalOrigin_MoveUp,
272 LogicalOrigin_MoveLeft,
273 LogicalOrigin_MoveRight,
274 LogicalOrigin_Set,
275 LogicalOrigin_Restore,
276
277 #if wxUSE_COLOURDLG
278 Colour_TextForeground,
279 Colour_TextBackground,
280 Colour_Background,
281 #endif // wxUSE_COLOURDLG
282 Colour_BackgroundMode,
283 Colour_TextureBackgound,
284
285 MenuOption_Last = Colour_TextureBackgound
286 };
287
288 // ----------------------------------------------------------------------------
289 // event tables and other macros for wxWidgets
290 // ----------------------------------------------------------------------------
291
292
293 // Create a new application object: this macro will allow wxWidgets to create
294 // the application object during program execution (it's better than using a
295 // static object for many reasons) and also declares the accessor function
296 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
297 // not wxApp)
298 IMPLEMENT_APP(MyApp)
299
300 // ============================================================================
301 // implementation
302 // ============================================================================
303
304 // ----------------------------------------------------------------------------
305 // the application class
306 // ----------------------------------------------------------------------------
307
308 bool MyApp::LoadImages()
309 {
310 gs_bmpNoMask = new wxBitmap;
311 gs_bmpWithColMask = new wxBitmap;
312 gs_bmpMask = new wxBitmap;
313 gs_bmpWithMask = new wxBitmap;
314 gs_bmp4 = new wxBitmap;
315 gs_bmp4_mono = new wxBitmap;
316 gs_bmp36 = new wxBitmap;
317
318 wxPathList pathList;
319 pathList.Add(_T("."));
320 pathList.Add(_T(".."));
321 pathList.Add(_T("../.."));
322
323 wxString path = pathList.FindValidPath(_T("pat4.bmp"));
324 if ( !path )
325 return false;
326
327 /* 4 colour bitmap */
328 gs_bmp4->LoadFile(path, wxBITMAP_TYPE_BMP);
329 /* turn into mono-bitmap */
330 gs_bmp4_mono->LoadFile(path, wxBITMAP_TYPE_BMP);
331 wxMask* mask4 = new wxMask(*gs_bmp4_mono, *wxBLACK);
332 gs_bmp4_mono->SetMask(mask4);
333
334 path = pathList.FindValidPath(_T("pat36.bmp"));
335 if ( !path )
336 return false;
337 gs_bmp36->LoadFile(path, wxBITMAP_TYPE_BMP);
338 wxMask* mask36 = new wxMask(*gs_bmp36, *wxBLACK);
339 gs_bmp36->SetMask(mask36);
340
341 path = pathList.FindValidPath(_T("image.bmp"));
342 if ( !path )
343 return false;
344 gs_bmpNoMask->LoadFile(path, wxBITMAP_TYPE_BMP);
345 gs_bmpWithMask->LoadFile(path, wxBITMAP_TYPE_BMP);
346 gs_bmpWithColMask->LoadFile(path, wxBITMAP_TYPE_BMP);
347
348 path = pathList.FindValidPath(_T("mask.bmp"));
349 if ( !path )
350 return false;
351 gs_bmpMask->LoadFile(path, wxBITMAP_TYPE_BMP);
352
353 wxMask *mask = new wxMask(*gs_bmpMask, *wxBLACK);
354 gs_bmpWithMask->SetMask(mask);
355
356 mask = new wxMask(*gs_bmpWithColMask, *wxWHITE);
357 gs_bmpWithColMask->SetMask(mask);
358
359 return true;
360 }
361
362 // `Main program' equivalent: the program execution "starts" here
363 bool MyApp::OnInit()
364 {
365 if ( !wxApp::OnInit() )
366 return false;
367
368 // Create the main application window
369 MyFrame *frame = new MyFrame(_T("Drawing sample"),
370 wxPoint(50, 50), wxSize(550, 340));
371
372 // Show it and tell the application that it's our main window
373 frame->Show(true);
374 SetTopWindow(frame);
375
376 if ( !LoadImages() )
377 {
378 wxLogError(wxT("Can't load one of the bitmap files needed ")
379 wxT("for this sample from the current or parent ")
380 wxT("directory, please copy them there."));
381
382 // stop here
383 DeleteBitmaps();
384
385 return false;
386 }
387
388 // ok, continue
389 return true;
390 }
391
392 void MyApp::DeleteBitmaps()
393 {
394 delete gs_bmpNoMask;
395 delete gs_bmpWithColMask;
396 delete gs_bmpMask;
397 delete gs_bmpWithMask;
398 delete gs_bmp4;
399 delete gs_bmp4_mono;
400 delete gs_bmp36;
401
402 gs_bmpNoMask = NULL;
403 gs_bmpWithColMask = NULL;
404 gs_bmpMask = NULL;
405 gs_bmpWithMask = NULL;
406 gs_bmp4 = NULL;
407 gs_bmp4_mono = NULL;
408 gs_bmp36 = NULL;
409 }
410
411 // ----------------------------------------------------------------------------
412 // MyCanvas
413 // ----------------------------------------------------------------------------
414
415 // the event tables connect the wxWidgets events with the functions (event
416 // handlers) which process them.
417 BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
418 EVT_PAINT (MyCanvas::OnPaint)
419 EVT_MOTION (MyCanvas::OnMouseMove)
420 END_EVENT_TABLE()
421
422 #include "smile.xpm"
423
424 MyCanvas::MyCanvas(MyFrame *parent)
425 : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
426 wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
427 {
428 m_owner = parent;
429 m_show = Show_Default;
430 m_smile_bmp = wxBitmap(smile_xpm);
431 m_std_icon = wxArtProvider::GetIcon(wxART_INFORMATION);
432 m_clip = false;
433 #if wxUSE_GRAPHICS_CONTEXT
434 m_useContext = false;
435 #endif
436 }
437
438 void MyCanvas::DrawTestBrushes(wxDC& dc)
439 {
440 static const wxCoord WIDTH = 200;
441 static const wxCoord HEIGHT = 80;
442
443 wxCoord x = 10,
444 y = 10;
445
446 dc.SetBrush(wxBrush(*wxGREEN, wxSOLID));
447 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
448 dc.DrawText(_T("Solid green"), x + 10, y + 10);
449
450 y += HEIGHT;
451 dc.SetBrush(wxBrush(*wxRED, wxCROSSDIAG_HATCH));
452 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
453 dc.DrawText(_T("Hatched red"), x + 10, y + 10);
454
455 y += HEIGHT;
456 dc.SetBrush(wxBrush(*gs_bmpMask));
457 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
458 dc.DrawText(_T("Stipple mono"), x + 10, y + 10);
459
460 y += HEIGHT;
461 dc.SetBrush(wxBrush(*gs_bmpNoMask));
462 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
463 dc.DrawText(_T("Stipple colour"), x + 10, y + 10);
464 }
465
466 void MyCanvas::DrawTestPoly(wxDC& dc)
467 {
468 wxBrush brushHatch(*wxRED, wxFDIAGONAL_HATCH);
469 dc.SetBrush(brushHatch);
470
471 wxPoint star[5];
472 star[0] = wxPoint(100, 60);
473 star[1] = wxPoint(60, 150);
474 star[2] = wxPoint(160, 100);
475 star[3] = wxPoint(40, 100);
476 star[4] = wxPoint(140, 150);
477
478 dc.DrawText(_T("You should see two (irregular) stars below, the left one ")
479 _T("hatched"), 10, 10);
480 dc.DrawText(_T("except for the central region and the right ")
481 _T("one entirely hatched"), 10, 30);
482 dc.DrawText(_T("The third star only has a hatched outline"), 10, 50);
483
484 dc.DrawPolygon(WXSIZEOF(star), star, 0, 30);
485 dc.DrawPolygon(WXSIZEOF(star), star, 160, 30, wxWINDING_RULE);
486
487 wxPoint star2[10];
488 star2[0] = wxPoint(0, 100);
489 star2[1] = wxPoint(-59, -81);
490 star2[2] = wxPoint(95, 31);
491 star2[3] = wxPoint(-95, 31);
492 star2[4] = wxPoint(59, -81);
493 star2[5] = wxPoint(0, 80);
494 star2[6] = wxPoint(-47, -64);
495 star2[7] = wxPoint(76, 24);
496 star2[8] = wxPoint(-76, 24);
497 star2[9] = wxPoint(47, -64);
498 int count[2] = {5, 5};
499
500 dc.DrawPolyPolygon(WXSIZEOF(count), count, star2, 450, 150);
501 }
502
503 void MyCanvas::DrawTestLines( int x, int y, int width, wxDC &dc )
504 {
505 dc.SetPen( wxPen( wxT("black"), width, wxSOLID) );
506 dc.SetBrush( *wxRED_BRUSH );
507 dc.DrawText(wxString::Format(wxT("Testing lines of width %d"), width), x + 10, y - 10);
508 dc.DrawRectangle( x+10, y+10, 100, 190 );
509
510 dc.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x + 150, y + 10);
511 dc.SetPen( wxPen( wxT("black"), width, wxSOLID) );
512 dc.DrawLine( x+20, y+20, 100, y+20 );
513 dc.SetPen( wxPen( wxT("black"), width, wxDOT) );
514 dc.DrawLine( x+20, y+30, 100, y+30 );
515 dc.SetPen( wxPen( wxT("black"), width, wxSHORT_DASH) );
516 dc.DrawLine( x+20, y+40, 100, y+40 );
517 dc.SetPen( wxPen( wxT("black"), width, wxLONG_DASH) );
518 dc.DrawLine( x+20, y+50, 100, y+50 );
519 dc.SetPen( wxPen( wxT("black"), width, wxDOT_DASH) );
520 dc.DrawLine( x+20, y+60, 100, y+60 );
521
522 dc.DrawText(_T("Misc hatches"), x + 150, y + 70);
523 dc.SetPen( wxPen( wxT("black"), width, wxBDIAGONAL_HATCH) );
524 dc.DrawLine( x+20, y+70, 100, y+70 );
525 dc.SetPen( wxPen( wxT("black"), width, wxCROSSDIAG_HATCH) );
526 dc.DrawLine( x+20, y+80, 100, y+80 );
527 dc.SetPen( wxPen( wxT("black"), width, wxFDIAGONAL_HATCH) );
528 dc.DrawLine( x+20, y+90, 100, y+90 );
529 dc.SetPen( wxPen( wxT("black"), width, wxCROSS_HATCH) );
530 dc.DrawLine( x+20, y+100, 100, y+100 );
531 dc.SetPen( wxPen( wxT("black"), width, wxHORIZONTAL_HATCH) );
532 dc.DrawLine( x+20, y+110, 100, y+110 );
533 dc.SetPen( wxPen( wxT("black"), width, wxVERTICAL_HATCH) );
534 dc.DrawLine( x+20, y+120, 100, y+120 );
535
536 dc.DrawText(_T("User dash"), x + 150, y + 140);
537 wxPen ud( wxT("black"), width, wxUSER_DASH );
538 wxDash dash1[6];
539 dash1[0] = 8; // Long dash <---------+
540 dash1[1] = 2; // Short gap |
541 dash1[2] = 3; // Short dash |
542 dash1[3] = 2; // Short gap |
543 dash1[4] = 3; // Short dash |
544 dash1[5] = 2; // Short gap and repeat +
545 ud.SetDashes( 6, dash1 );
546 dc.SetPen( ud );
547 dc.DrawLine( x+20, y+140, 100, y+140 );
548 dash1[0] = 5; // Make first dash shorter
549 ud.SetDashes( 6, dash1 );
550 dc.SetPen( ud );
551 dc.DrawLine( x+20, y+150, 100, y+150 );
552 dash1[2] = 5; // Make second dash longer
553 ud.SetDashes( 6, dash1 );
554 dc.SetPen( ud );
555 dc.DrawLine( x+20, y+160, 100, y+160 );
556 dash1[4] = 5; // Make third dash longer
557 ud.SetDashes( 6, dash1 );
558 dc.SetPen( ud );
559 dc.DrawLine( x+20, y+170, 100, y+170 );
560 }
561
562 void MyCanvas::DrawDefault(wxDC& dc)
563 {
564 // mark the origin
565 dc.DrawCircle(0, 0, 10);
566
567 #if !defined(wxMAC_USE_CORE_GRAPHICS) || !wxMAC_USE_CORE_GRAPHICS
568 // GetPixel and FloodFill not supported by Mac OS X CoreGraphics
569 // (FloodFill uses Blit from a non-wxMemoryDC)
570 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
571 dc.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID));
572
573 wxColour tmpColour ;
574 dc.GetPixel(1,1, &tmpColour);
575 dc.FloodFill(1,1, tmpColour, wxFLOOD_SURFACE);
576 #endif
577
578 dc.DrawCheckMark(5, 80, 15, 15);
579 dc.DrawCheckMark(25, 80, 30, 30);
580 dc.DrawCheckMark(60, 80, 60, 60);
581
582 // this is the test for "blitting bitmap into DC damages selected brush" bug
583 wxCoord rectSize = m_std_icon.GetWidth() + 10;
584 wxCoord x = 100;
585 dc.SetPen(*wxTRANSPARENT_PEN);
586 dc.SetBrush( *wxGREEN_BRUSH );
587 dc.DrawRectangle(x, 10, rectSize, rectSize);
588 dc.DrawBitmap(m_std_icon, x + 5, 15, true);
589 x += rectSize + 10;
590 dc.DrawRectangle(x, 10, rectSize, rectSize);
591 dc.DrawIcon(m_std_icon, x + 5, 15);
592 x += rectSize + 10;
593 dc.DrawRectangle(x, 10, rectSize, rectSize);
594
595 // test for "transparent" bitmap drawing (it intersects with the last
596 // rectangle above)
597 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
598
599 if (m_smile_bmp.Ok())
600 dc.DrawBitmap(m_smile_bmp, x + rectSize - 20, rectSize - 10, true);
601
602 dc.SetBrush( *wxBLACK_BRUSH );
603 dc.DrawRectangle( 0, 160, 1000, 300 );
604
605 // draw lines
606 wxBitmap bitmap(20,70);
607 wxMemoryDC memdc;
608 memdc.SelectObject( bitmap );
609 memdc.SetBrush( *wxBLACK_BRUSH );
610 memdc.SetPen( *wxWHITE_PEN );
611 memdc.DrawRectangle(0,0,20,70);
612 memdc.DrawLine( 10,0,10,70 );
613
614 // to the right
615 wxPen pen = *wxRED_PEN;
616 memdc.SetPen(pen);
617 memdc.DrawLine( 10, 5,10, 5 );
618 memdc.DrawLine( 10,10,11,10 );
619 memdc.DrawLine( 10,15,12,15 );
620 memdc.DrawLine( 10,20,13,20 );
621
622 /*
623 memdc.SetPen(*wxRED_PEN);
624 memdc.DrawLine( 12, 5,12, 5 );
625 memdc.DrawLine( 12,10,13,10 );
626 memdc.DrawLine( 12,15,14,15 );
627 memdc.DrawLine( 12,20,15,20 );
628 */
629
630 // same to the left
631 memdc.DrawLine( 10,25,10,25 );
632 memdc.DrawLine( 10,30, 9,30 );
633 memdc.DrawLine( 10,35, 8,35 );
634 memdc.DrawLine( 10,40, 7,40 );
635
636 // XOR draw lines
637 dc.SetPen(*wxWHITE_PEN);
638 memdc.SetLogicalFunction( wxINVERT );
639 memdc.SetPen( *wxWHITE_PEN );
640 memdc.DrawLine( 10,50,10,50 );
641 memdc.DrawLine( 10,55,11,55 );
642 memdc.DrawLine( 10,60,12,60 );
643 memdc.DrawLine( 10,65,13,65 );
644
645 memdc.DrawLine( 12,50,12,50 );
646 memdc.DrawLine( 12,55,13,55 );
647 memdc.DrawLine( 12,60,14,60 );
648 memdc.DrawLine( 12,65,15,65 );
649
650 memdc.SelectObject( wxNullBitmap );
651 dc.DrawBitmap( bitmap, 10, 170 );
652 wxImage image = bitmap.ConvertToImage();
653 image.Rescale( 60,210 );
654 bitmap = wxBitmap(image);
655 dc.DrawBitmap( bitmap, 50, 170 );
656
657 // test the rectangle outline drawing - there should be one pixel between
658 // the rect and the lines
659 dc.SetPen(*wxWHITE_PEN);
660 dc.SetBrush( *wxTRANSPARENT_BRUSH );
661 dc.DrawRectangle(150, 170, 49, 29);
662 dc.DrawRectangle(200, 170, 49, 29);
663 dc.SetPen(*wxWHITE_PEN);
664 dc.DrawLine(250, 210, 250, 170);
665 dc.DrawLine(260, 200, 150, 200);
666
667 // test the rectangle filled drawing - there should be one pixel between
668 // the rect and the lines
669 dc.SetPen(*wxTRANSPARENT_PEN);
670 dc.SetBrush( *wxWHITE_BRUSH );
671 dc.DrawRectangle(300, 170, 49, 29);
672 dc.DrawRectangle(350, 170, 49, 29);
673 dc.SetPen(*wxWHITE_PEN);
674 dc.DrawLine(400, 170, 400, 210);
675 dc.DrawLine(300, 200, 410, 200);
676
677 // a few more tests of this kind
678 dc.SetPen(*wxRED_PEN);
679 dc.SetBrush( *wxWHITE_BRUSH );
680 dc.DrawRectangle(300, 220, 1, 1);
681 dc.DrawRectangle(310, 220, 2, 2);
682 dc.DrawRectangle(320, 220, 3, 3);
683 dc.DrawRectangle(330, 220, 4, 4);
684
685 dc.SetPen(*wxTRANSPARENT_PEN);
686 dc.SetBrush( *wxWHITE_BRUSH );
687 dc.DrawRectangle(300, 230, 1, 1);
688 dc.DrawRectangle(310, 230, 2, 2);
689 dc.DrawRectangle(320, 230, 3, 3);
690 dc.DrawRectangle(330, 230, 4, 4);
691
692 // and now for filled rect with outline
693 dc.SetPen(*wxRED_PEN);
694 dc.SetBrush( *wxWHITE_BRUSH );
695 dc.DrawRectangle(500, 170, 49, 29);
696 dc.DrawRectangle(550, 170, 49, 29);
697 dc.SetPen(*wxWHITE_PEN);
698 dc.DrawLine(600, 170, 600, 210);
699 dc.DrawLine(500, 200, 610, 200);
700
701 // test the rectangle outline drawing - there should be one pixel between
702 // the rect and the lines
703 dc.SetPen(*wxWHITE_PEN);
704 dc.SetBrush( *wxTRANSPARENT_BRUSH );
705 dc.DrawRoundedRectangle(150, 270, 49, 29, 6);
706 dc.DrawRoundedRectangle(200, 270, 49, 29, 6);
707 dc.SetPen(*wxWHITE_PEN);
708 dc.DrawLine(250, 270, 250, 310);
709 dc.DrawLine(150, 300, 260, 300);
710
711 // test the rectangle filled drawing - there should be one pixel between
712 // the rect and the lines
713 dc.SetPen(*wxTRANSPARENT_PEN);
714 dc.SetBrush( *wxWHITE_BRUSH );
715 dc.DrawRoundedRectangle(300, 270, 49, 29, 6);
716 dc.DrawRoundedRectangle(350, 270, 49, 29, 6);
717 dc.SetPen(*wxWHITE_PEN);
718 dc.DrawLine(400, 270, 400, 310);
719 dc.DrawLine(300, 300, 410, 300);
720
721 // Added by JACS to demonstrate bizarre behaviour.
722 // With a size of 70, we get a missing red RHS,
723 // and the height is too small, so we get yellow
724 // showing. With a size of 40, it draws as expected:
725 // it just shows a white rectangle with red outline.
726 int totalWidth = 70;
727 int totalHeight = 70;
728 wxBitmap bitmap2(totalWidth, totalHeight);
729
730 wxMemoryDC memdc2;
731 memdc2.SelectObject(bitmap2);
732
733 wxColour clr(255, 255, 0);
734 wxBrush yellowBrush(clr, wxSOLID);
735 memdc2.SetBackground(yellowBrush);
736 memdc2.Clear();
737
738 wxPen yellowPen(clr, 1, wxSOLID);
739
740 // Now draw a white rectangle with red outline. It should
741 // entirely eclipse the yellow background.
742 memdc2.SetPen(*wxRED_PEN);
743 memdc2.SetBrush(*wxWHITE_BRUSH);
744
745 memdc2.DrawRectangle(0, 0, totalWidth, totalHeight);
746
747 memdc2.SetPen(wxNullPen);
748 memdc2.SetBrush(wxNullBrush);
749 memdc2.SelectObject(wxNullBitmap);
750
751 dc.DrawBitmap(bitmap2, 500, 270);
752
753 // Repeat, but draw directly on dc
754 // Draw a yellow rectangle filling the bitmap
755
756 x = 600; int y = 270;
757 dc.SetPen(yellowPen);
758 dc.SetBrush(yellowBrush);
759 dc.DrawRectangle(x, y, totalWidth, totalHeight);
760
761 // Now draw a white rectangle with red outline. It should
762 // entirely eclipse the yellow background.
763 dc.SetPen(*wxRED_PEN);
764 dc.SetBrush(*wxWHITE_BRUSH);
765
766 dc.DrawRectangle(x, y, totalWidth, totalHeight);
767 }
768
769 void MyCanvas::DrawText(wxDC& dc)
770 {
771 // set underlined font for testing
772 dc.SetFont( wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, true) );
773 dc.DrawText( _T("This is text"), 110, 10 );
774 dc.DrawRotatedText( _T("That is text"), 20, 10, -45 );
775
776 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
777 // under Win9x (it is not TrueType)
778 dc.SetFont( *wxSWISS_FONT );
779
780 wxString text;
781 dc.SetBackgroundMode(wxTRANSPARENT);
782
783 for ( int n = -180; n < 180; n += 30 )
784 {
785 text.Printf(wxT(" %d rotated text"), n);
786 dc.DrawRotatedText(text , 400, 400, n);
787 }
788
789 dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
790
791 dc.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
792
793 long length;
794 long height;
795 long descent;
796 dc.GetTextExtent( _T("This is Swiss 18pt text."), &length, &height, &descent );
797 text.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length, height, descent );
798 dc.DrawText( text, 110, 80 );
799
800 text.Printf( wxT("CharHeight() returns: %d"), dc.GetCharHeight() );
801 dc.DrawText( text, 110, 120 );
802
803 dc.DrawRectangle( 100, 40, 4, height );
804
805 // test the logical function effect
806 wxCoord y = 150;
807 dc.SetLogicalFunction(wxINVERT);
808 dc.DrawText( _T("There should be no text below"), 110, 150 );
809 dc.DrawRectangle( 110, y, 100, height );
810
811 // twice drawn inverted should result in invisible
812 y += height;
813 dc.DrawText( _T("Invisible text"), 110, y );
814 dc.DrawRectangle( 110, y, 100, height );
815 dc.DrawText( _T("Invisible text"), 110, y );
816 dc.DrawRectangle( 110, y, 100, height );
817 dc.SetLogicalFunction(wxCOPY);
818
819 y += height;
820 dc.DrawRectangle( 110, y, 100, height );
821 dc.DrawText( _T("Visible text"), 110, y );
822 }
823
824 static const struct
825 {
826 const wxChar *name;
827 int rop;
828 } rasterOperations[] =
829 {
830 { wxT("wxAND"), wxAND },
831 { wxT("wxAND_INVERT"), wxAND_INVERT },
832 { wxT("wxAND_REVERSE"), wxAND_REVERSE },
833 { wxT("wxCLEAR"), wxCLEAR },
834 { wxT("wxCOPY"), wxCOPY },
835 { wxT("wxEQUIV"), wxEQUIV },
836 { wxT("wxINVERT"), wxINVERT },
837 { wxT("wxNAND"), wxNAND },
838 { wxT("wxNO_OP"), wxNO_OP },
839 { wxT("wxOR"), wxOR },
840 { wxT("wxOR_INVERT"), wxOR_INVERT },
841 { wxT("wxOR_REVERSE"), wxOR_REVERSE },
842 { wxT("wxSET"), wxSET },
843 { wxT("wxSRC_INVERT"), wxSRC_INVERT },
844 { wxT("wxXOR"), wxXOR },
845 };
846
847 void MyCanvas::DrawImages(wxDC& dc, DrawMode mode)
848 {
849 dc.DrawText(_T("original image"), 0, 0);
850 dc.DrawBitmap(*gs_bmpNoMask, 0, 20, 0);
851 dc.DrawText(_T("with colour mask"), 0, 100);
852 dc.DrawBitmap(*gs_bmpWithColMask, 0, 120, true);
853 dc.DrawText(_T("the mask image"), 0, 200);
854 dc.DrawBitmap(*gs_bmpMask, 0, 220, 0);
855 dc.DrawText(_T("masked image"), 0, 300);
856 dc.DrawBitmap(*gs_bmpWithMask, 0, 320, true);
857
858 int cx = gs_bmpWithColMask->GetWidth(),
859 cy = gs_bmpWithColMask->GetHeight();
860
861 wxMemoryDC memDC;
862 for ( size_t n = 0; n < WXSIZEOF(rasterOperations); n++ )
863 {
864 wxCoord x = 120 + 150*(n%4),
865 y = 20 + 100*(n/4);
866
867 dc.DrawText(rasterOperations[n].name, x, y - 20);
868 memDC.SelectObject(*gs_bmpWithColMask);
869 if ( mode == Draw_Stretch )
870 {
871 dc.StretchBlit(x, y, cx, cy, &memDC, 0, 0, cx/2, cy/2,
872 rasterOperations[n].rop, true);
873 }
874 else
875 {
876 dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, true);
877 }
878 }
879 }
880
881 void MyCanvas::DrawWithLogicalOps(wxDC& dc)
882 {
883 static const wxCoord w = 60;
884 static const wxCoord h = 60;
885
886 // reuse the text colour here
887 dc.SetPen(wxPen(m_owner->m_colourForeground, 1, wxSOLID));
888 dc.SetBrush(*wxTRANSPARENT_BRUSH);
889
890 size_t n;
891 for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
892 {
893 wxCoord x = 20 + 150*(n%4),
894 y = 20 + 100*(n/4);
895
896 dc.DrawText(rasterOperations[n].name, x, y - 20);
897 dc.SetLogicalFunction(rasterOperations[n].rop);
898 dc.DrawRectangle(x, y, w, h);
899 dc.DrawLine(x, y, x + w, y + h);
900 dc.DrawLine(x + w, y, x, y + h);
901 }
902
903 // now some filled rectangles
904 dc.SetBrush(wxBrush(m_owner->m_colourForeground, wxSOLID));
905
906 for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
907 {
908 wxCoord x = 20 + 150*(n%4),
909 y = 500 + 100*(n/4);
910
911 dc.DrawText(rasterOperations[n].name, x, y - 20);
912 dc.SetLogicalFunction(rasterOperations[n].rop);
913 dc.DrawRectangle(x, y, w, h);
914 }
915 }
916
917 #if wxUSE_GRAPHICS_CONTEXT
918 #ifdef __WXGTK20__
919 void MyCanvas::DrawAlpha(wxDC& no_dc)
920 #else
921 void MyCanvas::DrawAlpha(wxDC& dc)
922 #endif
923 {
924 #ifdef __WXGTK__
925 wxGCDC dc( this );
926 PrepareDC( dc );
927 #endif
928
929 wxDouble margin = 20 ;
930 wxDouble width = 180 ;
931 wxDouble radius = 30 ;
932
933 dc.SetPen( wxPen( wxColour( 128, 0, 0, 255 ),12, wxSOLID));
934 dc.SetBrush( wxBrush( wxColour( 255, 0, 0, 255),wxSOLID));
935
936 wxRect r(margin,margin+width*0.66,width,width) ;
937
938 dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
939
940 dc.SetPen( wxPen( wxColour( 0, 0, 128, 255 ),12, wxSOLID));
941 dc.SetBrush( wxBrush( wxColour( 0, 0, 255, 255),wxSOLID));
942
943 r.Offset( width * 0.8 , - width * 0.66 ) ;
944
945 dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
946
947 dc.SetPen( wxPen( wxColour( 128, 128, 0, 255 ),12, wxSOLID));
948 dc.SetBrush( wxBrush( wxColour( 192, 192, 0, 255),wxSOLID));
949
950 r.Offset( width * 0.8 , width *0.5 ) ;
951
952 dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
953
954 dc.SetPen( *wxTRANSPARENT_PEN ) ;
955 dc.SetBrush( wxBrush( wxColour(255,255,128,128) ) );
956 dc.DrawRoundedRectangle( 0 , margin + width / 2 , width * 3 , 100 , radius) ;
957
958 dc.SetTextForeground( wxColour(255,255,0,128) );
959 dc.SetFont( wxFont( 40, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL ) );
960 dc.DrawText( wxT("Hello!"), 120, 80 );
961 }
962
963 #endif
964
965 void MyCanvas::DrawCircles(wxDC& dc)
966 {
967 int x = 100,
968 y = 100,
969 r = 20;
970
971 dc.SetPen( *wxRED_PEN );
972 dc.SetBrush( *wxGREEN_BRUSH );
973
974 dc.DrawText(_T("Some circles"), 0, y);
975 dc.DrawCircle(x, y, r);
976 dc.DrawCircle(x + 2*r, y, r);
977 dc.DrawCircle(x + 4*r, y, r);
978
979 y += 2*r;
980 dc.DrawText(_T("And ellipses"), 0, y);
981 dc.DrawEllipse(x - r, y, 2*r, r);
982 dc.DrawEllipse(x + r, y, 2*r, r);
983 dc.DrawEllipse(x + 3*r, y, 2*r, r);
984
985 y += 2*r;
986 dc.DrawText(_T("And arcs"), 0, y);
987 dc.DrawArc(x - r, y, x + r, y, x, y);
988 dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
989 dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
990
991 y += 2*r;
992 dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
993 dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
994 dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
995 dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
996
997 // same as above, just transparent brush
998
999 dc.SetPen( *wxRED_PEN );
1000 dc.SetBrush( *wxTRANSPARENT_BRUSH );
1001
1002 y += 2*r;
1003 dc.DrawText(_T("Some circles"), 0, y);
1004 dc.DrawCircle(x, y, r);
1005 dc.DrawCircle(x + 2*r, y, r);
1006 dc.DrawCircle(x + 4*r, y, r);
1007
1008 y += 2*r;
1009 dc.DrawText(_T("And ellipses"), 0, y);
1010 dc.DrawEllipse(x - r, y, 2*r, r);
1011 dc.DrawEllipse(x + r, y, 2*r, r);
1012 dc.DrawEllipse(x + 3*r, y, 2*r, r);
1013
1014 y += 2*r;
1015 dc.DrawText(_T("And arcs"), 0, y);
1016 dc.DrawArc(x - r, y, x + r, y, x, y);
1017 dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
1018 dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
1019
1020 y += 2*r;
1021 dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
1022 dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
1023 dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
1024 dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
1025
1026 }
1027
1028 void MyCanvas::DrawSplines(wxDC& dc)
1029 {
1030 #if wxUSE_SPLINES
1031 dc.DrawText(_T("Some splines"), 10, 5);
1032
1033 // values are hardcoded rather than randomly generated
1034 // so the output can be compared between native
1035 // implementations on platforms with different random
1036 // generators
1037
1038 const int R = 300;
1039 const wxPoint center( R + 20, R + 20 );
1040 const int angles[7] = { 0, 10, 33, 77, 13, 145, 90 };
1041 const int radii[5] = { 100 , 59, 85, 33, 90 };
1042 const int n = 200;
1043 wxPoint pts[n];
1044
1045 // background spline calculation
1046 unsigned int radius_pos = 0;
1047 unsigned int angle_pos = 0;
1048 int angle = 0;
1049 for ( int i = 0; i < n; i++ )
1050 {
1051 angle += angles[ angle_pos ];
1052 int r = R * radii[ radius_pos ] / 100;
1053 pts[ i ].x = center.x + (wxCoord)( r * cos( M_PI * angle / 180.0) );
1054 pts[ i ].y = center.y + (wxCoord)( r * sin( M_PI * angle / 180.0) );
1055
1056 angle_pos++;
1057 if ( angle_pos >= WXSIZEOF(angles) ) angle_pos = 0;
1058
1059 radius_pos++;
1060 if ( radius_pos >= WXSIZEOF(radii) ) radius_pos = 0;
1061 }
1062
1063 // background spline drawing
1064 dc.SetPen(*wxRED_PEN);
1065 dc.DrawSpline(WXSIZEOF(pts), pts);
1066
1067 // less detailed spline calculation
1068 wxPoint letters[4][5];
1069 // w
1070 letters[0][0] = wxPoint( 0,1); // O O
1071 letters[0][1] = wxPoint( 1,3); // * *
1072 letters[0][2] = wxPoint( 2,2); // * O *
1073 letters[0][3] = wxPoint( 3,3); // * * * *
1074 letters[0][4] = wxPoint( 4,1); // O O
1075 // x1
1076 letters[1][0] = wxPoint( 5,1); // O*O
1077 letters[1][1] = wxPoint( 6,1); // *
1078 letters[1][2] = wxPoint( 7,2); // O
1079 letters[1][3] = wxPoint( 8,3); // *
1080 letters[1][4] = wxPoint( 9,3); // O*O
1081 // x2
1082 letters[2][0] = wxPoint( 5,3); // O*O
1083 letters[2][1] = wxPoint( 6,3); // *
1084 letters[2][2] = wxPoint( 7,2); // O
1085 letters[2][3] = wxPoint( 8,1); // *
1086 letters[2][4] = wxPoint( 9,1); // O*O
1087 // W
1088 letters[3][0] = wxPoint(10,0); // O O
1089 letters[3][1] = wxPoint(11,3); // * *
1090 letters[3][2] = wxPoint(12,1); // * O *
1091 letters[3][3] = wxPoint(13,3); // * * * *
1092 letters[3][4] = wxPoint(14,0); // O O
1093
1094 const int dx = 2 * R / letters[3][4].x;
1095 const int h[4] = { -R/2, 0, R/4, R/2 };
1096
1097 for ( int m = 0; m < 4; m++ )
1098 {
1099 for ( int n = 0; n < 5; n++ )
1100 {
1101 letters[m][n].x = center.x - R + letters[m][n].x * dx;
1102 letters[m][n].y = center.y + h[ letters[m][n].y ];
1103 }
1104
1105 dc.SetPen( wxPen( wxT("blue"), 1, wxDOT) );
1106 dc.DrawLines(5, letters[m]);
1107 dc.SetPen( wxPen( wxT("black"), 4, wxSOLID) );
1108 dc.DrawSpline(5, letters[m]);
1109 }
1110
1111 #else
1112 dc.DrawText(_T("Splines not supported."), 10, 5);
1113 #endif
1114 }
1115
1116 void MyCanvas::DrawGradients(wxDC& dc)
1117 {
1118 static const int TEXT_HEIGHT = 15;
1119
1120 // LHS: linear
1121 wxRect r(10, 10, 50, 50);
1122 dc.DrawText(_T("wxRIGHT"), r.x, r.y);
1123 r.Offset(0, TEXT_HEIGHT);
1124 dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxRIGHT);
1125
1126 r.Offset(0, r.height + 10);
1127 dc.DrawText(_T("wxLEFT"), r.x, r.y);
1128 r.Offset(0, TEXT_HEIGHT);
1129 dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxLEFT);
1130
1131 r.Offset(0, r.height + 10);
1132 dc.DrawText(_T("wxDOWN"), r.x, r.y);
1133 r.Offset(0, TEXT_HEIGHT);
1134 dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxDOWN);
1135
1136 r.Offset(0, r.height + 10);
1137 dc.DrawText(_T("wxUP"), r.x, r.y);
1138 r.Offset(0, TEXT_HEIGHT);
1139 dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxUP);
1140
1141
1142 // RHS: concentric
1143 r = wxRect(200, 10, 50, 50);
1144 dc.DrawText(_T("Blue inside"), r.x, r.y);
1145 r.Offset(0, TEXT_HEIGHT);
1146 dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE);
1147
1148 r.Offset(0, r.height + 10);
1149 dc.DrawText(_T("White inside"), r.x, r.y);
1150 r.Offset(0, TEXT_HEIGHT);
1151 dc.GradientFillConcentric(r, *wxWHITE, *wxBLUE);
1152
1153 r.Offset(0, r.height + 10);
1154 dc.DrawText(_T("Blue in top left corner"), r.x, r.y);
1155 r.Offset(0, TEXT_HEIGHT);
1156 dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(0, 0));
1157
1158 r.Offset(0, r.height + 10);
1159 dc.DrawText(_T("Blue in bottom right corner"), r.x, r.y);
1160 r.Offset(0, TEXT_HEIGHT);
1161 dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(r.width, r.height));
1162 }
1163
1164 void MyCanvas::DrawRegions(wxDC& dc)
1165 {
1166 dc.DrawText(_T("You should see a red rect partly covered by a cyan one ")
1167 _T("on the left"), 10, 5);
1168 dc.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
1169 10, 5 + dc.GetCharHeight());
1170 dc.DrawText(_T("The second copy should be identical but right part of it ")
1171 _T("should be offset by 10 pixels."),
1172 10, 5 + 2*dc.GetCharHeight());
1173
1174 DrawRegionsHelper(dc, 10, true);
1175 DrawRegionsHelper(dc, 350, false);
1176 }
1177
1178 void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime)
1179 {
1180 wxCoord y = 100;
1181
1182 dc.DestroyClippingRegion();
1183 dc.SetBrush( *wxWHITE_BRUSH );
1184 dc.SetPen( *wxTRANSPARENT_PEN );
1185 dc.DrawRectangle( x, y, 310, 310 );
1186
1187 dc.SetClippingRegion( x + 10, y + 10, 100, 270 );
1188
1189 dc.SetBrush( *wxRED_BRUSH );
1190 dc.DrawRectangle( x, y, 310, 310 );
1191
1192 dc.SetClippingRegion( x + 10, y + 10, 100, 100 );
1193
1194 dc.SetBrush( *wxCYAN_BRUSH );
1195 dc.DrawRectangle( x, y, 310, 310 );
1196
1197 dc.DestroyClippingRegion();
1198
1199 wxRegion region(x + 110, y + 20, 100, 270);
1200 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
1201 if ( !firstTime )
1202 region.Offset(10, 10);
1203 #endif
1204 dc.SetClippingRegion(region);
1205
1206 dc.SetBrush( *wxGREY_BRUSH );
1207 dc.DrawRectangle( x, y, 310, 310 );
1208
1209 if (m_smile_bmp.Ok())
1210 {
1211 dc.DrawBitmap( m_smile_bmp, x + 150, y + 150, true );
1212 dc.DrawBitmap( m_smile_bmp, x + 130, y + 10, true );
1213 dc.DrawBitmap( m_smile_bmp, x + 130, y + 280, true );
1214 dc.DrawBitmap( m_smile_bmp, x + 100, y + 70, true );
1215 dc.DrawBitmap( m_smile_bmp, x + 200, y + 70, true );
1216 }
1217 }
1218
1219 void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
1220 {
1221 wxPaintDC pdc(this);
1222
1223 #if wxUSE_GRAPHICS_CONTEXT
1224 wxGCDC gdc( pdc ) ;
1225 wxDC &dc = m_useContext ? (wxDC&) gdc : (wxDC&) pdc ;
1226 #else
1227 wxDC &dc = pdc ;
1228 #endif
1229
1230 PrepareDC(dc);
1231
1232 m_owner->PrepareDC(dc);
1233
1234 dc.SetBackgroundMode( m_owner->m_backgroundMode );
1235 if ( m_owner->m_backgroundBrush.Ok() )
1236 dc.SetBackground( m_owner->m_backgroundBrush );
1237 if ( m_owner->m_colourForeground.Ok() )
1238 dc.SetTextForeground( m_owner->m_colourForeground );
1239 if ( m_owner->m_colourBackground.Ok() )
1240 dc.SetTextBackground( m_owner->m_colourBackground );
1241
1242 if ( m_owner->m_textureBackground) {
1243 if ( ! m_owner->m_backgroundBrush.Ok() ) {
1244 wxColour clr(0,128,0);
1245 wxBrush b(clr, wxSOLID);
1246 dc.SetBackground(b);
1247 }
1248 }
1249
1250 if ( m_clip )
1251 dc.SetClippingRegion(100, 100, 100, 100);
1252
1253 dc.Clear();
1254
1255 if ( m_owner->m_textureBackground )
1256 {
1257 dc.SetPen(*wxMEDIUM_GREY_PEN);
1258 for ( int i = 0; i < 200; i++ )
1259 dc.DrawLine(0, i*10, i*10, 0);
1260 }
1261
1262 switch ( m_show )
1263 {
1264 case Show_Default:
1265 DrawDefault(dc);
1266 break;
1267
1268 case Show_Circles:
1269 DrawCircles(dc);
1270 break;
1271
1272 case Show_Splines:
1273 DrawSplines(dc);
1274 break;
1275
1276 case Show_Regions:
1277 DrawRegions(dc);
1278 break;
1279
1280 case Show_Text:
1281 DrawText(dc);
1282 break;
1283
1284 case Show_Lines:
1285 DrawTestLines( 0, 100, 0, dc );
1286 DrawTestLines( 0, 320, 1, dc );
1287 DrawTestLines( 0, 540, 2, dc );
1288 DrawTestLines( 0, 760, 6, dc );
1289 break;
1290
1291 case Show_Brushes:
1292 DrawTestBrushes(dc);
1293 break;
1294
1295 case Show_Polygons:
1296 DrawTestPoly(dc);
1297 break;
1298
1299 case Show_Mask:
1300 DrawImages(dc, Draw_Normal);
1301 break;
1302
1303 case Show_Mask_Stretch:
1304 DrawImages(dc, Draw_Stretch);
1305 break;
1306
1307 case Show_Ops:
1308 DrawWithLogicalOps(dc);
1309 break;
1310
1311 #if wxUSE_GRAPHICS_CONTEXT
1312 case Show_Alpha:
1313 DrawAlpha(dc);
1314 break;
1315 #endif
1316
1317 case Show_Gradient:
1318 DrawGradients(dc);
1319 break;
1320
1321 default:
1322 break;
1323 }
1324 }
1325
1326 void MyCanvas::OnMouseMove(wxMouseEvent &event)
1327 {
1328 #if wxUSE_STATUSBAR
1329 wxClientDC dc(this);
1330 PrepareDC(dc);
1331 m_owner->PrepareDC(dc);
1332
1333 wxPoint pos = event.GetPosition();
1334 long x = dc.DeviceToLogicalX( pos.x );
1335 long y = dc.DeviceToLogicalY( pos.y );
1336 wxString str;
1337 str.Printf( wxT("Current mouse position: %d,%d"), (int)x, (int)y );
1338 m_owner->SetStatusText( str );
1339 #else
1340 wxUnusedVar(event);
1341 #endif // wxUSE_STATUSBAR
1342 }
1343
1344 // ----------------------------------------------------------------------------
1345 // MyFrame
1346 // ----------------------------------------------------------------------------
1347
1348 // the event tables connect the wxWidgets events with the functions (event
1349 // handlers) which process them. It can be also done at run-time, but for the
1350 // simple menu events like this the static method is much simpler.
1351 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
1352 EVT_MENU (File_Quit, MyFrame::OnQuit)
1353 EVT_MENU (File_About, MyFrame::OnAbout)
1354 EVT_MENU (File_Clip, MyFrame::OnClip)
1355 #if wxUSE_GRAPHICS_CONTEXT
1356 EVT_MENU (File_GraphicContext, MyFrame::OnGraphicContext)
1357 #endif
1358
1359 EVT_MENU_RANGE(MenuShow_First, MenuShow_Last, MyFrame::OnShow)
1360
1361 EVT_MENU_RANGE(MenuOption_First, MenuOption_Last, MyFrame::OnOption)
1362 END_EVENT_TABLE()
1363
1364 // frame constructor
1365 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
1366 : wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size,
1367 wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
1368 {
1369 // set the frame icon
1370 SetIcon(wxICON(mondrian));
1371
1372 wxMenu *menuFile = new wxMenu;
1373 menuFile->Append(File_ShowDefault, _T("&Default screen\tF1"));
1374 menuFile->Append(File_ShowText, _T("&Text screen\tF2"));
1375 menuFile->Append(File_ShowLines, _T("&Lines screen\tF3"));
1376 menuFile->Append(File_ShowBrushes, _T("&Brushes screen\tF4"));
1377 menuFile->Append(File_ShowPolygons, _T("&Polygons screen\tF5"));
1378 menuFile->Append(File_ShowMask, _T("&Mask screen\tF6"));
1379 menuFile->Append(File_ShowMaskStretch, _T("1/&2 scaled mask\tShift-F6"));
1380 menuFile->Append(File_ShowOps, _T("&ROP screen\tF7"));
1381 menuFile->Append(File_ShowRegions, _T("Re&gions screen\tF8"));
1382 menuFile->Append(File_ShowCircles, _T("&Circles screen\tF9"));
1383 #if wxUSE_GRAPHICS_CONTEXT
1384 menuFile->Append(File_ShowAlpha, _T("&Alpha screen\tF10"));
1385 #endif
1386 menuFile->Append(File_ShowSplines, _T("&Splines screen\tF11"));
1387 menuFile->Append(File_ShowGradients, _T("&Gradients screen\tF12"));
1388 menuFile->AppendSeparator();
1389 menuFile->AppendCheckItem(File_Clip, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
1390 #if wxUSE_GRAPHICS_CONTEXT
1391 menuFile->AppendCheckItem(File_GraphicContext, _T("&Use GraphicContext\tCtrl-Y"), _T("Use GraphicContext"));
1392 #endif
1393 menuFile->AppendSeparator();
1394 menuFile->Append(File_About, _T("&About...\tCtrl-A"), _T("Show about dialog"));
1395 menuFile->AppendSeparator();
1396 menuFile->Append(File_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
1397
1398 wxMenu *menuMapMode = new wxMenu;
1399 menuMapMode->Append( MapMode_Text, _T("&TEXT map mode") );
1400 menuMapMode->Append( MapMode_Lometric, _T("&LOMETRIC map mode") );
1401 menuMapMode->Append( MapMode_Twips, _T("T&WIPS map mode") );
1402 menuMapMode->Append( MapMode_Points, _T("&POINTS map mode") );
1403 menuMapMode->Append( MapMode_Metric, _T("&METRIC map mode") );
1404
1405 wxMenu *menuUserScale = new wxMenu;
1406 menuUserScale->Append( UserScale_StretchHoriz, _T("Stretch &horizontally\tCtrl-H") );
1407 menuUserScale->Append( UserScale_ShrinkHoriz, _T("Shrin&k horizontally\tCtrl-G") );
1408 menuUserScale->Append( UserScale_StretchVertic, _T("Stretch &vertically\tCtrl-V") );
1409 menuUserScale->Append( UserScale_ShrinkVertic, _T("&Shrink vertically\tCtrl-W") );
1410 menuUserScale->AppendSeparator();
1411 menuUserScale->Append( UserScale_Restore, _T("&Restore to normal\tCtrl-0") );
1412
1413 wxMenu *menuAxis = new wxMenu;
1414 menuAxis->AppendCheckItem( AxisMirror_Horiz, _T("Mirror horizontally\tCtrl-M") );
1415 menuAxis->AppendCheckItem( AxisMirror_Vertic, _T("Mirror vertically\tCtrl-N") );
1416
1417 wxMenu *menuLogical = new wxMenu;
1418 menuLogical->Append( LogicalOrigin_MoveDown, _T("Move &down\tCtrl-D") );
1419 menuLogical->Append( LogicalOrigin_MoveUp, _T("Move &up\tCtrl-U") );
1420 menuLogical->Append( LogicalOrigin_MoveLeft, _T("Move &right\tCtrl-L") );
1421 menuLogical->Append( LogicalOrigin_MoveRight, _T("Move &left\tCtrl-R") );
1422 menuLogical->AppendSeparator();
1423 menuLogical->Append( LogicalOrigin_Set, _T("Set to (&100, 100)\tShift-Ctrl-1") );
1424 menuLogical->Append( LogicalOrigin_Restore, _T("&Restore to normal\tShift-Ctrl-0") );
1425
1426 wxMenu *menuColour = new wxMenu;
1427 #if wxUSE_COLOURDLG
1428 menuColour->Append( Colour_TextForeground, _T("Text &foreground...") );
1429 menuColour->Append( Colour_TextBackground, _T("Text &background...") );
1430 menuColour->Append( Colour_Background, _T("Background &colour...") );
1431 #endif // wxUSE_COLOURDLG
1432 menuColour->AppendCheckItem( Colour_BackgroundMode, _T("&Opaque/transparent\tCtrl-B") );
1433 menuColour->AppendCheckItem( Colour_TextureBackgound, _T("Draw textured back&ground\tCtrl-T") );
1434
1435 // now append the freshly created menu to the menu bar...
1436 wxMenuBar *menuBar = new wxMenuBar;
1437 menuBar->Append(menuFile, _T("&File"));
1438 menuBar->Append(menuMapMode, _T("&Mode"));
1439 menuBar->Append(menuUserScale, _T("&Scale"));
1440 menuBar->Append(menuAxis, _T("&Axis"));
1441 menuBar->Append(menuLogical, _T("&Origin"));
1442 menuBar->Append(menuColour, _T("&Colours"));
1443
1444 // ... and attach this menu bar to the frame
1445 SetMenuBar(menuBar);
1446
1447 #if wxUSE_STATUSBAR
1448 CreateStatusBar(2);
1449 SetStatusText(_T("Welcome to wxWidgets!"));
1450 #endif // wxUSE_STATUSBAR
1451
1452 m_mapMode = wxMM_TEXT;
1453 m_xUserScale = 1.0;
1454 m_yUserScale = 1.0;
1455 m_xLogicalOrigin = 0;
1456 m_yLogicalOrigin = 0;
1457 m_xAxisReversed =
1458 m_yAxisReversed = false;
1459 m_backgroundMode = wxSOLID;
1460 m_colourForeground = *wxRED;
1461 m_colourBackground = *wxBLUE;
1462 m_textureBackground = false;
1463
1464 m_canvas = new MyCanvas( this );
1465 m_canvas->SetScrollbars( 10, 10, 100, 240 );
1466 }
1467
1468 // event handlers
1469
1470 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1471 {
1472 // true is to force the frame to close
1473 Close(true);
1474 }
1475
1476 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1477 {
1478 wxString msg;
1479 msg.Printf( wxT("This is the about dialog of the drawing sample.\n")
1480 wxT("This sample tests various primitive drawing functions\n")
1481 wxT("(without any attempts to prevent flicker).\n")
1482 wxT("Copyright (c) Robert Roebling 1999")
1483 );
1484
1485 wxMessageBox(msg, _T("About Drawing"), wxOK | wxICON_INFORMATION, this);
1486 }
1487
1488 void MyFrame::OnClip(wxCommandEvent& event)
1489 {
1490 m_canvas->Clip(event.IsChecked());
1491 }
1492
1493 #if wxUSE_GRAPHICS_CONTEXT
1494 void MyFrame::OnGraphicContext(wxCommandEvent& event)
1495 {
1496 m_canvas->UseGraphicContext(event.IsChecked());
1497 }
1498 #endif
1499
1500 void MyFrame::OnShow(wxCommandEvent& event)
1501 {
1502 m_canvas->ToShow((ScreenToShow)(event.GetId() - MenuShow_First));
1503 }
1504
1505 void MyFrame::OnOption(wxCommandEvent& event)
1506 {
1507 switch (event.GetId())
1508 {
1509 case MapMode_Text:
1510 m_mapMode = wxMM_TEXT;
1511 break;
1512 case MapMode_Lometric:
1513 m_mapMode = wxMM_LOMETRIC;
1514 break;
1515 case MapMode_Twips:
1516 m_mapMode = wxMM_TWIPS;
1517 break;
1518 case MapMode_Points:
1519 m_mapMode = wxMM_POINTS;
1520 break;
1521 case MapMode_Metric:
1522 m_mapMode = wxMM_METRIC;
1523 break;
1524
1525 case LogicalOrigin_MoveDown:
1526 m_yLogicalOrigin += 10;
1527 break;
1528 case LogicalOrigin_MoveUp:
1529 m_yLogicalOrigin -= 10;
1530 break;
1531 case LogicalOrigin_MoveLeft:
1532 m_xLogicalOrigin += 10;
1533 break;
1534 case LogicalOrigin_MoveRight:
1535 m_xLogicalOrigin -= 10;
1536 break;
1537 case LogicalOrigin_Set:
1538 m_xLogicalOrigin =
1539 m_yLogicalOrigin = -100;
1540 break;
1541 case LogicalOrigin_Restore:
1542 m_xLogicalOrigin =
1543 m_yLogicalOrigin = 0;
1544 break;
1545
1546 case UserScale_StretchHoriz:
1547 m_xUserScale *= 1.10;
1548 break;
1549 case UserScale_ShrinkHoriz:
1550 m_xUserScale /= 1.10;
1551 break;
1552 case UserScale_StretchVertic:
1553 m_yUserScale *= 1.10;
1554 break;
1555 case UserScale_ShrinkVertic:
1556 m_yUserScale /= 1.10;
1557 break;
1558 case UserScale_Restore:
1559 m_xUserScale =
1560 m_yUserScale = 1.0;
1561 break;
1562
1563 case AxisMirror_Vertic:
1564 m_yAxisReversed = !m_yAxisReversed;
1565 break;
1566 case AxisMirror_Horiz:
1567 m_xAxisReversed = !m_xAxisReversed;
1568 break;
1569
1570 #if wxUSE_COLOURDLG
1571 case Colour_TextForeground:
1572 m_colourForeground = SelectColour();
1573 break;
1574 case Colour_TextBackground:
1575 m_colourBackground = SelectColour();
1576 break;
1577 case Colour_Background:
1578 {
1579 wxColour col = SelectColour();
1580 if ( col.Ok() )
1581 {
1582 m_backgroundBrush.SetColour(col);
1583 }
1584 }
1585 break;
1586 #endif // wxUSE_COLOURDLG
1587
1588 case Colour_BackgroundMode:
1589 m_backgroundMode = m_backgroundMode == wxSOLID ? wxTRANSPARENT
1590 : wxSOLID;
1591 break;
1592
1593 case Colour_TextureBackgound:
1594 m_textureBackground = ! m_textureBackground;
1595 break;
1596
1597 default:
1598 // skip Refresh()
1599 return;
1600 }
1601
1602 m_canvas->Refresh();
1603 }
1604
1605 void MyFrame::PrepareDC(wxDC& dc)
1606 {
1607 dc.SetLogicalOrigin( m_xLogicalOrigin, m_yLogicalOrigin );
1608 dc.SetAxisOrientation( !m_xAxisReversed, m_yAxisReversed );
1609 dc.SetUserScale( m_xUserScale, m_yUserScale );
1610 dc.SetMapMode( m_mapMode );
1611 }
1612
1613 #if wxUSE_COLOURDLG
1614 wxColour MyFrame::SelectColour()
1615 {
1616 wxColour col;
1617 wxColourData data;
1618 wxColourDialog dialog(this, &data);
1619
1620 if ( dialog.ShowModal() == wxID_OK )
1621 {
1622 col = dialog.GetColourData().GetColour();
1623 }
1624
1625 return col;
1626 }
1627 #endif // wxUSE_COLOURDLG