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"
39 #define wxTEST_GRAPHICS 1
41 #define TEST_CAIRO_EVERYWHERE 0
44 #include "wx/graphics.h"
45 #include "wx/dcgraph.h"
46 #if wxUSE_GRAPHICS_CONTEXT == 0
47 #undef wxTEST_GRAPHICS
48 #define wxTEST_GRAPHICS 0
51 #undef wxUSE_GRAPHICS_CONTEXT
52 #define wxUSE_GRAPHICS_CONTEXT 0
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 // the application icon
60 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
61 #include "mondrian.xpm"
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 // what do we show on screen (there are too many shapes to put them all on
69 // screen simultaneously)
83 #if wxUSE_GRAPHICS_CONTEXT
91 // ----------------------------------------------------------------------------
93 // ----------------------------------------------------------------------------
95 static wxBitmap
*gs_bmpNoMask
= NULL
,
96 *gs_bmpWithColMask
= NULL
,
98 *gs_bmpWithMask
= NULL
,
100 *gs_bmp4_mono
= NULL
,
103 // ----------------------------------------------------------------------------
105 // ----------------------------------------------------------------------------
107 // Define a new application type, each program should derive a class from wxApp
108 class MyApp
: public wxApp
111 // override base class virtuals
112 // ----------------------------
114 // this one is called on application startup and is a good place for the app
115 // initialization (doing it here and not in the ctor allows to have an error
116 // return: if OnInit() returns false, the application terminates)
117 virtual bool OnInit();
119 virtual int OnExit() { DeleteBitmaps(); return 0; }
122 void DeleteBitmaps();
129 // Define a new frame type: this is going to be our main frame
130 class MyFrame
: public wxFrame
134 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
136 // event handlers (these functions should _not_ be virtual)
137 void OnQuit(wxCommandEvent
& event
);
138 void OnAbout(wxCommandEvent
& event
);
139 void OnClip(wxCommandEvent
& event
);
140 #if wxUSE_GRAPHICS_CONTEXT
141 void OnGraphicContext(wxCommandEvent
& event
);
143 void OnShow(wxCommandEvent
&event
);
144 void OnOption(wxCommandEvent
&event
);
147 wxColour
SelectColour();
148 #endif // wxUSE_COLOURDLG
149 void PrepareDC(wxDC
& dc
);
151 int m_backgroundMode
;
152 int m_textureBackground
;
156 int m_xLogicalOrigin
;
157 int m_yLogicalOrigin
;
158 bool m_xAxisReversed
,
160 wxColour m_colourForeground
, // these are _text_ colours
162 wxBrush m_backgroundBrush
;
166 // any class wishing to process wxWidgets events must use this macro
167 DECLARE_EVENT_TABLE()
170 // define a scrollable canvas for drawing onto
171 class MyCanvas
: public wxScrolledWindow
174 MyCanvas( MyFrame
*parent
);
176 void OnPaint(wxPaintEvent
&event
);
177 void OnMouseMove(wxMouseEvent
&event
);
178 void OnMouseDown(wxMouseEvent
&event
);
179 void OnMouseUp(wxMouseEvent
&event
);
181 void ToShow(ScreenToShow show
) { m_show
= show
; Refresh(); }
183 // set or remove the clipping region
184 void Clip(bool clip
) { m_clip
= clip
; Refresh(); }
185 #if wxUSE_GRAPHICS_CONTEXT
186 void UseGraphicContext(bool use
) { m_useContext
= use
; Refresh(); }
196 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
197 void DrawTestPoly(wxDC
& dc
);
198 void DrawTestBrushes(wxDC
& dc
);
199 void DrawText(wxDC
& dc
);
200 void DrawImages(wxDC
& dc
, DrawMode mode
);
201 void DrawWithLogicalOps(wxDC
& dc
);
202 #if wxUSE_GRAPHICS_CONTEXT
203 void DrawAlpha(wxDC
& dc
);
204 void DrawGraphics(wxGraphicsContext
* gc
);
206 void DrawRegions(wxDC
& dc
);
207 void DrawCircles(wxDC
& dc
);
208 void DrawSplines(wxDC
& dc
);
209 void DrawDefault(wxDC
& dc
);
210 void DrawGradients(wxDC
& dc
);
212 void DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
);
218 wxBitmap m_smile_bmp
;
223 wxPoint m_anchorpoint
;
224 wxPoint m_currentpoint
;
225 #if wxUSE_GRAPHICS_CONTEXT
229 DECLARE_EVENT_TABLE()
232 // ----------------------------------------------------------------------------
234 // ----------------------------------------------------------------------------
236 // IDs for the controls and the menu commands
240 File_Quit
= wxID_EXIT
,
241 File_About
= wxID_ABOUT
,
243 MenuShow_First
= wxID_HIGHEST
,
244 File_ShowDefault
= MenuShow_First
,
250 File_ShowMaskStretch
,
255 #if wxUSE_GRAPHICS_CONTEXT
260 MenuShow_Last
= File_ShowGradients
,
263 #if wxUSE_GRAPHICS_CONTEXT
269 MapMode_Text
= MenuOption_First
,
275 UserScale_StretchHoriz
,
276 UserScale_ShrinkHoriz
,
277 UserScale_StretchVertic
,
278 UserScale_ShrinkVertic
,
284 LogicalOrigin_MoveDown
,
285 LogicalOrigin_MoveUp
,
286 LogicalOrigin_MoveLeft
,
287 LogicalOrigin_MoveRight
,
289 LogicalOrigin_Restore
,
292 Colour_TextForeground
,
293 Colour_TextBackground
,
295 #endif // wxUSE_COLOURDLG
296 Colour_BackgroundMode
,
297 Colour_TextureBackgound
,
299 MenuOption_Last
= Colour_TextureBackgound
302 // ----------------------------------------------------------------------------
303 // event tables and other macros for wxWidgets
304 // ----------------------------------------------------------------------------
307 // Create a new application object: this macro will allow wxWidgets to create
308 // the application object during program execution (it's better than using a
309 // static object for many reasons) and also declares the accessor function
310 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
314 // ============================================================================
316 // ============================================================================
318 // ----------------------------------------------------------------------------
319 // the application class
320 // ----------------------------------------------------------------------------
322 bool MyApp::LoadImages()
324 gs_bmpNoMask
= new wxBitmap
;
325 gs_bmpWithColMask
= new wxBitmap
;
326 gs_bmpMask
= new wxBitmap
;
327 gs_bmpWithMask
= new wxBitmap
;
328 gs_bmp4
= new wxBitmap
;
329 gs_bmp4_mono
= new wxBitmap
;
330 gs_bmp36
= new wxBitmap
;
333 pathList
.Add(_T("."));
334 pathList
.Add(_T(".."));
335 pathList
.Add(_T("../.."));
337 wxString path
= pathList
.FindValidPath(_T("pat4.bmp"));
341 /* 4 colour bitmap */
342 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
343 /* turn into mono-bitmap */
344 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
345 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
346 gs_bmp4_mono
->SetMask(mask4
);
348 path
= pathList
.FindValidPath(_T("pat36.bmp"));
351 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
352 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
353 gs_bmp36
->SetMask(mask36
);
355 path
= pathList
.FindValidPath(_T("image.bmp"));
358 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
359 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
360 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
362 path
= pathList
.FindValidPath(_T("mask.bmp"));
365 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
367 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
368 gs_bmpWithMask
->SetMask(mask
);
370 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
371 gs_bmpWithColMask
->SetMask(mask
);
376 // `Main program' equivalent: the program execution "starts" here
379 if ( !wxApp::OnInit() )
382 // Create the main application window
383 MyFrame
*frame
= new MyFrame(_T("Drawing sample"),
384 wxPoint(50, 50), wxSize(550, 340));
386 // Show it and tell the application that it's our main window
392 wxLogError(wxT("Can't load one of the bitmap files needed ")
393 wxT("for this sample from the current or parent ")
394 wxT("directory, please copy them there."));
406 void MyApp::DeleteBitmaps()
409 delete gs_bmpWithColMask
;
411 delete gs_bmpWithMask
;
417 gs_bmpWithColMask
= NULL
;
419 gs_bmpWithMask
= NULL
;
425 // ----------------------------------------------------------------------------
427 // ----------------------------------------------------------------------------
429 // the event tables connect the wxWidgets events with the functions (event
430 // handlers) which process them.
431 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
432 EVT_PAINT (MyCanvas::OnPaint
)
433 EVT_MOTION (MyCanvas::OnMouseMove
)
434 EVT_LEFT_DOWN (MyCanvas::OnMouseDown
)
435 EVT_LEFT_UP (MyCanvas::OnMouseUp
)
440 MyCanvas::MyCanvas(MyFrame
*parent
)
441 : wxScrolledWindow(parent
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
,
442 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
445 m_show
= Show_Default
;
446 m_smile_bmp
= wxBitmap(smile_xpm
);
447 m_std_icon
= wxArtProvider::GetIcon(wxART_INFORMATION
);
449 m_rubberBand
= false;
450 #if wxUSE_GRAPHICS_CONTEXT
451 m_useContext
= false;
455 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
457 static const wxCoord WIDTH
= 200;
458 static const wxCoord HEIGHT
= 80;
463 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
464 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
465 dc
.DrawText(_T("Solid green"), x
+ 10, y
+ 10);
468 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
469 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
470 dc
.DrawText(_T("Hatched red"), x
+ 10, y
+ 10);
473 dc
.SetBrush(wxBrush(*gs_bmpMask
));
474 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
475 dc
.DrawText(_T("Stipple mono"), x
+ 10, y
+ 10);
478 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
479 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
480 dc
.DrawText(_T("Stipple colour"), x
+ 10, y
+ 10);
483 void MyCanvas::DrawTestPoly(wxDC
& dc
)
485 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
486 dc
.SetBrush(brushHatch
);
489 star
[0] = wxPoint(100, 60);
490 star
[1] = wxPoint(60, 150);
491 star
[2] = wxPoint(160, 100);
492 star
[3] = wxPoint(40, 100);
493 star
[4] = wxPoint(140, 150);
495 dc
.DrawText(_T("You should see two (irregular) stars below, the left one ")
496 _T("hatched"), 10, 10);
497 dc
.DrawText(_T("except for the central region and the right ")
498 _T("one entirely hatched"), 10, 30);
499 dc
.DrawText(_T("The third star only has a hatched outline"), 10, 50);
501 dc
.DrawPolygon(WXSIZEOF(star
), star
, 0, 30);
502 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 30, wxWINDING_RULE
);
505 star2
[0] = wxPoint(0, 100);
506 star2
[1] = wxPoint(-59, -81);
507 star2
[2] = wxPoint(95, 31);
508 star2
[3] = wxPoint(-95, 31);
509 star2
[4] = wxPoint(59, -81);
510 star2
[5] = wxPoint(0, 80);
511 star2
[6] = wxPoint(-47, -64);
512 star2
[7] = wxPoint(76, 24);
513 star2
[8] = wxPoint(-76, 24);
514 star2
[9] = wxPoint(47, -64);
515 int count
[2] = {5, 5};
517 dc
.DrawPolyPolygon(WXSIZEOF(count
), count
, star2
, 450, 150);
520 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
522 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
523 dc
.SetBrush( *wxRED_BRUSH
);
524 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
525 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
527 dc
.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x
+ 150, y
+ 10);
528 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
529 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
530 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
531 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
532 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
533 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
534 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
535 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
536 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
537 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
539 dc
.DrawText(_T("Misc hatches"), x
+ 150, y
+ 70);
540 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
541 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
542 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
543 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
544 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
545 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
546 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
547 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
548 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
549 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
550 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
551 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
553 dc
.DrawText(_T("User dash"), x
+ 150, y
+ 140);
554 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
556 dash1
[0] = 8; // Long dash <---------+
557 dash1
[1] = 2; // Short gap |
558 dash1
[2] = 3; // Short dash |
559 dash1
[3] = 2; // Short gap |
560 dash1
[4] = 3; // Short dash |
561 dash1
[5] = 2; // Short gap and repeat +
562 ud
.SetDashes( 6, dash1
);
564 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
565 dash1
[0] = 5; // Make first dash shorter
566 ud
.SetDashes( 6, dash1
);
568 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
569 dash1
[2] = 5; // Make second dash longer
570 ud
.SetDashes( 6, dash1
);
572 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
573 dash1
[4] = 5; // Make third dash longer
574 ud
.SetDashes( 6, dash1
);
576 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
579 void MyCanvas::DrawDefault(wxDC
& dc
)
582 dc
.DrawCircle(0, 0, 10);
584 #if !defined(wxMAC_USE_CORE_GRAPHICS) || !wxMAC_USE_CORE_GRAPHICS
585 // GetPixel and FloodFill not supported by Mac OS X CoreGraphics
586 // (FloodFill uses Blit from a non-wxMemoryDC)
587 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
588 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
591 dc
.GetPixel(1,1, &tmpColour
);
592 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
595 dc
.DrawCheckMark(5, 80, 15, 15);
596 dc
.DrawCheckMark(25, 80, 30, 30);
597 dc
.DrawCheckMark(60, 80, 60, 60);
599 // this is the test for "blitting bitmap into DC damages selected brush" bug
600 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
602 dc
.SetPen(*wxTRANSPARENT_PEN
);
603 dc
.SetBrush( *wxGREEN_BRUSH
);
604 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
605 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, true);
607 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
608 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
610 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
612 // test for "transparent" bitmap drawing (it intersects with the last
614 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
616 if (m_smile_bmp
.Ok())
617 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, true);
619 dc
.SetBrush( *wxBLACK_BRUSH
);
620 dc
.DrawRectangle( 0, 160, 1000, 300 );
623 wxBitmap
bitmap(20,70);
625 memdc
.SelectObject( bitmap
);
626 memdc
.SetBrush( *wxBLACK_BRUSH
);
627 memdc
.SetPen( *wxWHITE_PEN
);
628 memdc
.DrawRectangle(0,0,20,70);
629 memdc
.DrawLine( 10,0,10,70 );
632 wxPen pen
= *wxRED_PEN
;
634 memdc
.DrawLine( 10, 5,10, 5 );
635 memdc
.DrawLine( 10,10,11,10 );
636 memdc
.DrawLine( 10,15,12,15 );
637 memdc
.DrawLine( 10,20,13,20 );
640 memdc.SetPen(*wxRED_PEN);
641 memdc.DrawLine( 12, 5,12, 5 );
642 memdc.DrawLine( 12,10,13,10 );
643 memdc.DrawLine( 12,15,14,15 );
644 memdc.DrawLine( 12,20,15,20 );
648 memdc
.DrawLine( 10,25,10,25 );
649 memdc
.DrawLine( 10,30, 9,30 );
650 memdc
.DrawLine( 10,35, 8,35 );
651 memdc
.DrawLine( 10,40, 7,40 );
654 dc
.SetPen(*wxWHITE_PEN
);
655 memdc
.SetLogicalFunction( wxINVERT
);
656 memdc
.SetPen( *wxWHITE_PEN
);
657 memdc
.DrawLine( 10,50,10,50 );
658 memdc
.DrawLine( 10,55,11,55 );
659 memdc
.DrawLine( 10,60,12,60 );
660 memdc
.DrawLine( 10,65,13,65 );
662 memdc
.DrawLine( 12,50,12,50 );
663 memdc
.DrawLine( 12,55,13,55 );
664 memdc
.DrawLine( 12,60,14,60 );
665 memdc
.DrawLine( 12,65,15,65 );
667 memdc
.SelectObject( wxNullBitmap
);
668 dc
.DrawBitmap( bitmap
, 10, 170 );
669 wxImage image
= bitmap
.ConvertToImage();
670 image
.Rescale( 60,210 );
671 bitmap
= wxBitmap(image
);
672 dc
.DrawBitmap( bitmap
, 50, 170 );
674 // test the rectangle outline drawing - there should be one pixel between
675 // the rect and the lines
676 dc
.SetPen(*wxWHITE_PEN
);
677 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
678 dc
.DrawRectangle(150, 170, 49, 29);
679 dc
.DrawRectangle(200, 170, 49, 29);
680 dc
.SetPen(*wxWHITE_PEN
);
681 dc
.DrawLine(250, 210, 250, 170);
682 dc
.DrawLine(260, 200, 150, 200);
684 // test the rectangle filled drawing - there should be one pixel between
685 // the rect and the lines
686 dc
.SetPen(*wxTRANSPARENT_PEN
);
687 dc
.SetBrush( *wxWHITE_BRUSH
);
688 dc
.DrawRectangle(300, 170, 49, 29);
689 dc
.DrawRectangle(350, 170, 49, 29);
690 dc
.SetPen(*wxWHITE_PEN
);
691 dc
.DrawLine(400, 170, 400, 210);
692 dc
.DrawLine(300, 200, 410, 200);
694 // a few more tests of this kind
695 dc
.SetPen(*wxRED_PEN
);
696 dc
.SetBrush( *wxWHITE_BRUSH
);
697 dc
.DrawRectangle(300, 220, 1, 1);
698 dc
.DrawRectangle(310, 220, 2, 2);
699 dc
.DrawRectangle(320, 220, 3, 3);
700 dc
.DrawRectangle(330, 220, 4, 4);
702 dc
.SetPen(*wxTRANSPARENT_PEN
);
703 dc
.SetBrush( *wxWHITE_BRUSH
);
704 dc
.DrawRectangle(300, 230, 1, 1);
705 dc
.DrawRectangle(310, 230, 2, 2);
706 dc
.DrawRectangle(320, 230, 3, 3);
707 dc
.DrawRectangle(330, 230, 4, 4);
709 // and now for filled rect with outline
710 dc
.SetPen(*wxRED_PEN
);
711 dc
.SetBrush( *wxWHITE_BRUSH
);
712 dc
.DrawRectangle(500, 170, 49, 29);
713 dc
.DrawRectangle(550, 170, 49, 29);
714 dc
.SetPen(*wxWHITE_PEN
);
715 dc
.DrawLine(600, 170, 600, 210);
716 dc
.DrawLine(500, 200, 610, 200);
718 // test the rectangle outline drawing - there should be one pixel between
719 // the rect and the lines
720 dc
.SetPen(*wxWHITE_PEN
);
721 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
722 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
723 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
724 dc
.SetPen(*wxWHITE_PEN
);
725 dc
.DrawLine(250, 270, 250, 310);
726 dc
.DrawLine(150, 300, 260, 300);
728 // test the rectangle filled drawing - there should be one pixel between
729 // the rect and the lines
730 dc
.SetPen(*wxTRANSPARENT_PEN
);
731 dc
.SetBrush( *wxWHITE_BRUSH
);
732 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
733 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
734 dc
.SetPen(*wxWHITE_PEN
);
735 dc
.DrawLine(400, 270, 400, 310);
736 dc
.DrawLine(300, 300, 410, 300);
738 // Added by JACS to demonstrate bizarre behaviour.
739 // With a size of 70, we get a missing red RHS,
740 // and the height is too small, so we get yellow
741 // showing. With a size of 40, it draws as expected:
742 // it just shows a white rectangle with red outline.
744 int totalHeight
= 70;
745 wxBitmap
bitmap2(totalWidth
, totalHeight
);
748 memdc2
.SelectObject(bitmap2
);
750 wxColour
clr(255, 255, 0);
751 wxBrush
yellowBrush(clr
, wxSOLID
);
752 memdc2
.SetBackground(yellowBrush
);
755 wxPen
yellowPen(clr
, 1, wxSOLID
);
757 // Now draw a white rectangle with red outline. It should
758 // entirely eclipse the yellow background.
759 memdc2
.SetPen(*wxRED_PEN
);
760 memdc2
.SetBrush(*wxWHITE_BRUSH
);
762 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
764 memdc2
.SetPen(wxNullPen
);
765 memdc2
.SetBrush(wxNullBrush
);
766 memdc2
.SelectObject(wxNullBitmap
);
768 dc
.DrawBitmap(bitmap2
, 500, 270);
770 // Repeat, but draw directly on dc
771 // Draw a yellow rectangle filling the bitmap
773 x
= 600; int y
= 270;
774 dc
.SetPen(yellowPen
);
775 dc
.SetBrush(yellowBrush
);
776 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
778 // Now draw a white rectangle with red outline. It should
779 // entirely eclipse the yellow background.
780 dc
.SetPen(*wxRED_PEN
);
781 dc
.SetBrush(*wxWHITE_BRUSH
);
783 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
786 void MyCanvas::DrawText(wxDC
& dc
)
788 // set underlined font for testing
789 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, true) );
790 dc
.DrawText( _T("This is text"), 110, 10 );
791 dc
.DrawRotatedText( _T("That is text"), 20, 10, -45 );
793 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
794 // under Win9x (it is not TrueType)
795 dc
.SetFont( *wxSWISS_FONT
);
798 dc
.SetBackgroundMode(wxTRANSPARENT
);
800 for ( int n
= -180; n
< 180; n
+= 30 )
802 text
.Printf(wxT(" %d rotated text"), n
);
803 dc
.DrawRotatedText(text
, 400, 400, n
);
806 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
808 dc
.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
813 dc
.GetTextExtent( _T("This is Swiss 18pt text."), &length
, &height
, &descent
);
814 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
815 dc
.DrawText( text
, 110, 80 );
817 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
818 dc
.DrawText( text
, 110, 120 );
820 dc
.DrawRectangle( 100, 40, 4, height
);
822 // test the logical function effect
824 dc
.SetLogicalFunction(wxINVERT
);
825 dc
.DrawText( _T("There should be no text below"), 110, 150 );
826 dc
.DrawRectangle( 110, y
, 100, height
);
828 // twice drawn inverted should result in invisible
830 dc
.DrawText( _T("Invisible text"), 110, y
);
831 dc
.DrawRectangle( 110, y
, 100, height
);
832 dc
.DrawText( _T("Invisible text"), 110, y
);
833 dc
.DrawRectangle( 110, y
, 100, height
);
834 dc
.SetLogicalFunction(wxCOPY
);
837 dc
.DrawRectangle( 110, y
, 100, height
);
838 dc
.DrawText( _T("Visible text"), 110, y
);
845 } rasterOperations
[] =
847 { wxT("wxAND"), wxAND
},
848 { wxT("wxAND_INVERT"), wxAND_INVERT
},
849 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
850 { wxT("wxCLEAR"), wxCLEAR
},
851 { wxT("wxCOPY"), wxCOPY
},
852 { wxT("wxEQUIV"), wxEQUIV
},
853 { wxT("wxINVERT"), wxINVERT
},
854 { wxT("wxNAND"), wxNAND
},
855 { wxT("wxNO_OP"), wxNO_OP
},
856 { wxT("wxOR"), wxOR
},
857 { wxT("wxOR_INVERT"), wxOR_INVERT
},
858 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
859 { wxT("wxSET"), wxSET
},
860 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
861 { wxT("wxXOR"), wxXOR
},
864 void MyCanvas::DrawImages(wxDC
& dc
, DrawMode mode
)
866 dc
.DrawText(_T("original image"), 0, 0);
867 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
868 dc
.DrawText(_T("with colour mask"), 0, 100);
869 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, true);
870 dc
.DrawText(_T("the mask image"), 0, 200);
871 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
872 dc
.DrawText(_T("masked image"), 0, 300);
873 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, true);
875 int cx
= gs_bmpWithColMask
->GetWidth(),
876 cy
= gs_bmpWithColMask
->GetHeight();
879 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
881 wxCoord x
= 120 + 150*(n%4
),
884 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
885 memDC
.SelectObject(*gs_bmpWithColMask
);
886 if ( mode
== Draw_Stretch
)
888 dc
.StretchBlit(x
, y
, cx
, cy
, &memDC
, 0, 0, cx
/2, cy
/2,
889 rasterOperations
[n
].rop
, true);
893 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, true);
898 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
900 static const wxCoord w
= 60;
901 static const wxCoord h
= 60;
903 // reuse the text colour here
904 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
905 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
908 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
910 wxCoord x
= 20 + 150*(n%4
),
913 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
914 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
915 dc
.DrawRectangle(x
, y
, w
, h
);
916 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
917 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
920 // now some filled rectangles
921 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
923 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
925 wxCoord x
= 20 + 150*(n%4
),
928 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
929 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
930 dc
.DrawRectangle(x
, y
, w
, h
);
934 #if wxUSE_GRAPHICS_CONTEXT
936 void MyCanvas::DrawAlpha(wxDC
& no_dc
)
938 void MyCanvas::DrawAlpha(wxDC
& dc
)
946 wxDouble margin
= 20 ;
947 wxDouble width
= 180 ;
948 wxDouble radius
= 30 ;
950 dc
.SetPen( wxPen( wxColour( 128, 0, 0, 255 ),12, wxSOLID
));
951 dc
.SetBrush( wxBrush( wxColour( 255, 0, 0, 255),wxSOLID
));
953 wxRect
r(margin
,margin
+width
*0.66,width
,width
) ;
955 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
957 dc
.SetPen( wxPen( wxColour( 0, 0, 128, 255 ),12, wxSOLID
));
958 dc
.SetBrush( wxBrush( wxColour( 0, 0, 255, 255),wxSOLID
));
960 r
.Offset( width
* 0.8 , - width
* 0.66 ) ;
962 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
964 dc
.SetPen( wxPen( wxColour( 128, 128, 0, 255 ),12, wxSOLID
));
965 dc
.SetBrush( wxBrush( wxColour( 192, 192, 0, 255),wxSOLID
));
967 r
.Offset( width
* 0.8 , width
*0.5 ) ;
969 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
971 dc
.SetPen( *wxTRANSPARENT_PEN
) ;
972 dc
.SetBrush( wxBrush( wxColour(255,255,128,128) ) );
973 dc
.DrawRoundedRectangle( 0 , margin
+ width
/ 2 , width
* 3 , 100 , radius
) ;
975 dc
.SetTextForeground( wxColour(255,255,0,128) );
976 dc
.SetFont( wxFont( 40, wxFONTFAMILY_SWISS
, wxFONTSTYLE_ITALIC
, wxFONTWEIGHT_NORMAL
) );
977 dc
.DrawText( wxT("Hello!"), 120, 80 );
982 #if wxUSE_GRAPHICS_CONTEXT
984 const int BASE
= 80.0;
985 const int BASE2
= BASE
/2;
986 const int BASE4
= BASE
/4;
988 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
991 // modeled along Robin Dunn's GraphicsContext.py sample
993 void MyCanvas::DrawGraphics(wxGraphicsContext
* gc
)
995 wxFont font
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
996 gc
->SetFont(font
,*wxBLACK
);
998 // make a path that contains a circle and some lines, centered at 0,0
999 wxGraphicsPath path
= gc
->CreatePath() ;
1000 path
.AddCircle( 0, 0, BASE2
);
1001 path
.MoveToPoint(0, -BASE2
);
1002 path
.AddLineToPoint(0, BASE2
);
1003 path
.MoveToPoint(-BASE2
, 0);
1004 path
.AddLineToPoint(BASE2
, 0);
1005 path
.CloseSubpath();
1006 path
.AddRectangle(-BASE4
, -BASE4
/2, BASE2
, BASE4
);
1008 // Now use that path to demonstrate various capbilites of the grpahics context
1009 gc
->PushState(); // save current translation/scale/other state
1010 gc
->Translate(60, 75); // reposition the context origin
1012 gc
->SetPen(wxPen("navy", 1));
1013 gc
->SetBrush(wxBrush("pink"));
1015 for( int i
= 0 ; i
< 3 ; ++i
)
1021 label
= "StrokePath";
1031 gc
->GetTextExtent(label
, &w
, &h
, NULL
, NULL
);
1032 gc
->DrawText(label
, -w
/2, -BASE2
-h
-4);
1036 gc
->StrokePath(path
);
1045 gc
->Translate(2*BASE
, 0);
1048 gc
->PopState(); // restore saved state
1049 gc
->PushState(); // save it again
1050 gc
->Translate(60, 200); // offset to the lower part of the window
1052 gc
->DrawText("Scale", 0, -BASE2
);
1053 gc
->Translate(0, 20);
1055 gc
->SetBrush(wxBrush(wxColour(178, 34, 34, 128)));// 128 == half transparent
1056 for( int i
= 0 ; i
< 8 ; ++i
)
1058 gc
->Scale(1.08, 1.08); // increase scale by 8%
1063 gc
->PopState(); // restore saved state
1064 gc
->PushState(); // save it again
1065 gc
->Translate(400, 200);
1067 gc
->DrawText("Rotate", 0, -BASE2
);
1069 // Move the origin over to the next location
1070 gc
->Translate(0, 75);
1072 // draw our path again, rotating it about the central point,
1073 // and changing colors as we go
1074 for ( int angle
= 0 ; angle
< 360 ; angle
+= 30 )
1076 gc
->PushState(); // save this new current state so we can
1077 // pop back to it at the end of the loop
1078 wxImage::RGBValue val
= wxImage::HSVtoRGB(wxImage::HSVValue(float(angle
)/360, 1, 1));
1079 gc
->SetBrush(wxBrush(wxColour(val
.red
, val
.green
, val
.blue
, 64)));
1080 gc
->SetPen(wxPen(wxColour(val
.red
, val
.green
, val
.blue
, 128)));
1082 // use translate to artfully reposition each drawn path
1083 gc
->Translate(1.5 * BASE2
* cos(DegToRad(angle
)),
1084 1.5 * BASE2
* sin(DegToRad(angle
)));
1086 // use Rotate to rotate the path
1087 gc
->Rotate(DegToRad(angle
));
1097 void MyCanvas::DrawCircles(wxDC
& dc
)
1103 dc
.SetPen( *wxRED_PEN
);
1104 dc
.SetBrush( *wxGREEN_BRUSH
);
1106 dc
.DrawText(_T("Some circles"), 0, y
);
1107 dc
.DrawCircle(x
, y
, r
);
1108 dc
.DrawCircle(x
+ 2*r
, y
, r
);
1109 dc
.DrawCircle(x
+ 4*r
, y
, r
);
1112 dc
.DrawText(_T("And ellipses"), 0, y
);
1113 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
1114 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
1115 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
1118 dc
.DrawText(_T("And arcs"), 0, y
);
1119 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
1120 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
1121 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
1124 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
1125 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
1126 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
1127 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
1129 // same as above, just transparent brush
1131 dc
.SetPen( *wxRED_PEN
);
1132 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1135 dc
.DrawText(_T("Some circles"), 0, y
);
1136 dc
.DrawCircle(x
, y
, r
);
1137 dc
.DrawCircle(x
+ 2*r
, y
, r
);
1138 dc
.DrawCircle(x
+ 4*r
, y
, r
);
1141 dc
.DrawText(_T("And ellipses"), 0, y
);
1142 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
1143 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
1144 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
1147 dc
.DrawText(_T("And arcs"), 0, y
);
1148 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
1149 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
1150 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
1153 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
1154 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
1155 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
1156 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
1160 void MyCanvas::DrawSplines(wxDC
& dc
)
1163 dc
.DrawText(_T("Some splines"), 10, 5);
1165 // values are hardcoded rather than randomly generated
1166 // so the output can be compared between native
1167 // implementations on platforms with different random
1171 const wxPoint
center( R
+ 20, R
+ 20 );
1172 const int angles
[7] = { 0, 10, 33, 77, 13, 145, 90 };
1173 const int radii
[5] = { 100 , 59, 85, 33, 90 };
1177 // background spline calculation
1178 unsigned int radius_pos
= 0;
1179 unsigned int angle_pos
= 0;
1181 for ( int i
= 0; i
< n
; i
++ )
1183 angle
+= angles
[ angle_pos
];
1184 int r
= R
* radii
[ radius_pos
] / 100;
1185 pts
[ i
].x
= center
.x
+ (wxCoord
)( r
* cos( M_PI
* angle
/ 180.0) );
1186 pts
[ i
].y
= center
.y
+ (wxCoord
)( r
* sin( M_PI
* angle
/ 180.0) );
1189 if ( angle_pos
>= WXSIZEOF(angles
) ) angle_pos
= 0;
1192 if ( radius_pos
>= WXSIZEOF(radii
) ) radius_pos
= 0;
1195 // background spline drawing
1196 dc
.SetPen(*wxRED_PEN
);
1197 dc
.DrawSpline(WXSIZEOF(pts
), pts
);
1199 // less detailed spline calculation
1200 wxPoint letters
[4][5];
1202 letters
[0][0] = wxPoint( 0,1); // O O
1203 letters
[0][1] = wxPoint( 1,3); // * *
1204 letters
[0][2] = wxPoint( 2,2); // * O *
1205 letters
[0][3] = wxPoint( 3,3); // * * * *
1206 letters
[0][4] = wxPoint( 4,1); // O O
1208 letters
[1][0] = wxPoint( 5,1); // O*O
1209 letters
[1][1] = wxPoint( 6,1); // *
1210 letters
[1][2] = wxPoint( 7,2); // O
1211 letters
[1][3] = wxPoint( 8,3); // *
1212 letters
[1][4] = wxPoint( 9,3); // O*O
1214 letters
[2][0] = wxPoint( 5,3); // O*O
1215 letters
[2][1] = wxPoint( 6,3); // *
1216 letters
[2][2] = wxPoint( 7,2); // O
1217 letters
[2][3] = wxPoint( 8,1); // *
1218 letters
[2][4] = wxPoint( 9,1); // O*O
1220 letters
[3][0] = wxPoint(10,0); // O O
1221 letters
[3][1] = wxPoint(11,3); // * *
1222 letters
[3][2] = wxPoint(12,1); // * O *
1223 letters
[3][3] = wxPoint(13,3); // * * * *
1224 letters
[3][4] = wxPoint(14,0); // O O
1226 const int dx
= 2 * R
/ letters
[3][4].x
;
1227 const int h
[4] = { -R
/2, 0, R
/4, R
/2 };
1229 for ( int m
= 0; m
< 4; m
++ )
1231 for ( int n
= 0; n
< 5; n
++ )
1233 letters
[m
][n
].x
= center
.x
- R
+ letters
[m
][n
].x
* dx
;
1234 letters
[m
][n
].y
= center
.y
+ h
[ letters
[m
][n
].y
];
1237 dc
.SetPen( wxPen( wxT("blue"), 1, wxDOT
) );
1238 dc
.DrawLines(5, letters
[m
]);
1239 dc
.SetPen( wxPen( wxT("black"), 4, wxSOLID
) );
1240 dc
.DrawSpline(5, letters
[m
]);
1244 dc
.DrawText(_T("Splines not supported."), 10, 5);
1248 void MyCanvas::DrawGradients(wxDC
& dc
)
1250 static const int TEXT_HEIGHT
= 15;
1253 wxRect
r(10, 10, 50, 50);
1254 dc
.DrawText(_T("wxRIGHT"), r
.x
, r
.y
);
1255 r
.Offset(0, TEXT_HEIGHT
);
1256 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxRIGHT
);
1258 r
.Offset(0, r
.height
+ 10);
1259 dc
.DrawText(_T("wxLEFT"), r
.x
, r
.y
);
1260 r
.Offset(0, TEXT_HEIGHT
);
1261 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxLEFT
);
1263 r
.Offset(0, r
.height
+ 10);
1264 dc
.DrawText(_T("wxDOWN"), r
.x
, r
.y
);
1265 r
.Offset(0, TEXT_HEIGHT
);
1266 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxDOWN
);
1268 r
.Offset(0, r
.height
+ 10);
1269 dc
.DrawText(_T("wxUP"), r
.x
, r
.y
);
1270 r
.Offset(0, TEXT_HEIGHT
);
1271 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxUP
);
1275 r
= wxRect(200, 10, 50, 50);
1276 dc
.DrawText(_T("Blue inside"), r
.x
, r
.y
);
1277 r
.Offset(0, TEXT_HEIGHT
);
1278 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
);
1280 r
.Offset(0, r
.height
+ 10);
1281 dc
.DrawText(_T("White inside"), r
.x
, r
.y
);
1282 r
.Offset(0, TEXT_HEIGHT
);
1283 dc
.GradientFillConcentric(r
, *wxWHITE
, *wxBLUE
);
1285 r
.Offset(0, r
.height
+ 10);
1286 dc
.DrawText(_T("Blue in top left corner"), r
.x
, r
.y
);
1287 r
.Offset(0, TEXT_HEIGHT
);
1288 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
, wxPoint(0, 0));
1290 r
.Offset(0, r
.height
+ 10);
1291 dc
.DrawText(_T("Blue in bottom right corner"), r
.x
, r
.y
);
1292 r
.Offset(0, TEXT_HEIGHT
);
1293 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
, wxPoint(r
.width
, r
.height
));
1295 // check that the area filled by the gradient is exactly the interior of
1299 dc
.DrawText("The interior should be filled but", r
.x
, r
.y
);
1301 dc
.DrawText(" the red border should remain visible:", r
.x
, r
.y
);
1312 dc
.SetPen(wxPen(wxColour(255, 0, 0)));
1313 dc
.DrawRectangle(r
);
1315 dc
.GradientFillLinear(r
, wxColour(0,255,0), wxColour(0,0,0), wxNORTH
);
1316 dc
.DrawRectangle(r2
);
1318 dc
.GradientFillLinear(r2
, wxColour(0,0,0), wxColour(0,255,0), wxSOUTH
);
1319 dc
.DrawRectangle(r3
);
1321 dc
.GradientFillLinear(r3
, wxColour(0,255,0), wxColour(0,0,0), wxEAST
);
1322 dc
.DrawRectangle(r4
);
1324 dc
.GradientFillLinear(r4
, wxColour(0,0,0), wxColour(0,255,0), wxWEST
);
1327 void MyCanvas::DrawRegions(wxDC
& dc
)
1329 dc
.DrawText(_T("You should see a red rect partly covered by a cyan one ")
1330 _T("on the left"), 10, 5);
1331 dc
.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
1332 10, 5 + dc
.GetCharHeight());
1333 dc
.DrawText(_T("The second copy should be identical but right part of it ")
1334 _T("should be offset by 10 pixels."),
1335 10, 5 + 2*dc
.GetCharHeight());
1337 DrawRegionsHelper(dc
, 10, true);
1338 DrawRegionsHelper(dc
, 350, false);
1341 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
1345 dc
.DestroyClippingRegion();
1346 dc
.SetBrush( *wxWHITE_BRUSH
);
1347 dc
.SetPen( *wxTRANSPARENT_PEN
);
1348 dc
.DrawRectangle( x
, y
, 310, 310 );
1350 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
1352 dc
.SetBrush( *wxRED_BRUSH
);
1353 dc
.DrawRectangle( x
, y
, 310, 310 );
1355 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
1357 dc
.SetBrush( *wxCYAN_BRUSH
);
1358 dc
.DrawRectangle( x
, y
, 310, 310 );
1360 dc
.DestroyClippingRegion();
1362 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
1363 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
1365 region
.Offset(10, 10);
1367 dc
.SetClippingRegion(region
);
1369 dc
.SetBrush( *wxGREY_BRUSH
);
1370 dc
.DrawRectangle( x
, y
, 310, 310 );
1372 if (m_smile_bmp
.Ok())
1374 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, true );
1375 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, true );
1376 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, true );
1377 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, true );
1378 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, true );
1382 #if TEST_CAIRO_EVERYWHERE
1383 extern wxGraphicsRenderer
* gCairoRenderer
;
1386 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
1388 wxPaintDC
pdc(this);
1390 #if wxUSE_GRAPHICS_CONTEXT
1391 #if TEST_CAIRO_EVERYWHERE
1393 gdc
.SetGraphicsContext( gCairoRenderer
->CreateContext( pdc
) );
1397 wxDC
&dc
= m_useContext
? (wxDC
&) gdc
: (wxDC
&) pdc
;
1404 m_owner
->PrepareDC(dc
);
1406 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
1407 if ( m_owner
->m_backgroundBrush
.Ok() )
1408 dc
.SetBackground( m_owner
->m_backgroundBrush
);
1409 if ( m_owner
->m_colourForeground
.Ok() )
1410 dc
.SetTextForeground( m_owner
->m_colourForeground
);
1411 if ( m_owner
->m_colourBackground
.Ok() )
1412 dc
.SetTextBackground( m_owner
->m_colourBackground
);
1414 if ( m_owner
->m_textureBackground
) {
1415 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
1416 wxColour
clr(0,128,0);
1417 wxBrush
b(clr
, wxSOLID
);
1418 dc
.SetBackground(b
);
1423 dc
.SetClippingRegion(100, 100, 100, 100);
1427 if ( m_owner
->m_textureBackground
)
1429 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
1430 for ( int i
= 0; i
< 200; i
++ )
1431 dc
.DrawLine(0, i
*10, i
*10, 0);
1457 DrawTestLines( 0, 100, 0, dc
);
1458 DrawTestLines( 0, 320, 1, dc
);
1459 DrawTestLines( 0, 540, 2, dc
);
1460 DrawTestLines( 0, 760, 6, dc
);
1464 DrawTestBrushes(dc
);
1472 DrawImages(dc
, Draw_Normal
);
1475 case Show_Mask_Stretch
:
1476 DrawImages(dc
, Draw_Stretch
);
1480 DrawWithLogicalOps(dc
);
1483 #if wxUSE_GRAPHICS_CONTEXT
1488 DrawGraphics(gdc
.GetGraphicsContext());
1501 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
1505 wxClientDC
dc(this);
1507 m_owner
->PrepareDC(dc
);
1509 wxPoint pos
= event
.GetPosition();
1510 long x
= dc
.DeviceToLogicalX( pos
.x
);
1511 long y
= dc
.DeviceToLogicalY( pos
.y
);
1513 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
1514 m_owner
->SetStatusText( str
);
1520 event
.GetPosition(&x
,&y
);
1521 CalcUnscrolledPosition( x
, y
, &xx
, &yy
);
1522 m_currentpoint
= wxPoint( xx
, yy
) ;
1523 wxRect
newrect ( m_anchorpoint
, m_currentpoint
) ;
1525 wxClientDC
dc( this ) ;
1528 wxDCOverlay
overlaydc( m_overlay
, &dc
);
1531 dc
.SetPen( *wxGREY_PEN
);
1532 dc
.SetBrush( wxColour( 192,192,192,64 ) );
1534 dc
.SetPen( wxPen( *wxLIGHT_GREY
, 2, wxSOLID
) );
1535 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1537 dc
.DrawRectangle( newrect
);
1541 #endif // wxUSE_STATUSBAR
1544 void MyCanvas::OnMouseDown(wxMouseEvent
&event
)
1547 event
.GetPosition(&x
,&y
);
1548 CalcUnscrolledPosition( x
, y
, &xx
, &yy
);
1549 m_anchorpoint
= wxPoint( xx
, yy
) ;
1550 m_currentpoint
= m_anchorpoint
;
1551 m_rubberBand
= true ;
1555 void MyCanvas::OnMouseUp(wxMouseEvent
&event
)
1561 wxClientDC
dc( this );
1563 wxDCOverlay
overlaydc( m_overlay
, &dc
);
1567 m_rubberBand
= false;
1570 event
.GetPosition(&x
,&y
);
1571 CalcUnscrolledPosition( x
, y
, &xx
, &yy
);
1574 str
.Printf( wxT("Rectangle selection from %d,%d to %d,%d"),
1575 m_anchorpoint
.x
, m_anchorpoint
.y
, (int)xx
, (int)yy
);
1576 wxMessageBox( str
, wxT("Rubber-Banding") );
1581 // ----------------------------------------------------------------------------
1583 // ----------------------------------------------------------------------------
1585 // the event tables connect the wxWidgets events with the functions (event
1586 // handlers) which process them. It can be also done at run-time, but for the
1587 // simple menu events like this the static method is much simpler.
1588 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1589 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1590 EVT_MENU (File_About
, MyFrame::OnAbout
)
1591 EVT_MENU (File_Clip
, MyFrame::OnClip
)
1592 #if wxUSE_GRAPHICS_CONTEXT
1593 EVT_MENU (File_GraphicContext
, MyFrame::OnGraphicContext
)
1596 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1598 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1601 // frame constructor
1602 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1603 : wxFrame((wxFrame
*)NULL
, wxID_ANY
, title
, pos
, size
,
1604 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1606 // set the frame icon
1607 SetIcon(wxICON(mondrian
));
1609 wxMenu
*menuFile
= new wxMenu
;
1610 menuFile
->Append(File_ShowDefault
, _T("&Default screen\tF1"));
1611 menuFile
->Append(File_ShowText
, _T("&Text screen\tF2"));
1612 menuFile
->Append(File_ShowLines
, _T("&Lines screen\tF3"));
1613 menuFile
->Append(File_ShowBrushes
, _T("&Brushes screen\tF4"));
1614 menuFile
->Append(File_ShowPolygons
, _T("&Polygons screen\tF5"));
1615 menuFile
->Append(File_ShowMask
, _T("&Mask screen\tF6"));
1616 menuFile
->Append(File_ShowMaskStretch
, _T("1/&2 scaled mask\tShift-F6"));
1617 menuFile
->Append(File_ShowOps
, _T("&ROP screen\tF7"));
1618 menuFile
->Append(File_ShowRegions
, _T("Re&gions screen\tF8"));
1619 menuFile
->Append(File_ShowCircles
, _T("&Circles screen\tF9"));
1620 #if wxUSE_GRAPHICS_CONTEXT
1621 menuFile
->Append(File_ShowAlpha
, _T("&Alpha screen\tF10"));
1623 menuFile
->Append(File_ShowSplines
, _T("&Splines screen\tF11"));
1624 menuFile
->Append(File_ShowGradients
, _T("&Gradients screen\tF12"));
1625 #if wxUSE_GRAPHICS_CONTEXT
1626 menuFile
->Append(File_ShowGraphics
, _T("&Graphics screen\tF13"));
1628 menuFile
->AppendSeparator();
1629 menuFile
->AppendCheckItem(File_Clip
, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
1630 #if wxUSE_GRAPHICS_CONTEXT
1631 menuFile
->AppendCheckItem(File_GraphicContext
, _T("&Use GraphicContext\tCtrl-Y"), _T("Use GraphicContext"));
1633 menuFile
->AppendSeparator();
1634 menuFile
->Append(File_About
, _T("&About...\tCtrl-A"), _T("Show about dialog"));
1635 menuFile
->AppendSeparator();
1636 menuFile
->Append(File_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
1638 wxMenu
*menuMapMode
= new wxMenu
;
1639 menuMapMode
->Append( MapMode_Text
, _T("&TEXT map mode") );
1640 menuMapMode
->Append( MapMode_Lometric
, _T("&LOMETRIC map mode") );
1641 menuMapMode
->Append( MapMode_Twips
, _T("T&WIPS map mode") );
1642 menuMapMode
->Append( MapMode_Points
, _T("&POINTS map mode") );
1643 menuMapMode
->Append( MapMode_Metric
, _T("&METRIC map mode") );
1645 wxMenu
*menuUserScale
= new wxMenu
;
1646 menuUserScale
->Append( UserScale_StretchHoriz
, _T("Stretch &horizontally\tCtrl-H") );
1647 menuUserScale
->Append( UserScale_ShrinkHoriz
, _T("Shrin&k horizontally\tCtrl-G") );
1648 menuUserScale
->Append( UserScale_StretchVertic
, _T("Stretch &vertically\tCtrl-V") );
1649 menuUserScale
->Append( UserScale_ShrinkVertic
, _T("&Shrink vertically\tCtrl-W") );
1650 menuUserScale
->AppendSeparator();
1651 menuUserScale
->Append( UserScale_Restore
, _T("&Restore to normal\tCtrl-0") );
1653 wxMenu
*menuAxis
= new wxMenu
;
1654 menuAxis
->AppendCheckItem( AxisMirror_Horiz
, _T("Mirror horizontally\tCtrl-M") );
1655 menuAxis
->AppendCheckItem( AxisMirror_Vertic
, _T("Mirror vertically\tCtrl-N") );
1657 wxMenu
*menuLogical
= new wxMenu
;
1658 menuLogical
->Append( LogicalOrigin_MoveDown
, _T("Move &down\tCtrl-D") );
1659 menuLogical
->Append( LogicalOrigin_MoveUp
, _T("Move &up\tCtrl-U") );
1660 menuLogical
->Append( LogicalOrigin_MoveLeft
, _T("Move &right\tCtrl-L") );
1661 menuLogical
->Append( LogicalOrigin_MoveRight
, _T("Move &left\tCtrl-R") );
1662 menuLogical
->AppendSeparator();
1663 menuLogical
->Append( LogicalOrigin_Set
, _T("Set to (&100, 100)\tShift-Ctrl-1") );
1664 menuLogical
->Append( LogicalOrigin_Restore
, _T("&Restore to normal\tShift-Ctrl-0") );
1666 wxMenu
*menuColour
= new wxMenu
;
1668 menuColour
->Append( Colour_TextForeground
, _T("Text &foreground...") );
1669 menuColour
->Append( Colour_TextBackground
, _T("Text &background...") );
1670 menuColour
->Append( Colour_Background
, _T("Background &colour...") );
1671 #endif // wxUSE_COLOURDLG
1672 menuColour
->AppendCheckItem( Colour_BackgroundMode
, _T("&Opaque/transparent\tCtrl-B") );
1673 menuColour
->AppendCheckItem( Colour_TextureBackgound
, _T("Draw textured back&ground\tCtrl-T") );
1675 // now append the freshly created menu to the menu bar...
1676 wxMenuBar
*menuBar
= new wxMenuBar
;
1677 menuBar
->Append(menuFile
, _T("&File"));
1678 menuBar
->Append(menuMapMode
, _T("&Mode"));
1679 menuBar
->Append(menuUserScale
, _T("&Scale"));
1680 menuBar
->Append(menuAxis
, _T("&Axis"));
1681 menuBar
->Append(menuLogical
, _T("&Origin"));
1682 menuBar
->Append(menuColour
, _T("&Colours"));
1684 // ... and attach this menu bar to the frame
1685 SetMenuBar(menuBar
);
1689 SetStatusText(_T("Welcome to wxWidgets!"));
1690 #endif // wxUSE_STATUSBAR
1692 m_mapMode
= wxMM_TEXT
;
1695 m_xLogicalOrigin
= 0;
1696 m_yLogicalOrigin
= 0;
1698 m_yAxisReversed
= false;
1699 m_backgroundMode
= wxSOLID
;
1700 m_colourForeground
= *wxRED
;
1701 m_colourBackground
= *wxBLUE
;
1702 m_textureBackground
= false;
1704 m_canvas
= new MyCanvas( this );
1705 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1710 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1712 // true is to force the frame to close
1716 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1719 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1720 wxT("This sample tests various primitive drawing functions\n")
1721 wxT("(without any attempts to prevent flicker).\n")
1722 wxT("Copyright (c) Robert Roebling 1999")
1725 wxMessageBox(msg
, _T("About Drawing"), wxOK
| wxICON_INFORMATION
, this);
1728 void MyFrame::OnClip(wxCommandEvent
& event
)
1730 m_canvas
->Clip(event
.IsChecked());
1733 #if wxUSE_GRAPHICS_CONTEXT
1734 void MyFrame::OnGraphicContext(wxCommandEvent
& event
)
1736 m_canvas
->UseGraphicContext(event
.IsChecked());
1740 void MyFrame::OnShow(wxCommandEvent
& event
)
1742 m_canvas
->ToShow((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1745 void MyFrame::OnOption(wxCommandEvent
& event
)
1747 switch (event
.GetId())
1750 m_mapMode
= wxMM_TEXT
;
1752 case MapMode_Lometric
:
1753 m_mapMode
= wxMM_LOMETRIC
;
1756 m_mapMode
= wxMM_TWIPS
;
1758 case MapMode_Points
:
1759 m_mapMode
= wxMM_POINTS
;
1761 case MapMode_Metric
:
1762 m_mapMode
= wxMM_METRIC
;
1765 case LogicalOrigin_MoveDown
:
1766 m_yLogicalOrigin
+= 10;
1768 case LogicalOrigin_MoveUp
:
1769 m_yLogicalOrigin
-= 10;
1771 case LogicalOrigin_MoveLeft
:
1772 m_xLogicalOrigin
+= 10;
1774 case LogicalOrigin_MoveRight
:
1775 m_xLogicalOrigin
-= 10;
1777 case LogicalOrigin_Set
:
1779 m_yLogicalOrigin
= -100;
1781 case LogicalOrigin_Restore
:
1783 m_yLogicalOrigin
= 0;
1786 case UserScale_StretchHoriz
:
1787 m_xUserScale
*= 1.10;
1789 case UserScale_ShrinkHoriz
:
1790 m_xUserScale
/= 1.10;
1792 case UserScale_StretchVertic
:
1793 m_yUserScale
*= 1.10;
1795 case UserScale_ShrinkVertic
:
1796 m_yUserScale
/= 1.10;
1798 case UserScale_Restore
:
1803 case AxisMirror_Vertic
:
1804 m_yAxisReversed
= !m_yAxisReversed
;
1806 case AxisMirror_Horiz
:
1807 m_xAxisReversed
= !m_xAxisReversed
;
1811 case Colour_TextForeground
:
1812 m_colourForeground
= SelectColour();
1814 case Colour_TextBackground
:
1815 m_colourBackground
= SelectColour();
1817 case Colour_Background
:
1819 wxColour col
= SelectColour();
1822 m_backgroundBrush
.SetColour(col
);
1826 #endif // wxUSE_COLOURDLG
1828 case Colour_BackgroundMode
:
1829 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1833 case Colour_TextureBackgound
:
1834 m_textureBackground
= ! m_textureBackground
;
1842 m_canvas
->Refresh();
1845 void MyFrame::PrepareDC(wxDC
& dc
)
1847 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1848 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1849 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1850 dc
.SetMapMode( m_mapMode
);
1854 wxColour
MyFrame::SelectColour()
1858 wxColourDialog
dialog(this, &data
);
1860 if ( dialog
.ShowModal() == wxID_OK
)
1862 col
= dialog
.GetColourData().GetColour();
1867 #endif // wxUSE_COLOURDLG