1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/drawing/drawing.cpp
3 // Purpose: shows and tests wxDC features
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers
33 #include "wx/colordlg.h"
35 #include "wx/artprov.h"
36 #include "wx/dcgraph.h"
37 #include "wx/overlay.h"
38 #include "wx/graphics.h"
40 #define TEST_CAIRO_EVERYWHERE 0
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
46 // the application icon
47 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
48 #include "mondrian.xpm"
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 // what do we show on screen (there are too many shapes to put them all on
56 // screen simultaneously)
70 #if wxUSE_GRAPHICS_CONTEXT
78 // ----------------------------------------------------------------------------
80 // ----------------------------------------------------------------------------
82 static wxBitmap
*gs_bmpNoMask
= NULL
,
83 *gs_bmpWithColMask
= NULL
,
85 *gs_bmpWithMask
= NULL
,
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 // Define a new application type, each program should derive a class from wxApp
95 class MyApp
: public wxApp
98 // override base class virtuals
99 // ----------------------------
101 // this one is called on application startup and is a good place for the app
102 // initialization (doing it here and not in the ctor allows to have an error
103 // return: if OnInit() returns false, the application terminates)
104 virtual bool OnInit();
106 virtual int OnExit() { DeleteBitmaps(); return 0; }
109 void DeleteBitmaps();
116 // Define a new frame type: this is going to be our main frame
117 class MyFrame
: public wxFrame
121 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
123 // event handlers (these functions should _not_ be virtual)
124 void OnQuit(wxCommandEvent
& event
);
125 void OnAbout(wxCommandEvent
& event
);
126 void OnClip(wxCommandEvent
& event
);
127 #if wxUSE_GRAPHICS_CONTEXT
128 void OnGraphicContext(wxCommandEvent
& event
);
130 void OnShow(wxCommandEvent
&event
);
131 void OnOption(wxCommandEvent
&event
);
134 wxColour
SelectColour();
135 #endif // wxUSE_COLOURDLG
136 void PrepareDC(wxDC
& dc
);
138 int m_backgroundMode
;
139 int m_textureBackground
;
143 int m_xLogicalOrigin
;
144 int m_yLogicalOrigin
;
145 bool m_xAxisReversed
,
147 wxColour m_colourForeground
, // these are _text_ colours
149 wxBrush m_backgroundBrush
;
153 // any class wishing to process wxWidgets events must use this macro
154 DECLARE_EVENT_TABLE()
157 // define a scrollable canvas for drawing onto
158 class MyCanvas
: public wxScrolledWindow
161 MyCanvas( MyFrame
*parent
);
163 void OnPaint(wxPaintEvent
&event
);
164 void OnMouseMove(wxMouseEvent
&event
);
165 void OnMouseDown(wxMouseEvent
&event
);
166 void OnMouseUp(wxMouseEvent
&event
);
168 void ToShow(ScreenToShow show
) { m_show
= show
; Refresh(); }
170 // set or remove the clipping region
171 void Clip(bool clip
) { m_clip
= clip
; Refresh(); }
172 #if wxUSE_GRAPHICS_CONTEXT
173 void UseGraphicContext(bool use
) { m_useContext
= use
; Refresh(); }
183 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
184 void DrawTestPoly(wxDC
& dc
);
185 void DrawTestBrushes(wxDC
& dc
);
186 void DrawText(wxDC
& dc
);
187 void DrawImages(wxDC
& dc
, DrawMode mode
);
188 void DrawWithLogicalOps(wxDC
& dc
);
189 #if wxUSE_GRAPHICS_CONTEXT
190 void DrawAlpha(wxDC
& dc
);
191 void DrawGraphics(wxGraphicsContext
* gc
);
193 void DrawRegions(wxDC
& dc
);
194 void DrawCircles(wxDC
& dc
);
195 void DrawSplines(wxDC
& dc
);
196 void DrawDefault(wxDC
& dc
);
197 void DrawGradients(wxDC
& dc
);
199 void DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
);
205 wxBitmap m_smile_bmp
;
210 wxPoint m_anchorpoint
;
211 wxPoint m_currentpoint
;
212 #if wxUSE_GRAPHICS_CONTEXT
216 DECLARE_EVENT_TABLE()
219 // ----------------------------------------------------------------------------
221 // ----------------------------------------------------------------------------
223 // IDs for the controls and the menu commands
227 File_Quit
= wxID_EXIT
,
228 File_About
= wxID_ABOUT
,
230 MenuShow_First
= wxID_HIGHEST
,
231 File_ShowDefault
= MenuShow_First
,
237 File_ShowMaskStretch
,
242 #if wxUSE_GRAPHICS_CONTEXT
247 MenuShow_Last
= File_ShowGradients
,
250 #if wxUSE_GRAPHICS_CONTEXT
256 MapMode_Text
= MenuOption_First
,
262 UserScale_StretchHoriz
,
263 UserScale_ShrinkHoriz
,
264 UserScale_StretchVertic
,
265 UserScale_ShrinkVertic
,
271 LogicalOrigin_MoveDown
,
272 LogicalOrigin_MoveUp
,
273 LogicalOrigin_MoveLeft
,
274 LogicalOrigin_MoveRight
,
276 LogicalOrigin_Restore
,
279 Colour_TextForeground
,
280 Colour_TextBackground
,
282 #endif // wxUSE_COLOURDLG
283 Colour_BackgroundMode
,
284 Colour_TextureBackgound
,
286 MenuOption_Last
= Colour_TextureBackgound
289 // ----------------------------------------------------------------------------
290 // event tables and other macros for wxWidgets
291 // ----------------------------------------------------------------------------
294 // Create a new application object: this macro will allow wxWidgets to create
295 // the application object during program execution (it's better than using a
296 // static object for many reasons) and also declares the accessor function
297 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
301 // ============================================================================
303 // ============================================================================
305 // ----------------------------------------------------------------------------
306 // the application class
307 // ----------------------------------------------------------------------------
309 bool MyApp::LoadImages()
311 gs_bmpNoMask
= new wxBitmap
;
312 gs_bmpWithColMask
= new wxBitmap
;
313 gs_bmpMask
= new wxBitmap
;
314 gs_bmpWithMask
= new wxBitmap
;
315 gs_bmp4
= new wxBitmap
;
316 gs_bmp4_mono
= new wxBitmap
;
317 gs_bmp36
= new wxBitmap
;
320 pathList
.Add(_T("."));
321 pathList
.Add(_T(".."));
322 pathList
.Add(_T("../.."));
324 wxString path
= pathList
.FindValidPath(_T("pat4.bmp"));
328 /* 4 colour bitmap */
329 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
330 /* turn into mono-bitmap */
331 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
332 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
333 gs_bmp4_mono
->SetMask(mask4
);
335 path
= pathList
.FindValidPath(_T("pat36.bmp"));
338 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
339 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
340 gs_bmp36
->SetMask(mask36
);
342 path
= pathList
.FindValidPath(_T("image.bmp"));
345 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
346 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
347 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
349 path
= pathList
.FindValidPath(_T("mask.bmp"));
352 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
354 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
355 gs_bmpWithMask
->SetMask(mask
);
357 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
358 gs_bmpWithColMask
->SetMask(mask
);
363 // `Main program' equivalent: the program execution "starts" here
366 if ( !wxApp::OnInit() )
369 // Create the main application window
370 MyFrame
*frame
= new MyFrame(_T("Drawing sample"),
371 wxPoint(50, 50), wxSize(550, 340));
373 // Show it and tell the application that it's our main window
379 wxLogError(wxT("Can't load one of the bitmap files needed ")
380 wxT("for this sample from the current or parent ")
381 wxT("directory, please copy them there."));
393 void MyApp::DeleteBitmaps()
396 delete gs_bmpWithColMask
;
398 delete gs_bmpWithMask
;
404 gs_bmpWithColMask
= NULL
;
406 gs_bmpWithMask
= NULL
;
412 // ----------------------------------------------------------------------------
414 // ----------------------------------------------------------------------------
416 // the event tables connect the wxWidgets events with the functions (event
417 // handlers) which process them.
418 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
419 EVT_PAINT (MyCanvas::OnPaint
)
420 EVT_MOTION (MyCanvas::OnMouseMove
)
421 EVT_LEFT_DOWN (MyCanvas::OnMouseDown
)
422 EVT_LEFT_UP (MyCanvas::OnMouseUp
)
427 MyCanvas::MyCanvas(MyFrame
*parent
)
428 : wxScrolledWindow(parent
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
,
429 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
432 m_show
= Show_Default
;
433 m_smile_bmp
= wxBitmap(smile_xpm
);
434 m_std_icon
= wxArtProvider::GetIcon(wxART_INFORMATION
);
436 m_rubberBand
= false;
437 #if wxUSE_GRAPHICS_CONTEXT
438 m_useContext
= false;
442 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
444 static const wxCoord WIDTH
= 200;
445 static const wxCoord HEIGHT
= 80;
450 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
451 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
452 dc
.DrawText(_T("Solid green"), x
+ 10, y
+ 10);
455 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
456 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
457 dc
.DrawText(_T("Hatched red"), x
+ 10, y
+ 10);
460 dc
.SetBrush(wxBrush(*gs_bmpMask
));
461 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
462 dc
.DrawText(_T("Stipple mono"), x
+ 10, y
+ 10);
465 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
466 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
467 dc
.DrawText(_T("Stipple colour"), x
+ 10, y
+ 10);
470 void MyCanvas::DrawTestPoly(wxDC
& dc
)
472 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
473 dc
.SetBrush(brushHatch
);
476 star
[0] = wxPoint(100, 60);
477 star
[1] = wxPoint(60, 150);
478 star
[2] = wxPoint(160, 100);
479 star
[3] = wxPoint(40, 100);
480 star
[4] = wxPoint(140, 150);
482 dc
.DrawText(_T("You should see two (irregular) stars below, the left one ")
483 _T("hatched"), 10, 10);
484 dc
.DrawText(_T("except for the central region and the right ")
485 _T("one entirely hatched"), 10, 30);
486 dc
.DrawText(_T("The third star only has a hatched outline"), 10, 50);
488 dc
.DrawPolygon(WXSIZEOF(star
), star
, 0, 30);
489 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 30, wxWINDING_RULE
);
492 star2
[0] = wxPoint(0, 100);
493 star2
[1] = wxPoint(-59, -81);
494 star2
[2] = wxPoint(95, 31);
495 star2
[3] = wxPoint(-95, 31);
496 star2
[4] = wxPoint(59, -81);
497 star2
[5] = wxPoint(0, 80);
498 star2
[6] = wxPoint(-47, -64);
499 star2
[7] = wxPoint(76, 24);
500 star2
[8] = wxPoint(-76, 24);
501 star2
[9] = wxPoint(47, -64);
502 int count
[2] = {5, 5};
504 dc
.DrawPolyPolygon(WXSIZEOF(count
), count
, star2
, 450, 150);
507 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
509 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
510 dc
.SetBrush( *wxRED_BRUSH
);
511 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
512 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
514 dc
.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x
+ 150, y
+ 10);
515 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
516 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
517 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
518 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
519 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
520 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
521 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
522 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
523 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
524 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
526 dc
.DrawText(_T("Misc hatches"), x
+ 150, y
+ 70);
527 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
528 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
529 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
530 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
531 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
532 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
533 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
534 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
535 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
536 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
537 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
538 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
540 dc
.DrawText(_T("User dash"), x
+ 150, y
+ 140);
541 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
543 dash1
[0] = 8; // Long dash <---------+
544 dash1
[1] = 2; // Short gap |
545 dash1
[2] = 3; // Short dash |
546 dash1
[3] = 2; // Short gap |
547 dash1
[4] = 3; // Short dash |
548 dash1
[5] = 2; // Short gap and repeat +
549 ud
.SetDashes( 6, dash1
);
551 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
552 dash1
[0] = 5; // Make first dash shorter
553 ud
.SetDashes( 6, dash1
);
555 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
556 dash1
[2] = 5; // Make second dash longer
557 ud
.SetDashes( 6, dash1
);
559 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
560 dash1
[4] = 5; // Make third dash longer
561 ud
.SetDashes( 6, dash1
);
563 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
566 void MyCanvas::DrawDefault(wxDC
& dc
)
569 dc
.DrawCircle(0, 0, 10);
571 #if !defined(wxMAC_USE_CORE_GRAPHICS) || !wxMAC_USE_CORE_GRAPHICS
572 // GetPixel and FloodFill not supported by Mac OS X CoreGraphics
573 // (FloodFill uses Blit from a non-wxMemoryDC)
574 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
575 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
578 dc
.GetPixel(1,1, &tmpColour
);
579 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
582 dc
.DrawCheckMark(5, 80, 15, 15);
583 dc
.DrawCheckMark(25, 80, 30, 30);
584 dc
.DrawCheckMark(60, 80, 60, 60);
586 // this is the test for "blitting bitmap into DC damages selected brush" bug
587 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
589 dc
.SetPen(*wxTRANSPARENT_PEN
);
590 dc
.SetBrush( *wxGREEN_BRUSH
);
591 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
592 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, true);
594 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
595 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
597 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
599 // test for "transparent" bitmap drawing (it intersects with the last
601 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
603 if (m_smile_bmp
.Ok())
604 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, true);
606 dc
.SetBrush( *wxBLACK_BRUSH
);
607 dc
.DrawRectangle( 0, 160, 1000, 300 );
610 wxBitmap
bitmap(20,70);
612 memdc
.SelectObject( bitmap
);
613 memdc
.SetBrush( *wxBLACK_BRUSH
);
614 memdc
.SetPen( *wxWHITE_PEN
);
615 memdc
.DrawRectangle(0,0,20,70);
616 memdc
.DrawLine( 10,0,10,70 );
619 wxPen pen
= *wxRED_PEN
;
621 memdc
.DrawLine( 10, 5,10, 5 );
622 memdc
.DrawLine( 10,10,11,10 );
623 memdc
.DrawLine( 10,15,12,15 );
624 memdc
.DrawLine( 10,20,13,20 );
627 memdc.SetPen(*wxRED_PEN);
628 memdc.DrawLine( 12, 5,12, 5 );
629 memdc.DrawLine( 12,10,13,10 );
630 memdc.DrawLine( 12,15,14,15 );
631 memdc.DrawLine( 12,20,15,20 );
635 memdc
.DrawLine( 10,25,10,25 );
636 memdc
.DrawLine( 10,30, 9,30 );
637 memdc
.DrawLine( 10,35, 8,35 );
638 memdc
.DrawLine( 10,40, 7,40 );
641 dc
.SetPen(*wxWHITE_PEN
);
642 memdc
.SetLogicalFunction( wxINVERT
);
643 memdc
.SetPen( *wxWHITE_PEN
);
644 memdc
.DrawLine( 10,50,10,50 );
645 memdc
.DrawLine( 10,55,11,55 );
646 memdc
.DrawLine( 10,60,12,60 );
647 memdc
.DrawLine( 10,65,13,65 );
649 memdc
.DrawLine( 12,50,12,50 );
650 memdc
.DrawLine( 12,55,13,55 );
651 memdc
.DrawLine( 12,60,14,60 );
652 memdc
.DrawLine( 12,65,15,65 );
654 memdc
.SelectObject( wxNullBitmap
);
655 dc
.DrawBitmap( bitmap
, 10, 170 );
656 wxImage image
= bitmap
.ConvertToImage();
657 image
.Rescale( 60,210 );
658 bitmap
= wxBitmap(image
);
659 dc
.DrawBitmap( bitmap
, 50, 170 );
661 // test the rectangle outline drawing - there should be one pixel between
662 // the rect and the lines
663 dc
.SetPen(*wxWHITE_PEN
);
664 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
665 dc
.DrawRectangle(150, 170, 49, 29);
666 dc
.DrawRectangle(200, 170, 49, 29);
667 dc
.SetPen(*wxWHITE_PEN
);
668 dc
.DrawLine(250, 210, 250, 170);
669 dc
.DrawLine(260, 200, 150, 200);
671 // test the rectangle filled drawing - there should be one pixel between
672 // the rect and the lines
673 dc
.SetPen(*wxTRANSPARENT_PEN
);
674 dc
.SetBrush( *wxWHITE_BRUSH
);
675 dc
.DrawRectangle(300, 170, 49, 29);
676 dc
.DrawRectangle(350, 170, 49, 29);
677 dc
.SetPen(*wxWHITE_PEN
);
678 dc
.DrawLine(400, 170, 400, 210);
679 dc
.DrawLine(300, 200, 410, 200);
681 // a few more tests of this kind
682 dc
.SetPen(*wxRED_PEN
);
683 dc
.SetBrush( *wxWHITE_BRUSH
);
684 dc
.DrawRectangle(300, 220, 1, 1);
685 dc
.DrawRectangle(310, 220, 2, 2);
686 dc
.DrawRectangle(320, 220, 3, 3);
687 dc
.DrawRectangle(330, 220, 4, 4);
689 dc
.SetPen(*wxTRANSPARENT_PEN
);
690 dc
.SetBrush( *wxWHITE_BRUSH
);
691 dc
.DrawRectangle(300, 230, 1, 1);
692 dc
.DrawRectangle(310, 230, 2, 2);
693 dc
.DrawRectangle(320, 230, 3, 3);
694 dc
.DrawRectangle(330, 230, 4, 4);
696 // and now for filled rect with outline
697 dc
.SetPen(*wxRED_PEN
);
698 dc
.SetBrush( *wxWHITE_BRUSH
);
699 dc
.DrawRectangle(500, 170, 49, 29);
700 dc
.DrawRectangle(550, 170, 49, 29);
701 dc
.SetPen(*wxWHITE_PEN
);
702 dc
.DrawLine(600, 170, 600, 210);
703 dc
.DrawLine(500, 200, 610, 200);
705 // test the rectangle outline drawing - there should be one pixel between
706 // the rect and the lines
707 dc
.SetPen(*wxWHITE_PEN
);
708 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
709 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
710 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
711 dc
.SetPen(*wxWHITE_PEN
);
712 dc
.DrawLine(250, 270, 250, 310);
713 dc
.DrawLine(150, 300, 260, 300);
715 // test the rectangle filled drawing - there should be one pixel between
716 // the rect and the lines
717 dc
.SetPen(*wxTRANSPARENT_PEN
);
718 dc
.SetBrush( *wxWHITE_BRUSH
);
719 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
720 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
721 dc
.SetPen(*wxWHITE_PEN
);
722 dc
.DrawLine(400, 270, 400, 310);
723 dc
.DrawLine(300, 300, 410, 300);
725 // Added by JACS to demonstrate bizarre behaviour.
726 // With a size of 70, we get a missing red RHS,
727 // and the height is too small, so we get yellow
728 // showing. With a size of 40, it draws as expected:
729 // it just shows a white rectangle with red outline.
731 int totalHeight
= 70;
732 wxBitmap
bitmap2(totalWidth
, totalHeight
);
735 memdc2
.SelectObject(bitmap2
);
737 wxColour
clr(255, 255, 0);
738 wxBrush
yellowBrush(clr
, wxSOLID
);
739 memdc2
.SetBackground(yellowBrush
);
742 wxPen
yellowPen(clr
, 1, wxSOLID
);
744 // Now draw a white rectangle with red outline. It should
745 // entirely eclipse the yellow background.
746 memdc2
.SetPen(*wxRED_PEN
);
747 memdc2
.SetBrush(*wxWHITE_BRUSH
);
749 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
751 memdc2
.SetPen(wxNullPen
);
752 memdc2
.SetBrush(wxNullBrush
);
753 memdc2
.SelectObject(wxNullBitmap
);
755 dc
.DrawBitmap(bitmap2
, 500, 270);
757 // Repeat, but draw directly on dc
758 // Draw a yellow rectangle filling the bitmap
760 x
= 600; int y
= 270;
761 dc
.SetPen(yellowPen
);
762 dc
.SetBrush(yellowBrush
);
763 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
765 // Now draw a white rectangle with red outline. It should
766 // entirely eclipse the yellow background.
767 dc
.SetPen(*wxRED_PEN
);
768 dc
.SetBrush(*wxWHITE_BRUSH
);
770 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
773 void MyCanvas::DrawText(wxDC
& dc
)
775 // set underlined font for testing
776 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, true) );
777 dc
.DrawText( _T("This is text"), 110, 10 );
778 dc
.DrawRotatedText( _T("That is text"), 20, 10, -45 );
780 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
781 // under Win9x (it is not TrueType)
782 dc
.SetFont( *wxSWISS_FONT
);
785 dc
.SetBackgroundMode(wxTRANSPARENT
);
787 for ( int n
= -180; n
< 180; n
+= 30 )
789 text
.Printf(wxT(" %d rotated text"), n
);
790 dc
.DrawRotatedText(text
, 400, 400, n
);
793 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
795 dc
.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
800 dc
.GetTextExtent( _T("This is Swiss 18pt text."), &length
, &height
, &descent
);
801 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
802 dc
.DrawText( text
, 110, 80 );
804 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
805 dc
.DrawText( text
, 110, 120 );
807 dc
.DrawRectangle( 100, 40, 4, height
);
809 // test the logical function effect
811 dc
.SetLogicalFunction(wxINVERT
);
812 dc
.DrawText( _T("There should be no text below"), 110, 150 );
813 dc
.DrawRectangle( 110, y
, 100, height
);
815 // twice drawn inverted should result in invisible
817 dc
.DrawText( _T("Invisible text"), 110, y
);
818 dc
.DrawRectangle( 110, y
, 100, height
);
819 dc
.DrawText( _T("Invisible text"), 110, y
);
820 dc
.DrawRectangle( 110, y
, 100, height
);
821 dc
.SetLogicalFunction(wxCOPY
);
824 dc
.DrawRectangle( 110, y
, 100, height
);
825 dc
.DrawText( _T("Visible text"), 110, y
);
832 } rasterOperations
[] =
834 { wxT("wxAND"), wxAND
},
835 { wxT("wxAND_INVERT"), wxAND_INVERT
},
836 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
837 { wxT("wxCLEAR"), wxCLEAR
},
838 { wxT("wxCOPY"), wxCOPY
},
839 { wxT("wxEQUIV"), wxEQUIV
},
840 { wxT("wxINVERT"), wxINVERT
},
841 { wxT("wxNAND"), wxNAND
},
842 { wxT("wxNO_OP"), wxNO_OP
},
843 { wxT("wxOR"), wxOR
},
844 { wxT("wxOR_INVERT"), wxOR_INVERT
},
845 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
846 { wxT("wxSET"), wxSET
},
847 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
848 { wxT("wxXOR"), wxXOR
},
851 void MyCanvas::DrawImages(wxDC
& dc
, DrawMode mode
)
853 dc
.DrawText(_T("original image"), 0, 0);
854 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
855 dc
.DrawText(_T("with colour mask"), 0, 100);
856 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, true);
857 dc
.DrawText(_T("the mask image"), 0, 200);
858 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
859 dc
.DrawText(_T("masked image"), 0, 300);
860 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, true);
862 int cx
= gs_bmpWithColMask
->GetWidth(),
863 cy
= gs_bmpWithColMask
->GetHeight();
866 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
868 wxCoord x
= 120 + 150*(n%4
),
871 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
872 memDC
.SelectObject(*gs_bmpWithColMask
);
873 if ( mode
== Draw_Stretch
)
875 dc
.StretchBlit(x
, y
, cx
, cy
, &memDC
, 0, 0, cx
/2, cy
/2,
876 rasterOperations
[n
].rop
, true);
880 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, true);
885 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
887 static const wxCoord w
= 60;
888 static const wxCoord h
= 60;
890 // reuse the text colour here
891 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
892 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
895 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
897 wxCoord x
= 20 + 150*(n%4
),
900 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
901 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
902 dc
.DrawRectangle(x
, y
, w
, h
);
903 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
904 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
907 // now some filled rectangles
908 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
910 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
912 wxCoord x
= 20 + 150*(n%4
),
915 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
916 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
917 dc
.DrawRectangle(x
, y
, w
, h
);
921 #if wxUSE_GRAPHICS_CONTEXT
923 void MyCanvas::DrawAlpha(wxDC
& no_dc
)
925 void MyCanvas::DrawAlpha(wxDC
& dc
)
933 wxDouble margin
= 20 ;
934 wxDouble width
= 180 ;
935 wxDouble radius
= 30 ;
937 dc
.SetPen( wxPen( wxColour( 128, 0, 0, 255 ),12, wxSOLID
));
938 dc
.SetBrush( wxBrush( wxColour( 255, 0, 0, 255),wxSOLID
));
940 wxRect
r(margin
,margin
+width
*0.66,width
,width
) ;
942 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
944 dc
.SetPen( wxPen( wxColour( 0, 0, 128, 255 ),12, wxSOLID
));
945 dc
.SetBrush( wxBrush( wxColour( 0, 0, 255, 255),wxSOLID
));
947 r
.Offset( width
* 0.8 , - width
* 0.66 ) ;
949 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
951 dc
.SetPen( wxPen( wxColour( 128, 128, 0, 255 ),12, wxSOLID
));
952 dc
.SetBrush( wxBrush( wxColour( 192, 192, 0, 255),wxSOLID
));
954 r
.Offset( width
* 0.8 , width
*0.5 ) ;
956 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
958 dc
.SetPen( *wxTRANSPARENT_PEN
) ;
959 dc
.SetBrush( wxBrush( wxColour(255,255,128,128) ) );
960 dc
.DrawRoundedRectangle( 0 , margin
+ width
/ 2 , width
* 3 , 100 , radius
) ;
962 dc
.SetTextForeground( wxColour(255,255,0,128) );
963 dc
.SetFont( wxFont( 40, wxFONTFAMILY_SWISS
, wxFONTSTYLE_ITALIC
, wxFONTWEIGHT_NORMAL
) );
964 dc
.DrawText( wxT("Hello!"), 120, 80 );
969 #if wxUSE_GRAPHICS_CONTEXT
971 const int BASE
= 80.0;
972 const int BASE2
= BASE
/2;
973 const int BASE4
= BASE
/4;
975 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
978 // modeled along Robin Dunn's GraphicsContext.py sample
980 void MyCanvas::DrawGraphics(wxGraphicsContext
* gc
)
982 wxFont font
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
983 gc
->SetFont(font
,*wxBLACK
);
985 // make a path that contains a circle and some lines, centered at 0,0
986 wxGraphicsPath path
= gc
->CreatePath() ;
987 path
.AddCircle( 0, 0, BASE2
);
988 path
.MoveToPoint(0, -BASE2
);
989 path
.AddLineToPoint(0, BASE2
);
990 path
.MoveToPoint(-BASE2
, 0);
991 path
.AddLineToPoint(BASE2
, 0);
993 path
.AddRectangle(-BASE4
, -BASE4
/2, BASE2
, BASE4
);
995 // Now use that path to demonstrate various capbilites of the grpahics context
996 gc
->PushState(); // save current translation/scale/other state
997 gc
->Translate(60, 75); // reposition the context origin
999 gc
->SetPen(wxPen("navy", 1));
1000 gc
->SetBrush(wxBrush("pink"));
1002 for( int i
= 0 ; i
< 3 ; ++i
)
1008 label
= "StrokePath";
1018 gc
->GetTextExtent(label
, &w
, &h
, NULL
, NULL
);
1019 gc
->DrawText(label
, -w
/2, -BASE2
-h
-4);
1023 gc
->StrokePath(path
);
1032 gc
->Translate(2*BASE
, 0);
1035 gc
->PopState(); // restore saved state
1036 gc
->PushState(); // save it again
1037 gc
->Translate(60, 200); // offset to the lower part of the window
1039 gc
->DrawText("Scale", 0, -BASE2
);
1040 gc
->Translate(0, 20);
1042 gc
->SetBrush(wxBrush(wxColour(178, 34, 34, 128)));// 128 == half transparent
1043 for( int i
= 0 ; i
< 8 ; ++i
)
1045 gc
->Scale(1.08, 1.08); // increase scale by 8%
1050 gc
->PopState(); // restore saved state
1051 gc
->PushState(); // save it again
1052 gc
->Translate(400, 200);
1054 gc
->DrawText("Rotate", 0, -BASE2
);
1056 // Move the origin over to the next location
1057 gc
->Translate(0, 75);
1059 // draw our path again, rotating it about the central point,
1060 // and changing colors as we go
1061 for ( int angle
= 0 ; angle
< 360 ; angle
+= 30 )
1063 gc
->PushState(); // save this new current state so we can
1064 // pop back to it at the end of the loop
1065 wxImage::RGBValue val
= wxImage::HSVtoRGB(wxImage::HSVValue(float(angle
)/360, 1, 1));
1066 gc
->SetBrush(wxBrush(wxColour(val
.red
, val
.green
, val
.blue
, 64)));
1067 gc
->SetPen(wxPen(wxColour(val
.red
, val
.green
, val
.blue
, 128)));
1069 // use translate to artfully reposition each drawn path
1070 gc
->Translate(1.5 * BASE2
* cos(DegToRad(angle
)),
1071 1.5 * BASE2
* sin(DegToRad(angle
)));
1073 // use Rotate to rotate the path
1074 gc
->Rotate(DegToRad(angle
));
1084 void MyCanvas::DrawCircles(wxDC
& dc
)
1090 dc
.SetPen( *wxRED_PEN
);
1091 dc
.SetBrush( *wxGREEN_BRUSH
);
1093 dc
.DrawText(_T("Some circles"), 0, y
);
1094 dc
.DrawCircle(x
, y
, r
);
1095 dc
.DrawCircle(x
+ 2*r
, y
, r
);
1096 dc
.DrawCircle(x
+ 4*r
, y
, r
);
1099 dc
.DrawText(_T("And ellipses"), 0, y
);
1100 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
1101 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
1102 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
1105 dc
.DrawText(_T("And arcs"), 0, y
);
1106 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
1107 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
1108 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
1111 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
1112 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
1113 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
1114 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
1116 // same as above, just transparent brush
1118 dc
.SetPen( *wxRED_PEN
);
1119 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1122 dc
.DrawText(_T("Some circles"), 0, y
);
1123 dc
.DrawCircle(x
, y
, r
);
1124 dc
.DrawCircle(x
+ 2*r
, y
, r
);
1125 dc
.DrawCircle(x
+ 4*r
, y
, r
);
1128 dc
.DrawText(_T("And ellipses"), 0, y
);
1129 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
1130 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
1131 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
1134 dc
.DrawText(_T("And arcs"), 0, y
);
1135 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
1136 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
1137 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
1140 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
1141 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
1142 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
1143 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
1147 void MyCanvas::DrawSplines(wxDC
& dc
)
1150 dc
.DrawText(_T("Some splines"), 10, 5);
1152 // values are hardcoded rather than randomly generated
1153 // so the output can be compared between native
1154 // implementations on platforms with different random
1158 const wxPoint
center( R
+ 20, R
+ 20 );
1159 const int angles
[7] = { 0, 10, 33, 77, 13, 145, 90 };
1160 const int radii
[5] = { 100 , 59, 85, 33, 90 };
1164 // background spline calculation
1165 unsigned int radius_pos
= 0;
1166 unsigned int angle_pos
= 0;
1168 for ( int i
= 0; i
< n
; i
++ )
1170 angle
+= angles
[ angle_pos
];
1171 int r
= R
* radii
[ radius_pos
] / 100;
1172 pts
[ i
].x
= center
.x
+ (wxCoord
)( r
* cos( M_PI
* angle
/ 180.0) );
1173 pts
[ i
].y
= center
.y
+ (wxCoord
)( r
* sin( M_PI
* angle
/ 180.0) );
1176 if ( angle_pos
>= WXSIZEOF(angles
) ) angle_pos
= 0;
1179 if ( radius_pos
>= WXSIZEOF(radii
) ) radius_pos
= 0;
1182 // background spline drawing
1183 dc
.SetPen(*wxRED_PEN
);
1184 dc
.DrawSpline(WXSIZEOF(pts
), pts
);
1186 // less detailed spline calculation
1187 wxPoint letters
[4][5];
1189 letters
[0][0] = wxPoint( 0,1); // O O
1190 letters
[0][1] = wxPoint( 1,3); // * *
1191 letters
[0][2] = wxPoint( 2,2); // * O *
1192 letters
[0][3] = wxPoint( 3,3); // * * * *
1193 letters
[0][4] = wxPoint( 4,1); // O O
1195 letters
[1][0] = wxPoint( 5,1); // O*O
1196 letters
[1][1] = wxPoint( 6,1); // *
1197 letters
[1][2] = wxPoint( 7,2); // O
1198 letters
[1][3] = wxPoint( 8,3); // *
1199 letters
[1][4] = wxPoint( 9,3); // O*O
1201 letters
[2][0] = wxPoint( 5,3); // O*O
1202 letters
[2][1] = wxPoint( 6,3); // *
1203 letters
[2][2] = wxPoint( 7,2); // O
1204 letters
[2][3] = wxPoint( 8,1); // *
1205 letters
[2][4] = wxPoint( 9,1); // O*O
1207 letters
[3][0] = wxPoint(10,0); // O O
1208 letters
[3][1] = wxPoint(11,3); // * *
1209 letters
[3][2] = wxPoint(12,1); // * O *
1210 letters
[3][3] = wxPoint(13,3); // * * * *
1211 letters
[3][4] = wxPoint(14,0); // O O
1213 const int dx
= 2 * R
/ letters
[3][4].x
;
1214 const int h
[4] = { -R
/2, 0, R
/4, R
/2 };
1216 for ( int m
= 0; m
< 4; m
++ )
1218 for ( int n
= 0; n
< 5; n
++ )
1220 letters
[m
][n
].x
= center
.x
- R
+ letters
[m
][n
].x
* dx
;
1221 letters
[m
][n
].y
= center
.y
+ h
[ letters
[m
][n
].y
];
1224 dc
.SetPen( wxPen( wxT("blue"), 1, wxDOT
) );
1225 dc
.DrawLines(5, letters
[m
]);
1226 dc
.SetPen( wxPen( wxT("black"), 4, wxSOLID
) );
1227 dc
.DrawSpline(5, letters
[m
]);
1231 dc
.DrawText(_T("Splines not supported."), 10, 5);
1235 void MyCanvas::DrawGradients(wxDC
& dc
)
1237 static const int TEXT_HEIGHT
= 15;
1240 wxRect
r(10, 10, 50, 50);
1241 dc
.DrawText(_T("wxRIGHT"), r
.x
, r
.y
);
1242 r
.Offset(0, TEXT_HEIGHT
);
1243 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxRIGHT
);
1245 r
.Offset(0, r
.height
+ 10);
1246 dc
.DrawText(_T("wxLEFT"), r
.x
, r
.y
);
1247 r
.Offset(0, TEXT_HEIGHT
);
1248 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxLEFT
);
1250 r
.Offset(0, r
.height
+ 10);
1251 dc
.DrawText(_T("wxDOWN"), r
.x
, r
.y
);
1252 r
.Offset(0, TEXT_HEIGHT
);
1253 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxDOWN
);
1255 r
.Offset(0, r
.height
+ 10);
1256 dc
.DrawText(_T("wxUP"), r
.x
, r
.y
);
1257 r
.Offset(0, TEXT_HEIGHT
);
1258 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxUP
);
1262 r
= wxRect(200, 10, 50, 50);
1263 dc
.DrawText(_T("Blue inside"), r
.x
, r
.y
);
1264 r
.Offset(0, TEXT_HEIGHT
);
1265 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
);
1267 r
.Offset(0, r
.height
+ 10);
1268 dc
.DrawText(_T("White inside"), r
.x
, r
.y
);
1269 r
.Offset(0, TEXT_HEIGHT
);
1270 dc
.GradientFillConcentric(r
, *wxWHITE
, *wxBLUE
);
1272 r
.Offset(0, r
.height
+ 10);
1273 dc
.DrawText(_T("Blue in top left corner"), r
.x
, r
.y
);
1274 r
.Offset(0, TEXT_HEIGHT
);
1275 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
, wxPoint(0, 0));
1277 r
.Offset(0, r
.height
+ 10);
1278 dc
.DrawText(_T("Blue in bottom right corner"), r
.x
, r
.y
);
1279 r
.Offset(0, TEXT_HEIGHT
);
1280 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
, wxPoint(r
.width
, r
.height
));
1282 // check that the area filled by the gradient is exactly the interior of
1286 dc
.DrawText("The interior should be filled but", r
.x
, r
.y
);
1288 dc
.DrawText(" the red border should remain visible:", r
.x
, r
.y
);
1299 dc
.SetPen(wxPen(wxColour(255, 0, 0)));
1300 dc
.DrawRectangle(r
);
1302 dc
.GradientFillLinear(r
, wxColour(0,255,0), wxColour(0,0,0), wxNORTH
);
1303 dc
.DrawRectangle(r2
);
1305 dc
.GradientFillLinear(r2
, wxColour(0,0,0), wxColour(0,255,0), wxSOUTH
);
1306 dc
.DrawRectangle(r3
);
1308 dc
.GradientFillLinear(r3
, wxColour(0,255,0), wxColour(0,0,0), wxEAST
);
1309 dc
.DrawRectangle(r4
);
1311 dc
.GradientFillLinear(r4
, wxColour(0,0,0), wxColour(0,255,0), wxWEST
);
1314 void MyCanvas::DrawRegions(wxDC
& dc
)
1316 dc
.DrawText(_T("You should see a red rect partly covered by a cyan one ")
1317 _T("on the left"), 10, 5);
1318 dc
.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
1319 10, 5 + dc
.GetCharHeight());
1320 dc
.DrawText(_T("The second copy should be identical but right part of it ")
1321 _T("should be offset by 10 pixels."),
1322 10, 5 + 2*dc
.GetCharHeight());
1324 DrawRegionsHelper(dc
, 10, true);
1325 DrawRegionsHelper(dc
, 350, false);
1328 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
1332 dc
.DestroyClippingRegion();
1333 dc
.SetBrush( *wxWHITE_BRUSH
);
1334 dc
.SetPen( *wxTRANSPARENT_PEN
);
1335 dc
.DrawRectangle( x
, y
, 310, 310 );
1337 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
1339 dc
.SetBrush( *wxRED_BRUSH
);
1340 dc
.DrawRectangle( x
, y
, 310, 310 );
1342 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
1344 dc
.SetBrush( *wxCYAN_BRUSH
);
1345 dc
.DrawRectangle( x
, y
, 310, 310 );
1347 dc
.DestroyClippingRegion();
1349 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
1350 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
1352 region
.Offset(10, 10);
1354 dc
.SetDeviceClippingRegion(region
);
1356 dc
.SetBrush( *wxGREY_BRUSH
);
1357 dc
.DrawRectangle( x
, y
, 310, 310 );
1359 if (m_smile_bmp
.Ok())
1361 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, true );
1362 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, true );
1363 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, true );
1364 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, true );
1365 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, true );
1369 #if TEST_CAIRO_EVERYWHERE
1370 extern wxGraphicsRenderer
* gCairoRenderer
;
1373 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
1375 wxPaintDC
pdc(this);
1377 #if wxUSE_GRAPHICS_CONTEXT
1378 #if TEST_CAIRO_EVERYWHERE
1380 gdc
.SetGraphicsContext( gCairoRenderer
->CreateContext( pdc
) );
1384 wxDC
&dc
= m_useContext
? (wxDC
&) gdc
: (wxDC
&) pdc
;
1391 m_owner
->PrepareDC(dc
);
1393 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
1394 if ( m_owner
->m_backgroundBrush
.Ok() )
1395 dc
.SetBackground( m_owner
->m_backgroundBrush
);
1396 if ( m_owner
->m_colourForeground
.Ok() )
1397 dc
.SetTextForeground( m_owner
->m_colourForeground
);
1398 if ( m_owner
->m_colourBackground
.Ok() )
1399 dc
.SetTextBackground( m_owner
->m_colourBackground
);
1401 if ( m_owner
->m_textureBackground
) {
1402 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
1403 wxColour
clr(0,128,0);
1404 wxBrush
b(clr
, wxSOLID
);
1405 dc
.SetBackground(b
);
1410 dc
.SetClippingRegion(100, 100, 100, 100);
1414 if ( m_owner
->m_textureBackground
)
1416 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
1417 for ( int i
= 0; i
< 200; i
++ )
1418 dc
.DrawLine(0, i
*10, i
*10, 0);
1444 DrawTestLines( 0, 100, 0, dc
);
1445 DrawTestLines( 0, 320, 1, dc
);
1446 DrawTestLines( 0, 540, 2, dc
);
1447 DrawTestLines( 0, 760, 6, dc
);
1451 DrawTestBrushes(dc
);
1459 DrawImages(dc
, Draw_Normal
);
1462 case Show_Mask_Stretch
:
1463 DrawImages(dc
, Draw_Stretch
);
1467 DrawWithLogicalOps(dc
);
1470 #if wxUSE_GRAPHICS_CONTEXT
1475 DrawGraphics(gdc
.GetGraphicsContext());
1488 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
1492 wxClientDC
dc(this);
1494 m_owner
->PrepareDC(dc
);
1496 wxPoint pos
= event
.GetPosition();
1497 long x
= dc
.DeviceToLogicalX( pos
.x
);
1498 long y
= dc
.DeviceToLogicalY( pos
.y
);
1500 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
1501 m_owner
->SetStatusText( str
);
1507 event
.GetPosition(&x
,&y
);
1508 CalcUnscrolledPosition( x
, y
, &xx
, &yy
);
1509 m_currentpoint
= wxPoint( xx
, yy
) ;
1510 wxRect
newrect ( m_anchorpoint
, m_currentpoint
) ;
1512 wxClientDC
dc( this ) ;
1515 wxDCOverlay
overlaydc( m_overlay
, &dc
);
1518 dc
.SetPen( *wxGREY_PEN
);
1519 dc
.SetBrush( wxColour( 192,192,192,64 ) );
1521 dc
.SetPen( wxPen( *wxLIGHT_GREY
, 2, wxSOLID
) );
1522 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1524 dc
.DrawRectangle( newrect
);
1528 #endif // wxUSE_STATUSBAR
1531 void MyCanvas::OnMouseDown(wxMouseEvent
&event
)
1534 event
.GetPosition(&x
,&y
);
1535 CalcUnscrolledPosition( x
, y
, &xx
, &yy
);
1536 m_anchorpoint
= wxPoint( xx
, yy
) ;
1537 m_currentpoint
= m_anchorpoint
;
1538 m_rubberBand
= true ;
1542 void MyCanvas::OnMouseUp(wxMouseEvent
&event
)
1548 wxClientDC
dc( this );
1550 wxDCOverlay
overlaydc( m_overlay
, &dc
);
1554 m_rubberBand
= false;
1557 event
.GetPosition(&x
,&y
);
1558 CalcUnscrolledPosition( x
, y
, &xx
, &yy
);
1561 str
.Printf( wxT("Rectangle selection from %d,%d to %d,%d"),
1562 m_anchorpoint
.x
, m_anchorpoint
.y
, (int)xx
, (int)yy
);
1563 wxMessageBox( str
, wxT("Rubber-Banding") );
1568 // ----------------------------------------------------------------------------
1570 // ----------------------------------------------------------------------------
1572 // the event tables connect the wxWidgets events with the functions (event
1573 // handlers) which process them. It can be also done at run-time, but for the
1574 // simple menu events like this the static method is much simpler.
1575 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1576 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1577 EVT_MENU (File_About
, MyFrame::OnAbout
)
1578 EVT_MENU (File_Clip
, MyFrame::OnClip
)
1579 #if wxUSE_GRAPHICS_CONTEXT
1580 EVT_MENU (File_GraphicContext
, MyFrame::OnGraphicContext
)
1583 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1585 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1588 // frame constructor
1589 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1590 : wxFrame((wxFrame
*)NULL
, wxID_ANY
, title
, pos
, size
,
1591 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1593 // set the frame icon
1594 SetIcon(wxICON(mondrian
));
1596 wxMenu
*menuFile
= new wxMenu
;
1597 menuFile
->Append(File_ShowDefault
, _T("&Default screen\tF1"));
1598 menuFile
->Append(File_ShowText
, _T("&Text screen\tF2"));
1599 menuFile
->Append(File_ShowLines
, _T("&Lines screen\tF3"));
1600 menuFile
->Append(File_ShowBrushes
, _T("&Brushes screen\tF4"));
1601 menuFile
->Append(File_ShowPolygons
, _T("&Polygons screen\tF5"));
1602 menuFile
->Append(File_ShowMask
, _T("&Mask screen\tF6"));
1603 menuFile
->Append(File_ShowMaskStretch
, _T("1/&2 scaled mask\tShift-F6"));
1604 menuFile
->Append(File_ShowOps
, _T("&ROP screen\tF7"));
1605 menuFile
->Append(File_ShowRegions
, _T("Re&gions screen\tF8"));
1606 menuFile
->Append(File_ShowCircles
, _T("&Circles screen\tF9"));
1607 #if wxUSE_GRAPHICS_CONTEXT
1608 menuFile
->Append(File_ShowAlpha
, _T("&Alpha screen\tF10"));
1610 menuFile
->Append(File_ShowSplines
, _T("&Splines screen\tF11"));
1611 menuFile
->Append(File_ShowGradients
, _T("&Gradients screen\tF12"));
1612 #if wxUSE_GRAPHICS_CONTEXT
1613 menuFile
->Append(File_ShowGraphics
, _T("&Graphics screen"));
1615 menuFile
->AppendSeparator();
1616 menuFile
->AppendCheckItem(File_Clip
, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
1617 #if wxUSE_GRAPHICS_CONTEXT
1618 menuFile
->AppendCheckItem(File_GraphicContext
, _T("&Use GraphicContext\tCtrl-Y"), _T("Use GraphicContext"));
1620 menuFile
->AppendSeparator();
1621 menuFile
->Append(File_About
, _T("&About...\tCtrl-A"), _T("Show about dialog"));
1622 menuFile
->AppendSeparator();
1623 menuFile
->Append(File_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
1625 wxMenu
*menuMapMode
= new wxMenu
;
1626 menuMapMode
->Append( MapMode_Text
, _T("&TEXT map mode") );
1627 menuMapMode
->Append( MapMode_Lometric
, _T("&LOMETRIC map mode") );
1628 menuMapMode
->Append( MapMode_Twips
, _T("T&WIPS map mode") );
1629 menuMapMode
->Append( MapMode_Points
, _T("&POINTS map mode") );
1630 menuMapMode
->Append( MapMode_Metric
, _T("&METRIC map mode") );
1632 wxMenu
*menuUserScale
= new wxMenu
;
1633 menuUserScale
->Append( UserScale_StretchHoriz
, _T("Stretch &horizontally\tCtrl-H") );
1634 menuUserScale
->Append( UserScale_ShrinkHoriz
, _T("Shrin&k horizontally\tCtrl-G") );
1635 menuUserScale
->Append( UserScale_StretchVertic
, _T("Stretch &vertically\tCtrl-V") );
1636 menuUserScale
->Append( UserScale_ShrinkVertic
, _T("&Shrink vertically\tCtrl-W") );
1637 menuUserScale
->AppendSeparator();
1638 menuUserScale
->Append( UserScale_Restore
, _T("&Restore to normal\tCtrl-0") );
1640 wxMenu
*menuAxis
= new wxMenu
;
1641 menuAxis
->AppendCheckItem( AxisMirror_Horiz
, _T("Mirror horizontally\tCtrl-M") );
1642 menuAxis
->AppendCheckItem( AxisMirror_Vertic
, _T("Mirror vertically\tCtrl-N") );
1644 wxMenu
*menuLogical
= new wxMenu
;
1645 menuLogical
->Append( LogicalOrigin_MoveDown
, _T("Move &down\tCtrl-D") );
1646 menuLogical
->Append( LogicalOrigin_MoveUp
, _T("Move &up\tCtrl-U") );
1647 menuLogical
->Append( LogicalOrigin_MoveLeft
, _T("Move &right\tCtrl-L") );
1648 menuLogical
->Append( LogicalOrigin_MoveRight
, _T("Move &left\tCtrl-R") );
1649 menuLogical
->AppendSeparator();
1650 menuLogical
->Append( LogicalOrigin_Set
, _T("Set to (&100, 100)\tShift-Ctrl-1") );
1651 menuLogical
->Append( LogicalOrigin_Restore
, _T("&Restore to normal\tShift-Ctrl-0") );
1653 wxMenu
*menuColour
= new wxMenu
;
1655 menuColour
->Append( Colour_TextForeground
, _T("Text &foreground...") );
1656 menuColour
->Append( Colour_TextBackground
, _T("Text &background...") );
1657 menuColour
->Append( Colour_Background
, _T("Background &colour...") );
1658 #endif // wxUSE_COLOURDLG
1659 menuColour
->AppendCheckItem( Colour_BackgroundMode
, _T("&Opaque/transparent\tCtrl-B") );
1660 menuColour
->AppendCheckItem( Colour_TextureBackgound
, _T("Draw textured back&ground\tCtrl-T") );
1662 // now append the freshly created menu to the menu bar...
1663 wxMenuBar
*menuBar
= new wxMenuBar
;
1664 menuBar
->Append(menuFile
, _T("&File"));
1665 menuBar
->Append(menuMapMode
, _T("&Mode"));
1666 menuBar
->Append(menuUserScale
, _T("&Scale"));
1667 menuBar
->Append(menuAxis
, _T("&Axis"));
1668 menuBar
->Append(menuLogical
, _T("&Origin"));
1669 menuBar
->Append(menuColour
, _T("&Colours"));
1671 // ... and attach this menu bar to the frame
1672 SetMenuBar(menuBar
);
1676 SetStatusText(_T("Welcome to wxWidgets!"));
1677 #endif // wxUSE_STATUSBAR
1679 m_mapMode
= wxMM_TEXT
;
1682 m_xLogicalOrigin
= 0;
1683 m_yLogicalOrigin
= 0;
1685 m_yAxisReversed
= false;
1686 m_backgroundMode
= wxSOLID
;
1687 m_colourForeground
= *wxRED
;
1688 m_colourBackground
= *wxBLUE
;
1689 m_textureBackground
= false;
1691 m_canvas
= new MyCanvas( this );
1692 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1697 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1699 // true is to force the frame to close
1703 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1706 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1707 wxT("This sample tests various primitive drawing functions\n")
1708 wxT("(without any attempts to prevent flicker).\n")
1709 wxT("Copyright (c) Robert Roebling 1999")
1712 wxMessageBox(msg
, _T("About Drawing"), wxOK
| wxICON_INFORMATION
, this);
1715 void MyFrame::OnClip(wxCommandEvent
& event
)
1717 m_canvas
->Clip(event
.IsChecked());
1720 #if wxUSE_GRAPHICS_CONTEXT
1721 void MyFrame::OnGraphicContext(wxCommandEvent
& event
)
1723 m_canvas
->UseGraphicContext(event
.IsChecked());
1727 void MyFrame::OnShow(wxCommandEvent
& event
)
1729 m_canvas
->ToShow((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1732 void MyFrame::OnOption(wxCommandEvent
& event
)
1734 switch (event
.GetId())
1737 m_mapMode
= wxMM_TEXT
;
1739 case MapMode_Lometric
:
1740 m_mapMode
= wxMM_LOMETRIC
;
1743 m_mapMode
= wxMM_TWIPS
;
1745 case MapMode_Points
:
1746 m_mapMode
= wxMM_POINTS
;
1748 case MapMode_Metric
:
1749 m_mapMode
= wxMM_METRIC
;
1752 case LogicalOrigin_MoveDown
:
1753 m_yLogicalOrigin
+= 10;
1755 case LogicalOrigin_MoveUp
:
1756 m_yLogicalOrigin
-= 10;
1758 case LogicalOrigin_MoveLeft
:
1759 m_xLogicalOrigin
+= 10;
1761 case LogicalOrigin_MoveRight
:
1762 m_xLogicalOrigin
-= 10;
1764 case LogicalOrigin_Set
:
1766 m_yLogicalOrigin
= -100;
1768 case LogicalOrigin_Restore
:
1770 m_yLogicalOrigin
= 0;
1773 case UserScale_StretchHoriz
:
1774 m_xUserScale
*= 1.10;
1776 case UserScale_ShrinkHoriz
:
1777 m_xUserScale
/= 1.10;
1779 case UserScale_StretchVertic
:
1780 m_yUserScale
*= 1.10;
1782 case UserScale_ShrinkVertic
:
1783 m_yUserScale
/= 1.10;
1785 case UserScale_Restore
:
1790 case AxisMirror_Vertic
:
1791 m_yAxisReversed
= !m_yAxisReversed
;
1793 case AxisMirror_Horiz
:
1794 m_xAxisReversed
= !m_xAxisReversed
;
1798 case Colour_TextForeground
:
1799 m_colourForeground
= SelectColour();
1801 case Colour_TextBackground
:
1802 m_colourBackground
= SelectColour();
1804 case Colour_Background
:
1806 wxColour col
= SelectColour();
1809 m_backgroundBrush
.SetColour(col
);
1813 #endif // wxUSE_COLOURDLG
1815 case Colour_BackgroundMode
:
1816 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1820 case Colour_TextureBackgound
:
1821 m_textureBackground
= ! m_textureBackground
;
1829 m_canvas
->Refresh();
1832 void MyFrame::PrepareDC(wxDC
& dc
)
1834 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1835 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1836 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1837 dc
.SetMapMode( m_mapMode
);
1841 wxColour
MyFrame::SelectColour()
1845 wxColourDialog
dialog(this, &data
);
1847 if ( dialog
.ShowModal() == wxID_OK
)
1849 col
= dialog
.GetColourData().GetColour();
1854 #endif // wxUSE_COLOURDLG