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