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"
39 #include "wx/filename.h"
41 #define TEST_CAIRO_EVERYWHERE 0
43 // ----------------------------------------------------------------------------
45 // ----------------------------------------------------------------------------
47 // the application icon
48 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
49 #include "mondrian.xpm"
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 // what do we show on screen (there are too many shapes to put them all on
57 // screen simultaneously)
71 #if wxUSE_GRAPHICS_CONTEXT
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 static wxBitmap
*gs_bmpNoMask
= NULL
,
84 *gs_bmpWithColMask
= NULL
,
86 *gs_bmpWithMask
= NULL
,
91 // ----------------------------------------------------------------------------
93 // ----------------------------------------------------------------------------
95 // Define a new application type, each program should derive a class from wxApp
96 class MyApp
: public wxApp
99 // override base class virtuals
100 // ----------------------------
102 // this one is called on application startup and is a good place for the app
103 // initialization (doing it here and not in the ctor allows to have an error
104 // return: if OnInit() returns false, the application terminates)
105 virtual bool OnInit();
107 virtual int OnExit() { DeleteBitmaps(); return 0; }
110 void DeleteBitmaps();
117 // Define a new frame type: this is going to be our main frame
118 class MyFrame
: public wxFrame
122 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
124 // event handlers (these functions should _not_ be virtual)
125 void OnQuit(wxCommandEvent
& event
);
126 void OnAbout(wxCommandEvent
& event
);
127 void OnClip(wxCommandEvent
& event
);
128 #if wxUSE_GRAPHICS_CONTEXT
129 void OnGraphicContext(wxCommandEvent
& event
);
131 void OnShow(wxCommandEvent
&event
);
132 void OnOption(wxCommandEvent
&event
);
135 wxColour
SelectColour();
136 #endif // wxUSE_COLOURDLG
137 void PrepareDC(wxDC
& dc
);
139 int m_backgroundMode
;
140 int m_textureBackground
;
144 int m_xLogicalOrigin
;
145 int m_yLogicalOrigin
;
146 bool m_xAxisReversed
,
148 wxColour m_colourForeground
, // these are _text_ colours
150 wxBrush m_backgroundBrush
;
154 // any class wishing to process wxWidgets events must use this macro
155 DECLARE_EVENT_TABLE()
158 // define a scrollable canvas for drawing onto
159 class MyCanvas
: public wxScrolledWindow
162 MyCanvas( MyFrame
*parent
);
164 void OnPaint(wxPaintEvent
&event
);
165 void OnMouseMove(wxMouseEvent
&event
);
166 void OnMouseDown(wxMouseEvent
&event
);
167 void OnMouseUp(wxMouseEvent
&event
);
169 void ToShow(ScreenToShow show
) { m_show
= show
; Refresh(); }
171 // set or remove the clipping region
172 void Clip(bool clip
) { m_clip
= clip
; Refresh(); }
173 #if wxUSE_GRAPHICS_CONTEXT
174 void UseGraphicContext(bool use
) { m_useContext
= use
; Refresh(); }
184 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
185 void DrawTestPoly(wxDC
& dc
);
186 void DrawTestBrushes(wxDC
& dc
);
187 void DrawText(wxDC
& dc
);
188 void DrawImages(wxDC
& dc
, DrawMode mode
);
189 void DrawWithLogicalOps(wxDC
& dc
);
190 #if wxUSE_GRAPHICS_CONTEXT
191 void DrawAlpha(wxDC
& dc
);
192 void DrawGraphics(wxGraphicsContext
* gc
);
194 void DrawRegions(wxDC
& dc
);
195 void DrawCircles(wxDC
& dc
);
196 void DrawSplines(wxDC
& dc
);
197 void DrawDefault(wxDC
& dc
);
198 void DrawGradients(wxDC
& dc
);
200 void DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
);
206 wxBitmap m_smile_bmp
;
211 wxPoint m_anchorpoint
;
212 wxPoint m_currentpoint
;
213 #if wxUSE_GRAPHICS_CONTEXT
217 DECLARE_EVENT_TABLE()
220 // ----------------------------------------------------------------------------
222 // ----------------------------------------------------------------------------
224 // IDs for the controls and the menu commands
228 File_Quit
= wxID_EXIT
,
229 File_About
= wxID_ABOUT
,
231 MenuShow_First
= wxID_HIGHEST
,
232 File_ShowDefault
= MenuShow_First
,
238 File_ShowMaskStretch
,
243 #if wxUSE_GRAPHICS_CONTEXT
248 MenuShow_Last
= File_ShowGradients
,
251 #if wxUSE_GRAPHICS_CONTEXT
257 MapMode_Text
= MenuOption_First
,
263 UserScale_StretchHoriz
,
264 UserScale_ShrinkHoriz
,
265 UserScale_StretchVertic
,
266 UserScale_ShrinkVertic
,
272 LogicalOrigin_MoveDown
,
273 LogicalOrigin_MoveUp
,
274 LogicalOrigin_MoveLeft
,
275 LogicalOrigin_MoveRight
,
277 LogicalOrigin_Restore
,
280 Colour_TextForeground
,
281 Colour_TextBackground
,
283 #endif // wxUSE_COLOURDLG
284 Colour_BackgroundMode
,
285 Colour_TextureBackgound
,
287 MenuOption_Last
= Colour_TextureBackgound
290 // ----------------------------------------------------------------------------
291 // event tables and other macros for wxWidgets
292 // ----------------------------------------------------------------------------
295 // Create a new application object: this macro will allow wxWidgets to create
296 // the application object during program execution (it's better than using a
297 // static object for many reasons) and also declares the accessor function
298 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
302 // ============================================================================
304 // ============================================================================
306 // ----------------------------------------------------------------------------
307 // the application class
308 // ----------------------------------------------------------------------------
310 bool MyApp::LoadImages()
312 gs_bmpNoMask
= new wxBitmap
;
313 gs_bmpWithColMask
= new wxBitmap
;
314 gs_bmpMask
= new wxBitmap
;
315 gs_bmpWithMask
= new wxBitmap
;
316 gs_bmp4
= new wxBitmap
;
317 gs_bmp4_mono
= new wxBitmap
;
318 gs_bmp36
= new wxBitmap
;
321 // special hack for Unix in-tree sample build, don't do this in real
322 // programs, use wxStandardPaths instead
323 pathList
.Add(wxFileName(argv
[0]).GetPath());
324 pathList
.Add(_T("."));
325 pathList
.Add(_T(".."));
326 pathList
.Add(_T("../.."));
328 wxString path
= pathList
.FindValidPath(_T("pat4.bmp"));
332 /* 4 colour bitmap */
333 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
334 /* turn into mono-bitmap */
335 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
336 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
337 gs_bmp4_mono
->SetMask(mask4
);
339 path
= pathList
.FindValidPath(_T("pat36.bmp"));
342 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
343 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
344 gs_bmp36
->SetMask(mask36
);
346 path
= pathList
.FindValidPath(_T("image.bmp"));
349 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
350 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
351 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
353 path
= pathList
.FindValidPath(_T("mask.bmp"));
356 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
358 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
359 gs_bmpWithMask
->SetMask(mask
);
361 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
362 gs_bmpWithColMask
->SetMask(mask
);
367 // `Main program' equivalent: the program execution "starts" here
370 if ( !wxApp::OnInit() )
373 // Create the main application window
374 MyFrame
*frame
= new MyFrame(_T("Drawing sample"),
375 wxPoint(50, 50), wxSize(550, 340));
377 // Show it and tell the application that it's our main window
383 wxLogError(wxT("Can't load one of the bitmap files needed ")
384 wxT("for this sample from the current or parent ")
385 wxT("directory, please copy them there."));
387 // still continue, the sample can be used without images too if they're
388 // missing for whatever reason
395 void MyApp::DeleteBitmaps()
398 delete gs_bmpWithColMask
;
400 delete gs_bmpWithMask
;
406 gs_bmpWithColMask
= NULL
;
408 gs_bmpWithMask
= NULL
;
414 // ----------------------------------------------------------------------------
416 // ----------------------------------------------------------------------------
418 // the event tables connect the wxWidgets events with the functions (event
419 // handlers) which process them.
420 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
421 EVT_PAINT (MyCanvas::OnPaint
)
422 EVT_MOTION (MyCanvas::OnMouseMove
)
423 EVT_LEFT_DOWN (MyCanvas::OnMouseDown
)
424 EVT_LEFT_UP (MyCanvas::OnMouseUp
)
429 MyCanvas::MyCanvas(MyFrame
*parent
)
430 : wxScrolledWindow(parent
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
,
431 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
434 m_show
= Show_Default
;
435 m_smile_bmp
= wxBitmap(smile_xpm
);
436 m_std_icon
= wxArtProvider::GetIcon(wxART_INFORMATION
);
438 m_rubberBand
= false;
439 #if wxUSE_GRAPHICS_CONTEXT
440 m_useContext
= false;
444 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
446 static const wxCoord WIDTH
= 200;
447 static const wxCoord HEIGHT
= 80;
452 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
453 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
454 dc
.DrawText(_T("Solid green"), x
+ 10, y
+ 10);
457 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
458 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
459 dc
.DrawText(_T("Hatched red"), x
+ 10, y
+ 10);
462 dc
.SetBrush(wxBrush(*gs_bmpMask
));
463 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
464 dc
.DrawText(_T("Stipple mono"), x
+ 10, y
+ 10);
467 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
468 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
469 dc
.DrawText(_T("Stipple colour"), x
+ 10, y
+ 10);
472 void MyCanvas::DrawTestPoly(wxDC
& dc
)
474 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
475 dc
.SetBrush(brushHatch
);
478 star
[0] = wxPoint(100, 60);
479 star
[1] = wxPoint(60, 150);
480 star
[2] = wxPoint(160, 100);
481 star
[3] = wxPoint(40, 100);
482 star
[4] = wxPoint(140, 150);
484 dc
.DrawText(_T("You should see two (irregular) stars below, the left one ")
485 _T("hatched"), 10, 10);
486 dc
.DrawText(_T("except for the central region and the right ")
487 _T("one entirely hatched"), 10, 30);
488 dc
.DrawText(_T("The third star only has a hatched outline"), 10, 50);
490 dc
.DrawPolygon(WXSIZEOF(star
), star
, 0, 30);
491 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 30, wxWINDING_RULE
);
494 star2
[0] = wxPoint(0, 100);
495 star2
[1] = wxPoint(-59, -81);
496 star2
[2] = wxPoint(95, 31);
497 star2
[3] = wxPoint(-95, 31);
498 star2
[4] = wxPoint(59, -81);
499 star2
[5] = wxPoint(0, 80);
500 star2
[6] = wxPoint(-47, -64);
501 star2
[7] = wxPoint(76, 24);
502 star2
[8] = wxPoint(-76, 24);
503 star2
[9] = wxPoint(47, -64);
504 int count
[2] = {5, 5};
506 dc
.DrawPolyPolygon(WXSIZEOF(count
), count
, star2
, 450, 150);
509 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
511 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
512 dc
.SetBrush( *wxRED_BRUSH
);
513 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
514 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
516 dc
.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x
+ 150, y
+ 10);
517 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
518 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
519 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
520 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
521 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
522 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
523 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
524 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
525 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
526 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
528 dc
.DrawText(_T("Misc hatches"), x
+ 150, y
+ 70);
529 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
530 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
531 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
532 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
533 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
534 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
535 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
536 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
537 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
538 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
539 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
540 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
542 dc
.DrawText(_T("User dash"), x
+ 150, y
+ 140);
543 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
545 dash1
[0] = 8; // Long dash <---------+
546 dash1
[1] = 2; // Short gap |
547 dash1
[2] = 3; // Short dash |
548 dash1
[3] = 2; // Short gap |
549 dash1
[4] = 3; // Short dash |
550 dash1
[5] = 2; // Short gap and repeat +
551 ud
.SetDashes( 6, dash1
);
553 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
554 dash1
[0] = 5; // Make first dash shorter
555 ud
.SetDashes( 6, dash1
);
557 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
558 dash1
[2] = 5; // Make second dash longer
559 ud
.SetDashes( 6, dash1
);
561 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
562 dash1
[4] = 5; // Make third dash longer
563 ud
.SetDashes( 6, dash1
);
565 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
568 void MyCanvas::DrawDefault(wxDC
& dc
)
571 dc
.DrawCircle(0, 0, 10);
573 #if !defined(wxMAC_USE_CORE_GRAPHICS) || !wxMAC_USE_CORE_GRAPHICS
574 // GetPixel and FloodFill not supported by Mac OS X CoreGraphics
575 // (FloodFill uses Blit from a non-wxMemoryDC)
576 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
577 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
580 dc
.GetPixel(1,1, &tmpColour
);
581 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
584 dc
.DrawCheckMark(5, 80, 15, 15);
585 dc
.DrawCheckMark(25, 80, 30, 30);
586 dc
.DrawCheckMark(60, 80, 60, 60);
588 // this is the test for "blitting bitmap into DC damages selected brush" bug
589 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
591 dc
.SetPen(*wxTRANSPARENT_PEN
);
592 dc
.SetBrush( *wxGREEN_BRUSH
);
593 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
594 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, true);
596 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
597 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
599 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
601 // test for "transparent" bitmap drawing (it intersects with the last
603 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
605 if (m_smile_bmp
.Ok())
606 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, true);
608 dc
.SetBrush( *wxBLACK_BRUSH
);
609 dc
.DrawRectangle( 0, 160, 1000, 300 );
612 wxBitmap
bitmap(20,70);
614 memdc
.SelectObject( bitmap
);
615 memdc
.SetBrush( *wxBLACK_BRUSH
);
616 memdc
.SetPen( *wxWHITE_PEN
);
617 memdc
.DrawRectangle(0,0,20,70);
618 memdc
.DrawLine( 10,0,10,70 );
621 wxPen pen
= *wxRED_PEN
;
623 memdc
.DrawLine( 10, 5,10, 5 );
624 memdc
.DrawLine( 10,10,11,10 );
625 memdc
.DrawLine( 10,15,12,15 );
626 memdc
.DrawLine( 10,20,13,20 );
629 memdc.SetPen(*wxRED_PEN);
630 memdc.DrawLine( 12, 5,12, 5 );
631 memdc.DrawLine( 12,10,13,10 );
632 memdc.DrawLine( 12,15,14,15 );
633 memdc.DrawLine( 12,20,15,20 );
637 memdc
.DrawLine( 10,25,10,25 );
638 memdc
.DrawLine( 10,30, 9,30 );
639 memdc
.DrawLine( 10,35, 8,35 );
640 memdc
.DrawLine( 10,40, 7,40 );
643 dc
.SetPen(*wxWHITE_PEN
);
644 memdc
.SetLogicalFunction( wxINVERT
);
645 memdc
.SetPen( *wxWHITE_PEN
);
646 memdc
.DrawLine( 10,50,10,50 );
647 memdc
.DrawLine( 10,55,11,55 );
648 memdc
.DrawLine( 10,60,12,60 );
649 memdc
.DrawLine( 10,65,13,65 );
651 memdc
.DrawLine( 12,50,12,50 );
652 memdc
.DrawLine( 12,55,13,55 );
653 memdc
.DrawLine( 12,60,14,60 );
654 memdc
.DrawLine( 12,65,15,65 );
656 memdc
.SelectObject( wxNullBitmap
);
657 dc
.DrawBitmap( bitmap
, 10, 170 );
658 wxImage image
= bitmap
.ConvertToImage();
659 image
.Rescale( 60,210 );
660 bitmap
= wxBitmap(image
);
661 dc
.DrawBitmap( bitmap
, 50, 170 );
663 // test the rectangle outline drawing - there should be one pixel between
664 // the rect and the lines
665 dc
.SetPen(*wxWHITE_PEN
);
666 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
667 dc
.DrawRectangle(150, 170, 49, 29);
668 dc
.DrawRectangle(200, 170, 49, 29);
669 dc
.SetPen(*wxWHITE_PEN
);
670 dc
.DrawLine(250, 210, 250, 170);
671 dc
.DrawLine(260, 200, 150, 200);
673 // test the rectangle filled drawing - there should be one pixel between
674 // the rect and the lines
675 dc
.SetPen(*wxTRANSPARENT_PEN
);
676 dc
.SetBrush( *wxWHITE_BRUSH
);
677 dc
.DrawRectangle(300, 170, 49, 29);
678 dc
.DrawRectangle(350, 170, 49, 29);
679 dc
.SetPen(*wxWHITE_PEN
);
680 dc
.DrawLine(400, 170, 400, 210);
681 dc
.DrawLine(300, 200, 410, 200);
683 // a few more tests of this kind
684 dc
.SetPen(*wxRED_PEN
);
685 dc
.SetBrush( *wxWHITE_BRUSH
);
686 dc
.DrawRectangle(300, 220, 1, 1);
687 dc
.DrawRectangle(310, 220, 2, 2);
688 dc
.DrawRectangle(320, 220, 3, 3);
689 dc
.DrawRectangle(330, 220, 4, 4);
691 dc
.SetPen(*wxTRANSPARENT_PEN
);
692 dc
.SetBrush( *wxWHITE_BRUSH
);
693 dc
.DrawRectangle(300, 230, 1, 1);
694 dc
.DrawRectangle(310, 230, 2, 2);
695 dc
.DrawRectangle(320, 230, 3, 3);
696 dc
.DrawRectangle(330, 230, 4, 4);
698 // and now for filled rect with outline
699 dc
.SetPen(*wxRED_PEN
);
700 dc
.SetBrush( *wxWHITE_BRUSH
);
701 dc
.DrawRectangle(500, 170, 49, 29);
702 dc
.DrawRectangle(550, 170, 49, 29);
703 dc
.SetPen(*wxWHITE_PEN
);
704 dc
.DrawLine(600, 170, 600, 210);
705 dc
.DrawLine(500, 200, 610, 200);
707 // test the rectangle outline drawing - there should be one pixel between
708 // the rect and the lines
709 dc
.SetPen(*wxWHITE_PEN
);
710 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
711 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
712 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
713 dc
.SetPen(*wxWHITE_PEN
);
714 dc
.DrawLine(250, 270, 250, 310);
715 dc
.DrawLine(150, 300, 260, 300);
717 // test the rectangle filled drawing - there should be one pixel between
718 // the rect and the lines
719 dc
.SetPen(*wxTRANSPARENT_PEN
);
720 dc
.SetBrush( *wxWHITE_BRUSH
);
721 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
722 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
723 dc
.SetPen(*wxWHITE_PEN
);
724 dc
.DrawLine(400, 270, 400, 310);
725 dc
.DrawLine(300, 300, 410, 300);
727 // Added by JACS to demonstrate bizarre behaviour.
728 // With a size of 70, we get a missing red RHS,
729 // and the height is too small, so we get yellow
730 // showing. With a size of 40, it draws as expected:
731 // it just shows a white rectangle with red outline.
733 int totalHeight
= 70;
734 wxBitmap
bitmap2(totalWidth
, totalHeight
);
737 memdc2
.SelectObject(bitmap2
);
739 wxColour
clr(255, 255, 0);
740 wxBrush
yellowBrush(clr
, wxSOLID
);
741 memdc2
.SetBackground(yellowBrush
);
744 wxPen
yellowPen(clr
, 1, wxSOLID
);
746 // Now draw a white rectangle with red outline. It should
747 // entirely eclipse the yellow background.
748 memdc2
.SetPen(*wxRED_PEN
);
749 memdc2
.SetBrush(*wxWHITE_BRUSH
);
751 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
753 memdc2
.SetPen(wxNullPen
);
754 memdc2
.SetBrush(wxNullBrush
);
755 memdc2
.SelectObject(wxNullBitmap
);
757 dc
.DrawBitmap(bitmap2
, 500, 270);
759 // Repeat, but draw directly on dc
760 // Draw a yellow rectangle filling the bitmap
762 x
= 600; int y
= 270;
763 dc
.SetPen(yellowPen
);
764 dc
.SetBrush(yellowBrush
);
765 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
767 // Now draw a white rectangle with red outline. It should
768 // entirely eclipse the yellow background.
769 dc
.SetPen(*wxRED_PEN
);
770 dc
.SetBrush(*wxWHITE_BRUSH
);
772 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
775 void MyCanvas::DrawText(wxDC
& dc
)
777 // set underlined font for testing
778 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, true) );
779 dc
.DrawText( _T("This is text"), 110, 10 );
780 dc
.DrawRotatedText( _T("That is text"), 20, 10, -45 );
782 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
783 // under Win9x (it is not TrueType)
784 dc
.SetFont( *wxSWISS_FONT
);
787 dc
.SetBackgroundMode(wxTRANSPARENT
);
789 for ( int n
= -180; n
< 180; n
+= 30 )
791 text
.Printf(wxT(" %d rotated text"), n
);
792 dc
.DrawRotatedText(text
, 400, 400, n
);
795 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
797 dc
.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
802 dc
.GetTextExtent( _T("This is Swiss 18pt text."), &length
, &height
, &descent
);
803 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
804 dc
.DrawText( text
, 110, 80 );
806 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
807 dc
.DrawText( text
, 110, 120 );
809 dc
.DrawRectangle( 100, 40, 4, height
);
811 // test the logical function effect
813 dc
.SetLogicalFunction(wxINVERT
);
814 // text drawing should ignore logical function
815 dc
.DrawText( _T("There should be a text below"), 110, 150 );
816 dc
.DrawRectangle( 110, y
, 100, height
);
819 dc
.DrawText( _T("Visible text"), 110, y
);
820 dc
.DrawRectangle( 110, y
, 100, height
);
821 dc
.DrawText( _T("Visible text"), 110, y
);
822 dc
.DrawRectangle( 110, y
, 100, height
);
823 dc
.SetLogicalFunction(wxCOPY
);
826 dc
.DrawRectangle( 110, y
, 100, height
);
827 dc
.DrawText( _T("Another visible text"), 110, y
);
834 } rasterOperations
[] =
836 { wxT("wxAND"), wxAND
},
837 { wxT("wxAND_INVERT"), wxAND_INVERT
},
838 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
839 { wxT("wxCLEAR"), wxCLEAR
},
840 { wxT("wxCOPY"), wxCOPY
},
841 { wxT("wxEQUIV"), wxEQUIV
},
842 { wxT("wxINVERT"), wxINVERT
},
843 { wxT("wxNAND"), wxNAND
},
844 { wxT("wxNO_OP"), wxNO_OP
},
845 { wxT("wxOR"), wxOR
},
846 { wxT("wxOR_INVERT"), wxOR_INVERT
},
847 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
848 { wxT("wxSET"), wxSET
},
849 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
850 { wxT("wxXOR"), wxXOR
},
853 void MyCanvas::DrawImages(wxDC
& dc
, DrawMode mode
)
855 dc
.DrawText(_T("original image"), 0, 0);
856 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
857 dc
.DrawText(_T("with colour mask"), 0, 100);
858 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, true);
859 dc
.DrawText(_T("the mask image"), 0, 200);
860 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
861 dc
.DrawText(_T("masked image"), 0, 300);
862 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, true);
864 int cx
= gs_bmpWithColMask
->GetWidth(),
865 cy
= gs_bmpWithColMask
->GetHeight();
868 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
870 wxCoord x
= 120 + 150*(n%4
),
873 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
874 memDC
.SelectObject(*gs_bmpWithColMask
);
875 if ( mode
== Draw_Stretch
)
877 dc
.StretchBlit(x
, y
, cx
, cy
, &memDC
, 0, 0, cx
/2, cy
/2,
878 rasterOperations
[n
].rop
, true);
882 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, true);
887 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
889 static const wxCoord w
= 60;
890 static const wxCoord h
= 60;
892 // reuse the text colour here
893 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
894 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
897 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
899 wxCoord x
= 20 + 150*(n%4
),
902 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
903 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
904 dc
.DrawRectangle(x
, y
, w
, h
);
905 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
906 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
909 // now some filled rectangles
910 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
912 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
914 wxCoord x
= 20 + 150*(n%4
),
917 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
918 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
919 dc
.DrawRectangle(x
, y
, w
, h
);
923 #if wxUSE_GRAPHICS_CONTEXT
925 void MyCanvas::DrawAlpha(wxDC
& no_dc
)
927 void MyCanvas::DrawAlpha(wxDC
& dc
)
935 wxDouble margin
= 20 ;
936 wxDouble width
= 180 ;
937 wxDouble radius
= 30 ;
939 dc
.SetPen( wxPen( wxColour( 128, 0, 0, 255 ),12, wxSOLID
));
940 dc
.SetBrush( wxBrush( wxColour( 255, 0, 0, 255),wxSOLID
));
942 wxRect
r(margin
,margin
+width
*0.66,width
,width
) ;
944 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
946 dc
.SetPen( wxPen( wxColour( 0, 0, 128, 255 ),12, wxSOLID
));
947 dc
.SetBrush( wxBrush( wxColour( 0, 0, 255, 255),wxSOLID
));
949 r
.Offset( width
* 0.8 , - width
* 0.66 ) ;
951 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
953 dc
.SetPen( wxPen( wxColour( 128, 128, 0, 255 ),12, wxSOLID
));
954 dc
.SetBrush( wxBrush( wxColour( 192, 192, 0, 255),wxSOLID
));
956 r
.Offset( width
* 0.8 , width
*0.5 ) ;
958 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
960 dc
.SetPen( *wxTRANSPARENT_PEN
) ;
961 dc
.SetBrush( wxBrush( wxColour(255,255,128,128) ) );
962 dc
.DrawRoundedRectangle( 0 , margin
+ width
/ 2 , width
* 3 , 100 , radius
) ;
964 dc
.SetTextForeground( wxColour(255,255,0,128) );
965 dc
.SetFont( wxFont( 40, wxFONTFAMILY_SWISS
, wxFONTSTYLE_ITALIC
, wxFONTWEIGHT_NORMAL
) );
966 dc
.DrawText( wxT("Hello!"), 120, 80 );
971 #if wxUSE_GRAPHICS_CONTEXT
973 const int BASE
= 80.0;
974 const int BASE2
= BASE
/2;
975 const int BASE4
= BASE
/4;
977 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
980 // modeled along Robin Dunn's GraphicsContext.py sample
982 void MyCanvas::DrawGraphics(wxGraphicsContext
* gc
)
984 wxFont font
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
985 gc
->SetFont(font
,*wxBLACK
);
987 // make a path that contains a circle and some lines, centered at 0,0
988 wxGraphicsPath path
= gc
->CreatePath() ;
989 path
.AddCircle( 0, 0, BASE2
);
990 path
.MoveToPoint(0, -BASE2
);
991 path
.AddLineToPoint(0, BASE2
);
992 path
.MoveToPoint(-BASE2
, 0);
993 path
.AddLineToPoint(BASE2
, 0);
995 path
.AddRectangle(-BASE4
, -BASE4
/2, BASE2
, BASE4
);
997 // Now use that path to demonstrate various capbilites of the grpahics context
998 gc
->PushState(); // save current translation/scale/other state
999 gc
->Translate(60, 75); // reposition the context origin
1001 gc
->SetPen(wxPen("navy", 1));
1002 gc
->SetBrush(wxBrush("pink"));
1004 for( int i
= 0 ; i
< 3 ; ++i
)
1010 label
= "StrokePath";
1020 gc
->GetTextExtent(label
, &w
, &h
, NULL
, NULL
);
1021 gc
->DrawText(label
, -w
/2, -BASE2
-h
-4);
1025 gc
->StrokePath(path
);
1034 gc
->Translate(2*BASE
, 0);
1037 gc
->PopState(); // restore saved state
1038 gc
->PushState(); // save it again
1039 gc
->Translate(60, 200); // offset to the lower part of the window
1041 gc
->DrawText("Scale", 0, -BASE2
);
1042 gc
->Translate(0, 20);
1044 gc
->SetBrush(wxBrush(wxColour(178, 34, 34, 128)));// 128 == half transparent
1045 for( int i
= 0 ; i
< 8 ; ++i
)
1047 gc
->Scale(1.08, 1.08); // increase scale by 8%
1052 gc
->PopState(); // restore saved state
1053 gc
->PushState(); // save it again
1054 gc
->Translate(400, 200);
1056 gc
->DrawText("Rotate", 0, -BASE2
);
1058 // Move the origin over to the next location
1059 gc
->Translate(0, 75);
1061 // draw our path again, rotating it about the central point,
1062 // and changing colors as we go
1063 for ( int angle
= 0 ; angle
< 360 ; angle
+= 30 )
1065 gc
->PushState(); // save this new current state so we can
1066 // pop back to it at the end of the loop
1067 wxImage::RGBValue val
= wxImage::HSVtoRGB(wxImage::HSVValue(float(angle
)/360, 1, 1));
1068 gc
->SetBrush(wxBrush(wxColour(val
.red
, val
.green
, val
.blue
, 64)));
1069 gc
->SetPen(wxPen(wxColour(val
.red
, val
.green
, val
.blue
, 128)));
1071 // use translate to artfully reposition each drawn path
1072 gc
->Translate(1.5 * BASE2
* cos(DegToRad(angle
)),
1073 1.5 * BASE2
* sin(DegToRad(angle
)));
1075 // use Rotate to rotate the path
1076 gc
->Rotate(DegToRad(angle
));
1086 void MyCanvas::DrawCircles(wxDC
& dc
)
1092 dc
.SetPen( *wxRED_PEN
);
1093 dc
.SetBrush( *wxGREEN_BRUSH
);
1095 dc
.DrawText(_T("Some circles"), 0, y
);
1096 dc
.DrawCircle(x
, y
, r
);
1097 dc
.DrawCircle(x
+ 2*r
, y
, r
);
1098 dc
.DrawCircle(x
+ 4*r
, y
, r
);
1101 dc
.DrawText(_T("And ellipses"), 0, y
);
1102 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
1103 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
1104 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
1107 dc
.DrawText(_T("And arcs"), 0, y
);
1108 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
1109 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
1110 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
1113 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
1114 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
1115 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
1116 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
1118 // same as above, just transparent brush
1120 dc
.SetPen( *wxRED_PEN
);
1121 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1124 dc
.DrawText(_T("Some circles"), 0, y
);
1125 dc
.DrawCircle(x
, y
, r
);
1126 dc
.DrawCircle(x
+ 2*r
, y
, r
);
1127 dc
.DrawCircle(x
+ 4*r
, y
, r
);
1130 dc
.DrawText(_T("And ellipses"), 0, y
);
1131 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
1132 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
1133 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
1136 dc
.DrawText(_T("And arcs"), 0, y
);
1137 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
1138 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
1139 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
1142 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
1143 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
1144 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
1145 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
1149 void MyCanvas::DrawSplines(wxDC
& dc
)
1152 dc
.DrawText(_T("Some splines"), 10, 5);
1154 // values are hardcoded rather than randomly generated
1155 // so the output can be compared between native
1156 // implementations on platforms with different random
1160 const wxPoint
center( R
+ 20, R
+ 20 );
1161 const int angles
[7] = { 0, 10, 33, 77, 13, 145, 90 };
1162 const int radii
[5] = { 100 , 59, 85, 33, 90 };
1166 // background spline calculation
1167 unsigned int radius_pos
= 0;
1168 unsigned int angle_pos
= 0;
1170 for ( int i
= 0; i
< n
; i
++ )
1172 angle
+= angles
[ angle_pos
];
1173 int r
= R
* radii
[ radius_pos
] / 100;
1174 pts
[ i
].x
= center
.x
+ (wxCoord
)( r
* cos( M_PI
* angle
/ 180.0) );
1175 pts
[ i
].y
= center
.y
+ (wxCoord
)( r
* sin( M_PI
* angle
/ 180.0) );
1178 if ( angle_pos
>= WXSIZEOF(angles
) ) angle_pos
= 0;
1181 if ( radius_pos
>= WXSIZEOF(radii
) ) radius_pos
= 0;
1184 // background spline drawing
1185 dc
.SetPen(*wxRED_PEN
);
1186 dc
.DrawSpline(WXSIZEOF(pts
), pts
);
1188 // less detailed spline calculation
1189 wxPoint letters
[4][5];
1191 letters
[0][0] = wxPoint( 0,1); // O O
1192 letters
[0][1] = wxPoint( 1,3); // * *
1193 letters
[0][2] = wxPoint( 2,2); // * O *
1194 letters
[0][3] = wxPoint( 3,3); // * * * *
1195 letters
[0][4] = wxPoint( 4,1); // O O
1197 letters
[1][0] = wxPoint( 5,1); // O*O
1198 letters
[1][1] = wxPoint( 6,1); // *
1199 letters
[1][2] = wxPoint( 7,2); // O
1200 letters
[1][3] = wxPoint( 8,3); // *
1201 letters
[1][4] = wxPoint( 9,3); // O*O
1203 letters
[2][0] = wxPoint( 5,3); // O*O
1204 letters
[2][1] = wxPoint( 6,3); // *
1205 letters
[2][2] = wxPoint( 7,2); // O
1206 letters
[2][3] = wxPoint( 8,1); // *
1207 letters
[2][4] = wxPoint( 9,1); // O*O
1209 letters
[3][0] = wxPoint(10,0); // O O
1210 letters
[3][1] = wxPoint(11,3); // * *
1211 letters
[3][2] = wxPoint(12,1); // * O *
1212 letters
[3][3] = wxPoint(13,3); // * * * *
1213 letters
[3][4] = wxPoint(14,0); // O O
1215 const int dx
= 2 * R
/ letters
[3][4].x
;
1216 const int h
[4] = { -R
/2, 0, R
/4, R
/2 };
1218 for ( int m
= 0; m
< 4; m
++ )
1220 for ( int n
= 0; n
< 5; n
++ )
1222 letters
[m
][n
].x
= center
.x
- R
+ letters
[m
][n
].x
* dx
;
1223 letters
[m
][n
].y
= center
.y
+ h
[ letters
[m
][n
].y
];
1226 dc
.SetPen( wxPen( wxT("blue"), 1, wxDOT
) );
1227 dc
.DrawLines(5, letters
[m
]);
1228 dc
.SetPen( wxPen( wxT("black"), 4, wxSOLID
) );
1229 dc
.DrawSpline(5, letters
[m
]);
1233 dc
.DrawText(_T("Splines not supported."), 10, 5);
1237 void MyCanvas::DrawGradients(wxDC
& dc
)
1239 static const int TEXT_HEIGHT
= 15;
1242 wxRect
r(10, 10, 50, 50);
1243 dc
.DrawText(_T("wxRIGHT"), r
.x
, r
.y
);
1244 r
.Offset(0, TEXT_HEIGHT
);
1245 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxRIGHT
);
1247 r
.Offset(0, r
.height
+ 10);
1248 dc
.DrawText(_T("wxLEFT"), r
.x
, r
.y
);
1249 r
.Offset(0, TEXT_HEIGHT
);
1250 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxLEFT
);
1252 r
.Offset(0, r
.height
+ 10);
1253 dc
.DrawText(_T("wxDOWN"), r
.x
, r
.y
);
1254 r
.Offset(0, TEXT_HEIGHT
);
1255 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxDOWN
);
1257 r
.Offset(0, r
.height
+ 10);
1258 dc
.DrawText(_T("wxUP"), r
.x
, r
.y
);
1259 r
.Offset(0, TEXT_HEIGHT
);
1260 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxUP
);
1264 r
= wxRect(200, 10, 50, 50);
1265 dc
.DrawText(_T("Blue inside"), r
.x
, r
.y
);
1266 r
.Offset(0, TEXT_HEIGHT
);
1267 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
);
1269 r
.Offset(0, r
.height
+ 10);
1270 dc
.DrawText(_T("White inside"), r
.x
, r
.y
);
1271 r
.Offset(0, TEXT_HEIGHT
);
1272 dc
.GradientFillConcentric(r
, *wxWHITE
, *wxBLUE
);
1274 r
.Offset(0, r
.height
+ 10);
1275 dc
.DrawText(_T("Blue in top left corner"), r
.x
, r
.y
);
1276 r
.Offset(0, TEXT_HEIGHT
);
1277 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
, wxPoint(0, 0));
1279 r
.Offset(0, r
.height
+ 10);
1280 dc
.DrawText(_T("Blue in bottom right corner"), r
.x
, r
.y
);
1281 r
.Offset(0, TEXT_HEIGHT
);
1282 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
, wxPoint(r
.width
, r
.height
));
1284 // check that the area filled by the gradient is exactly the interior of
1288 dc
.DrawText("The interior should be filled but", r
.x
, r
.y
);
1290 dc
.DrawText(" the red border should remain visible:", r
.x
, r
.y
);
1301 dc
.SetPen(wxPen(wxColour(255, 0, 0)));
1302 dc
.DrawRectangle(r
);
1304 dc
.GradientFillLinear(r
, wxColour(0,255,0), wxColour(0,0,0), wxNORTH
);
1305 dc
.DrawRectangle(r2
);
1307 dc
.GradientFillLinear(r2
, wxColour(0,0,0), wxColour(0,255,0), wxSOUTH
);
1308 dc
.DrawRectangle(r3
);
1310 dc
.GradientFillLinear(r3
, wxColour(0,255,0), wxColour(0,0,0), wxEAST
);
1311 dc
.DrawRectangle(r4
);
1313 dc
.GradientFillLinear(r4
, wxColour(0,0,0), wxColour(0,255,0), wxWEST
);
1316 void MyCanvas::DrawRegions(wxDC
& dc
)
1318 dc
.DrawText(_T("You should see a red rect partly covered by a cyan one ")
1319 _T("on the left"), 10, 5);
1320 dc
.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
1321 10, 5 + dc
.GetCharHeight());
1322 dc
.DrawText(_T("The second copy should be identical but right part of it ")
1323 _T("should be offset by 10 pixels."),
1324 10, 5 + 2*dc
.GetCharHeight());
1326 DrawRegionsHelper(dc
, 10, true);
1327 DrawRegionsHelper(dc
, 350, false);
1330 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
1334 dc
.DestroyClippingRegion();
1335 dc
.SetBrush( *wxWHITE_BRUSH
);
1336 dc
.SetPen( *wxTRANSPARENT_PEN
);
1337 dc
.DrawRectangle( x
, y
, 310, 310 );
1339 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
1341 dc
.SetBrush( *wxRED_BRUSH
);
1342 dc
.DrawRectangle( x
, y
, 310, 310 );
1344 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
1346 dc
.SetBrush( *wxCYAN_BRUSH
);
1347 dc
.DrawRectangle( x
, y
, 310, 310 );
1349 dc
.DestroyClippingRegion();
1351 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
1352 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
1354 region
.Offset(10, 10);
1356 dc
.SetDeviceClippingRegion(region
);
1358 dc
.SetBrush( *wxGREY_BRUSH
);
1359 dc
.DrawRectangle( x
, y
, 310, 310 );
1361 if (m_smile_bmp
.Ok())
1363 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, true );
1364 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, true );
1365 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, true );
1366 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, true );
1367 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, true );
1371 #if TEST_CAIRO_EVERYWHERE
1372 extern wxGraphicsRenderer
* gCairoRenderer
;
1375 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
1377 wxPaintDC
pdc(this);
1379 #if wxUSE_GRAPHICS_CONTEXT
1380 #if TEST_CAIRO_EVERYWHERE
1382 gdc
.SetGraphicsContext( gCairoRenderer
->CreateContext( pdc
) );
1386 wxDC
&dc
= m_useContext
? (wxDC
&) gdc
: (wxDC
&) pdc
;
1393 m_owner
->PrepareDC(dc
);
1395 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
1396 if ( m_owner
->m_backgroundBrush
.Ok() )
1397 dc
.SetBackground( m_owner
->m_backgroundBrush
);
1398 if ( m_owner
->m_colourForeground
.Ok() )
1399 dc
.SetTextForeground( m_owner
->m_colourForeground
);
1400 if ( m_owner
->m_colourBackground
.Ok() )
1401 dc
.SetTextBackground( m_owner
->m_colourBackground
);
1403 if ( m_owner
->m_textureBackground
) {
1404 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
1405 wxColour
clr(0,128,0);
1406 wxBrush
b(clr
, wxSOLID
);
1407 dc
.SetBackground(b
);
1412 dc
.SetClippingRegion(100, 100, 100, 100);
1416 if ( m_owner
->m_textureBackground
)
1418 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
1419 for ( int i
= 0; i
< 200; i
++ )
1420 dc
.DrawLine(0, i
*10, i
*10, 0);
1446 DrawTestLines( 0, 100, 0, dc
);
1447 DrawTestLines( 0, 320, 1, dc
);
1448 DrawTestLines( 0, 540, 2, dc
);
1449 DrawTestLines( 0, 760, 6, dc
);
1453 DrawTestBrushes(dc
);
1461 DrawImages(dc
, Draw_Normal
);
1464 case Show_Mask_Stretch
:
1465 DrawImages(dc
, Draw_Stretch
);
1469 DrawWithLogicalOps(dc
);
1472 #if wxUSE_GRAPHICS_CONTEXT
1477 DrawGraphics(gdc
.GetGraphicsContext());
1490 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
1494 wxClientDC
dc(this);
1496 m_owner
->PrepareDC(dc
);
1498 wxPoint pos
= event
.GetPosition();
1499 long x
= dc
.DeviceToLogicalX( pos
.x
);
1500 long y
= dc
.DeviceToLogicalY( pos
.y
);
1502 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
1503 m_owner
->SetStatusText( str
);
1509 event
.GetPosition(&x
,&y
);
1510 CalcUnscrolledPosition( x
, y
, &xx
, &yy
);
1511 m_currentpoint
= wxPoint( xx
, yy
) ;
1512 wxRect
newrect ( m_anchorpoint
, m_currentpoint
) ;
1514 wxClientDC
dc( this ) ;
1517 wxDCOverlay
overlaydc( m_overlay
, &dc
);
1520 dc
.SetPen( *wxGREY_PEN
);
1521 dc
.SetBrush( wxColour( 192,192,192,64 ) );
1523 dc
.SetPen( wxPen( *wxLIGHT_GREY
, 2, wxSOLID
) );
1524 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1526 dc
.DrawRectangle( newrect
);
1530 #endif // wxUSE_STATUSBAR
1533 void MyCanvas::OnMouseDown(wxMouseEvent
&event
)
1536 event
.GetPosition(&x
,&y
);
1537 CalcUnscrolledPosition( x
, y
, &xx
, &yy
);
1538 m_anchorpoint
= wxPoint( xx
, yy
) ;
1539 m_currentpoint
= m_anchorpoint
;
1540 m_rubberBand
= true ;
1544 void MyCanvas::OnMouseUp(wxMouseEvent
&event
)
1550 wxClientDC
dc( this );
1552 wxDCOverlay
overlaydc( m_overlay
, &dc
);
1556 m_rubberBand
= false;
1559 event
.GetPosition(&x
,&y
);
1560 CalcUnscrolledPosition( x
, y
, &xx
, &yy
);
1563 str
.Printf( wxT("Rectangle selection from %d,%d to %d,%d"),
1564 m_anchorpoint
.x
, m_anchorpoint
.y
, (int)xx
, (int)yy
);
1565 wxMessageBox( str
, wxT("Rubber-Banding") );
1570 // ----------------------------------------------------------------------------
1572 // ----------------------------------------------------------------------------
1574 // the event tables connect the wxWidgets events with the functions (event
1575 // handlers) which process them. It can be also done at run-time, but for the
1576 // simple menu events like this the static method is much simpler.
1577 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1578 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1579 EVT_MENU (File_About
, MyFrame::OnAbout
)
1580 EVT_MENU (File_Clip
, MyFrame::OnClip
)
1581 #if wxUSE_GRAPHICS_CONTEXT
1582 EVT_MENU (File_GraphicContext
, MyFrame::OnGraphicContext
)
1585 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1587 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1590 // frame constructor
1591 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1592 : wxFrame((wxFrame
*)NULL
, wxID_ANY
, title
, pos
, size
,
1593 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1595 // set the frame icon
1596 SetIcon(wxICON(mondrian
));
1598 wxMenu
*menuFile
= new wxMenu
;
1599 menuFile
->Append(File_ShowDefault
, _T("&Default screen\tF1"));
1600 menuFile
->Append(File_ShowText
, _T("&Text screen\tF2"));
1601 menuFile
->Append(File_ShowLines
, _T("&Lines screen\tF3"));
1602 menuFile
->Append(File_ShowBrushes
, _T("&Brushes screen\tF4"));
1603 menuFile
->Append(File_ShowPolygons
, _T("&Polygons screen\tF5"));
1604 menuFile
->Append(File_ShowMask
, _T("&Mask screen\tF6"));
1605 menuFile
->Append(File_ShowMaskStretch
, _T("1/&2 scaled mask\tShift-F6"));
1606 menuFile
->Append(File_ShowOps
, _T("&Raster operations screen\tF7"));
1607 menuFile
->Append(File_ShowRegions
, _T("Re&gions screen\tF8"));
1608 menuFile
->Append(File_ShowCircles
, _T("&Circles screen\tF9"));
1609 #if wxUSE_GRAPHICS_CONTEXT
1610 menuFile
->Append(File_ShowAlpha
, _T("&Alpha screen\tF10"));
1612 menuFile
->Append(File_ShowSplines
, _T("&Splines screen\tF11"));
1613 menuFile
->Append(File_ShowGradients
, _T("&Gradients screen\tF12"));
1614 #if wxUSE_GRAPHICS_CONTEXT
1615 menuFile
->Append(File_ShowGraphics
, _T("&Graphics screen"));
1617 menuFile
->AppendSeparator();
1618 menuFile
->AppendCheckItem(File_Clip
, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
1619 #if wxUSE_GRAPHICS_CONTEXT
1620 menuFile
->AppendCheckItem(File_GraphicContext
, _T("&Use GraphicContext\tCtrl-Y"), _T("Use GraphicContext"));
1622 menuFile
->AppendSeparator();
1623 menuFile
->Append(File_About
, _T("&About...\tCtrl-A"), _T("Show about dialog"));
1624 menuFile
->AppendSeparator();
1625 menuFile
->Append(File_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
1627 wxMenu
*menuMapMode
= new wxMenu
;
1628 menuMapMode
->Append( MapMode_Text
, _T("&TEXT map mode") );
1629 menuMapMode
->Append( MapMode_Lometric
, _T("&LOMETRIC map mode") );
1630 menuMapMode
->Append( MapMode_Twips
, _T("T&WIPS map mode") );
1631 menuMapMode
->Append( MapMode_Points
, _T("&POINTS map mode") );
1632 menuMapMode
->Append( MapMode_Metric
, _T("&METRIC map mode") );
1634 wxMenu
*menuUserScale
= new wxMenu
;
1635 menuUserScale
->Append( UserScale_StretchHoriz
, _T("Stretch &horizontally\tCtrl-H") );
1636 menuUserScale
->Append( UserScale_ShrinkHoriz
, _T("Shrin&k horizontally\tCtrl-G") );
1637 menuUserScale
->Append( UserScale_StretchVertic
, _T("Stretch &vertically\tCtrl-V") );
1638 menuUserScale
->Append( UserScale_ShrinkVertic
, _T("&Shrink vertically\tCtrl-W") );
1639 menuUserScale
->AppendSeparator();
1640 menuUserScale
->Append( UserScale_Restore
, _T("&Restore to normal\tCtrl-0") );
1642 wxMenu
*menuAxis
= new wxMenu
;
1643 menuAxis
->AppendCheckItem( AxisMirror_Horiz
, _T("Mirror horizontally\tCtrl-M") );
1644 menuAxis
->AppendCheckItem( AxisMirror_Vertic
, _T("Mirror vertically\tCtrl-N") );
1646 wxMenu
*menuLogical
= new wxMenu
;
1647 menuLogical
->Append( LogicalOrigin_MoveDown
, _T("Move &down\tCtrl-D") );
1648 menuLogical
->Append( LogicalOrigin_MoveUp
, _T("Move &up\tCtrl-U") );
1649 menuLogical
->Append( LogicalOrigin_MoveLeft
, _T("Move &right\tCtrl-L") );
1650 menuLogical
->Append( LogicalOrigin_MoveRight
, _T("Move &left\tCtrl-R") );
1651 menuLogical
->AppendSeparator();
1652 menuLogical
->Append( LogicalOrigin_Set
, _T("Set to (&100, 100)\tShift-Ctrl-1") );
1653 menuLogical
->Append( LogicalOrigin_Restore
, _T("&Restore to normal\tShift-Ctrl-0") );
1655 wxMenu
*menuColour
= new wxMenu
;
1657 menuColour
->Append( Colour_TextForeground
, _T("Text &foreground...") );
1658 menuColour
->Append( Colour_TextBackground
, _T("Text &background...") );
1659 menuColour
->Append( Colour_Background
, _T("Background &colour...") );
1660 #endif // wxUSE_COLOURDLG
1661 menuColour
->AppendCheckItem( Colour_BackgroundMode
, _T("&Opaque/transparent\tCtrl-B") );
1662 menuColour
->AppendCheckItem( Colour_TextureBackgound
, _T("Draw textured back&ground\tCtrl-T") );
1664 // now append the freshly created menu to the menu bar...
1665 wxMenuBar
*menuBar
= new wxMenuBar
;
1666 menuBar
->Append(menuFile
, _T("&File"));
1667 menuBar
->Append(menuMapMode
, _T("&Mode"));
1668 menuBar
->Append(menuUserScale
, _T("&Scale"));
1669 menuBar
->Append(menuAxis
, _T("&Axis"));
1670 menuBar
->Append(menuLogical
, _T("&Origin"));
1671 menuBar
->Append(menuColour
, _T("&Colours"));
1673 // ... and attach this menu bar to the frame
1674 SetMenuBar(menuBar
);
1678 SetStatusText(_T("Welcome to wxWidgets!"));
1679 #endif // wxUSE_STATUSBAR
1681 m_mapMode
= wxMM_TEXT
;
1684 m_xLogicalOrigin
= 0;
1685 m_yLogicalOrigin
= 0;
1687 m_yAxisReversed
= false;
1688 m_backgroundMode
= wxSOLID
;
1689 m_colourForeground
= *wxRED
;
1690 m_colourBackground
= *wxBLUE
;
1691 m_textureBackground
= false;
1693 m_canvas
= new MyCanvas( this );
1694 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1699 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1701 // true is to force the frame to close
1705 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1708 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1709 wxT("This sample tests various primitive drawing functions\n")
1710 wxT("(without any attempts to prevent flicker).\n")
1711 wxT("Copyright (c) Robert Roebling 1999")
1714 wxMessageBox(msg
, _T("About Drawing"), wxOK
| wxICON_INFORMATION
, this);
1717 void MyFrame::OnClip(wxCommandEvent
& event
)
1719 m_canvas
->Clip(event
.IsChecked());
1722 #if wxUSE_GRAPHICS_CONTEXT
1723 void MyFrame::OnGraphicContext(wxCommandEvent
& event
)
1725 m_canvas
->UseGraphicContext(event
.IsChecked());
1729 void MyFrame::OnShow(wxCommandEvent
& event
)
1731 m_canvas
->ToShow((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1734 void MyFrame::OnOption(wxCommandEvent
& event
)
1736 switch (event
.GetId())
1739 m_mapMode
= wxMM_TEXT
;
1741 case MapMode_Lometric
:
1742 m_mapMode
= wxMM_LOMETRIC
;
1745 m_mapMode
= wxMM_TWIPS
;
1747 case MapMode_Points
:
1748 m_mapMode
= wxMM_POINTS
;
1750 case MapMode_Metric
:
1751 m_mapMode
= wxMM_METRIC
;
1754 case LogicalOrigin_MoveDown
:
1755 m_yLogicalOrigin
+= 10;
1757 case LogicalOrigin_MoveUp
:
1758 m_yLogicalOrigin
-= 10;
1760 case LogicalOrigin_MoveLeft
:
1761 m_xLogicalOrigin
+= 10;
1763 case LogicalOrigin_MoveRight
:
1764 m_xLogicalOrigin
-= 10;
1766 case LogicalOrigin_Set
:
1768 m_yLogicalOrigin
= -100;
1770 case LogicalOrigin_Restore
:
1772 m_yLogicalOrigin
= 0;
1775 case UserScale_StretchHoriz
:
1776 m_xUserScale
*= 1.10;
1778 case UserScale_ShrinkHoriz
:
1779 m_xUserScale
/= 1.10;
1781 case UserScale_StretchVertic
:
1782 m_yUserScale
*= 1.10;
1784 case UserScale_ShrinkVertic
:
1785 m_yUserScale
/= 1.10;
1787 case UserScale_Restore
:
1792 case AxisMirror_Vertic
:
1793 m_yAxisReversed
= !m_yAxisReversed
;
1795 case AxisMirror_Horiz
:
1796 m_xAxisReversed
= !m_xAxisReversed
;
1800 case Colour_TextForeground
:
1801 m_colourForeground
= SelectColour();
1803 case Colour_TextBackground
:
1804 m_colourBackground
= SelectColour();
1806 case Colour_Background
:
1808 wxColour col
= SelectColour();
1811 m_backgroundBrush
.SetColour(col
);
1815 #endif // wxUSE_COLOURDLG
1817 case Colour_BackgroundMode
:
1818 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1822 case Colour_TextureBackgound
:
1823 m_textureBackground
= ! m_textureBackground
;
1831 m_canvas
->Refresh();
1834 void MyFrame::PrepareDC(wxDC
& dc
)
1836 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1837 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1838 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1839 dc
.SetMapMode( m_mapMode
);
1843 wxColour
MyFrame::SelectColour()
1847 wxColourDialog
dialog(this, &data
);
1849 if ( dialog
.ShowModal() == wxID_OK
)
1851 col
= dialog
.GetColourData().GetColour();
1856 #endif // wxUSE_COLOURDLG