Small testing changes,
[wxWidgets.git] / samples / drawing / drawing.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: drawing.cpp
3 // Purpose: shows and tests wxDC features
4 // Author: Robert Roebling
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "drawing.cpp"
22 #pragma interface "drawing.cpp"
23 #endif
24
25 // For compilers that support precompilation, includes "wx/wx.h".
26 #include "wx/wxprec.h"
27
28 #ifdef __BORLANDC__
29 #pragma hdrstop
30 #endif
31
32 // for all others, include the necessary headers (this file is usually all you
33 // need because it includes almost all "standard" wxWindows headers
34 #ifndef WX_PRECOMP
35 #include "wx/wx.h"
36 #endif
37
38 #include "wx/colordlg.h"
39 #include "wx/image.h"
40
41 // ----------------------------------------------------------------------------
42 // ressources
43 // ----------------------------------------------------------------------------
44
45 // the application icon
46 #if defined(__WXGTK__) || defined(__WXMOTIF__)
47 #include "mondrian.xpm"
48 #endif
49
50 // ----------------------------------------------------------------------------
51 // constants
52 // ----------------------------------------------------------------------------
53
54 // what do we show on screen (there are too many shapes to put them all on
55 // screen simultaneously)
56 enum ScreenToShow
57 {
58 Show_Default,
59 Show_Text,
60 Show_Lines,
61 Show_Polygons,
62 Show_Mask,
63 Show_Ops
64 };
65
66 // ----------------------------------------------------------------------------
67 // global variables
68 // ----------------------------------------------------------------------------
69
70 static wxBitmap gs_bmpNoMask,
71 gs_bmpWithColMask,
72 gs_bmpMask,
73 gs_bmpWithMask,
74 gs_bmp4,
75 gs_bmp36;
76
77 // ----------------------------------------------------------------------------
78 // private classes
79 // ----------------------------------------------------------------------------
80
81 // Define a new application type, each program should derive a class from wxApp
82 class MyApp : public wxApp
83 {
84 public:
85 // override base class virtuals
86 // ----------------------------
87
88 // this one is called on application startup and is a good place for the app
89 // initialization (doing it here and not in the ctor allows to have an error
90 // return: if OnInit() returns false, the application terminates)
91 virtual bool OnInit();
92
93 protected:
94 bool LoadImages();
95 };
96
97 class MyCanvas;
98
99 // Define a new frame type: this is going to be our main frame
100 class MyFrame : public wxFrame
101 {
102 public:
103 // ctor(s)
104 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
105
106 // event handlers (these functions should _not_ be virtual)
107 void OnQuit(wxCommandEvent& event);
108 void OnAbout(wxCommandEvent& event);
109 void OnShow(wxCommandEvent &event);
110 void OnOption(wxCommandEvent &event);
111
112 wxColour SelectColour();
113 void PrepareDC(wxDC& dc);
114
115 int m_backgroundMode;
116 int m_textureBackground;
117 int m_mapMode;
118 double m_xUserScale;
119 double m_yUserScale;
120 int m_xLogicalOrigin;
121 int m_yLogicalOrigin;
122 bool m_xAxisReversed,
123 m_yAxisReversed;
124 wxColour m_colourForeground, // these are _text_ colours
125 m_colourBackground;
126 wxBrush m_backgroundBrush;
127 MyCanvas *m_canvas;
128
129 private:
130 // any class wishing to process wxWindows events must use this macro
131 DECLARE_EVENT_TABLE()
132 };
133
134 // define a scrollable canvas for drawing onto
135 class MyCanvas: public wxScrolledWindow
136 {
137 public:
138 MyCanvas( MyFrame *parent );
139
140 void OnPaint(wxPaintEvent &event);
141 void OnMouseMove(wxMouseEvent &event);
142
143 void Show(ScreenToShow show) { m_show = show; Refresh(); }
144
145 protected:
146 void DrawTestPoly( int x, int y, wxDC &dc ,int transparent );
147 void DrawTestLines( int x, int y, int width, wxDC &dc );
148 void DrawText(wxDC& dc);
149 void DrawImages(wxDC& dc);
150 void DrawWithLogicalOps(wxDC& dc);
151 void DrawDefault(wxDC& dc);
152
153 private:
154 MyFrame *m_owner;
155
156 ScreenToShow m_show;
157
158 DECLARE_EVENT_TABLE()
159 };
160
161 // ----------------------------------------------------------------------------
162 // constants
163 // ----------------------------------------------------------------------------
164
165 // IDs for the controls and the menu commands
166 enum
167 {
168 // menu items
169 File_Quit = 1,
170 File_About,
171
172 MenuShow_First,
173 File_ShowDefault = MenuShow_First,
174 File_ShowText,
175 File_ShowLines,
176 File_ShowPolygons,
177 File_ShowMask,
178 File_ShowOps,
179 MenuShow_Last = File_ShowOps,
180
181 MenuOption_First,
182
183 MapMode_Text = MenuOption_First,
184 MapMode_Lometric,
185 MapMode_Twips,
186 MapMode_Points,
187 MapMode_Metric,
188
189 UserScale_StretchHoriz,
190 UserScale_ShrinkHoriz,
191 UserScale_StretchVertic,
192 UserScale_ShrinkVertic,
193 UserScale_Restore,
194
195 AxisMirror_Horiz,
196 AxisMirror_Vertic,
197
198 LogicalOrigin_MoveDown,
199 LogicalOrigin_MoveUp,
200 LogicalOrigin_MoveLeft,
201 LogicalOrigin_MoveRight,
202
203 Colour_TextForeground,
204 Colour_TextBackground,
205 Colour_Background,
206 Colour_BackgroundMode,
207 Colour_TextureBackgound,
208
209 MenuOption_Last = Colour_TextureBackgound
210 };
211
212 // ----------------------------------------------------------------------------
213 // event tables and other macros for wxWindows
214 // ----------------------------------------------------------------------------
215
216
217 // Create a new application object: this macro will allow wxWindows to create
218 // the application object during program execution (it's better than using a
219 // static object for many reasons) and also declares the accessor function
220 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
221 // not wxApp)
222 IMPLEMENT_APP(MyApp)
223
224 // ============================================================================
225 // implementation
226 // ============================================================================
227
228 // ----------------------------------------------------------------------------
229 // the application class
230 // ----------------------------------------------------------------------------
231
232 bool MyApp::LoadImages()
233 {
234 wxPathList pathList;
235 pathList.Add(".");
236 pathList.Add("..");
237
238 wxString path = pathList.FindValidPath("pat4.bmp");
239 if ( !path )
240 return FALSE;
241 gs_bmp4.LoadFile(path, wxBITMAP_TYPE_BMP);
242 wxMask* mask4 = new wxMask(gs_bmp4, *wxBLACK);
243 gs_bmp4.SetMask(mask4);
244
245 path = pathList.FindValidPath("pat36.bmp");
246 if ( !path )
247 return FALSE;
248 gs_bmp36.LoadFile(path, wxBITMAP_TYPE_BMP);
249 wxMask* mask36 = new wxMask(gs_bmp36, *wxBLACK);
250 gs_bmp36.SetMask(mask36);
251
252 path = pathList.FindValidPath("image.bmp");
253 if ( !path )
254 return FALSE;
255 gs_bmpNoMask.LoadFile(path, wxBITMAP_TYPE_BMP);
256 gs_bmpWithMask.LoadFile(path, wxBITMAP_TYPE_BMP);
257 gs_bmpWithColMask.LoadFile(path, wxBITMAP_TYPE_BMP);
258
259 path = pathList.FindValidPath("mask.bmp");
260 if ( !path )
261 return FALSE;
262 gs_bmpMask.LoadFile(path, wxBITMAP_TYPE_BMP);
263
264 // This is so wrong, it hurts.
265 // gs_bmpMask.SetDepth(1);
266 // wxMask *mask = new wxMask(gs_bmpMask);
267
268 wxMask *mask = new wxMask(gs_bmpMask, *wxBLACK);
269 gs_bmpWithMask.SetMask(mask);
270
271 mask = new wxMask(gs_bmpWithColMask, *wxWHITE);
272 gs_bmpWithColMask.SetMask(mask);
273
274 return TRUE;
275 }
276
277 // `Main program' equivalent: the program execution "starts" here
278 bool MyApp::OnInit()
279 {
280 // Create the main application window
281 MyFrame *frame = new MyFrame("Drawing sample",
282 wxPoint(50, 50), wxSize(550, 340));
283
284 // Show it and tell the application that it's our main window
285 frame->Show(TRUE);
286 SetTopWindow(frame);
287
288 if ( !LoadImages() )
289 {
290 wxLogError("Can't load one of the bitmap files needed for this sample "
291 "from the current or parent directory, please copy them "
292 "there.");
293
294 // stop here
295 return FALSE;
296 }
297
298 // ok, continue
299 return TRUE;
300 }
301
302 // ----------------------------------------------------------------------------
303 // MyCanvas
304 // ----------------------------------------------------------------------------
305
306 // the event tables connect the wxWindows events with the functions (event
307 // handlers) which process them.
308 BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
309 EVT_PAINT (MyCanvas::OnPaint)
310 EVT_MOTION (MyCanvas::OnMouseMove)
311 END_EVENT_TABLE()
312
313 MyCanvas::MyCanvas( MyFrame *parent ) : wxScrolledWindow( parent )
314 {
315 m_owner = parent;
316 m_show = Show_Default;
317 }
318
319 //draw a polygon and an overlapping rectangle
320 //is transparent is 1, the fill pattern are made transparent
321 //is transparent is 2, the fill pattern are made transparent but inversed
322 //is transparent is 0 the text for and background color will be used to represent/map
323 //the colors of the monochrome bitmap pixels to the fillpattern
324 //
325 //i miss_used the the menu items for setting so called back and fore ground color
326 //just to show how the those colors do influence the fillpatterns
327 //just play with those,
328 //and with the code
329 //variations are endless using other logical functions
330 void MyCanvas::DrawTestPoly( int x, int y,wxDC &dc,int transparent )
331 {
332 wxBrush* brush4 = new wxBrush(gs_bmp4);
333 wxBrush* brush36 = new wxBrush(gs_bmp36);
334
335 wxPoint todraw[5];
336 todraw[0].x=(long)x+100;
337 todraw[0].y=(long)y+100;
338 todraw[1].x=(long)x+300;
339 todraw[1].y=(long)y+100;
340 todraw[2].x=(long)x+300;
341 todraw[2].y=(long)y+300;
342 todraw[3].x=(long)x+150;
343 todraw[3].y=(long)y+350;
344 todraw[4].x=(long)x+100;
345 todraw[4].y=(long)y+300;
346
347 wxPoint todraw2[5];
348 todraw2[0].x=100;
349 todraw2[0].y=100;
350 todraw2[1].x=300;
351 todraw2[1].y=100;
352 todraw2[2].x=300;
353 todraw2[2].y=300;
354 todraw2[3].x=150;
355 todraw2[3].y=350;
356 todraw2[4].x=100;
357 todraw2[4].y=300;
358
359 switch (transparent)
360 {
361 case 0:
362 {
363 dc.SetPen( wxPen( "black", 4, wxSOLID) );
364 dc.SetBrush( *brush4 );
365 dc.SetTextForeground(*wxGREEN);
366 dc.SetTextBackground(m_owner->m_colourForeground);
367 dc.SetLogicalFunction(wxCOPY);
368 dc.DrawPolygon(5,todraw,0,0,wxWINDING_RULE);
369
370 //don't understand hwo but the outline is also depending on logicalfunction
371 dc.SetPen( wxPen( "red", 4, wxSOLID) );
372 dc.SetBrush( *brush36 );
373 dc.SetTextForeground(*wxCYAN);
374 dc.SetTextBackground(m_owner->m_colourBackground);
375 dc.SetLogicalFunction(wxCOPY);
376 dc.DrawRectangle( x+10, y+10, 200, 200 );
377 dc.SetBrush(wxNullBrush);
378 dc.SetPen(wxNullPen);
379 break;
380 }
381 case 1: //now with transparent fillpatterns
382 {
383
384 wxBitmap* bmpBlit = new wxBitmap(600,400);
385 wxMemoryDC* memDC= new wxMemoryDC();
386 // wxBrush _clearbrush(*wxGREEN,wxSOLID);
387 wxBrush _clearbrush(*wxBLACK,wxSOLID);
388 memDC->SelectObject(*bmpBlit);
389 memDC->BeginDrawing();
390 memDC->SetBackground(_clearbrush);
391 memDC->Clear();
392 memDC->SetBackground(wxNullBrush);
393
394 memDC->SetPen( wxPen( "black", 4, wxSOLID) );
395 memDC->SetBrush( wxNullBrush);
396 memDC->SetBrush( *brush4 );
397 memDC->SetTextForeground(*wxBLACK); // 0s --> 0x000000 (black)
398 memDC->SetTextBackground(*wxWHITE); // 1s --> 0xFFFFFF (white)
399 memDC->SetLogicalFunction(wxAND_INVERT);
400
401 // BLACK OUT the opaque pixels and leave the rest as is
402 memDC->DrawPolygon(5,todraw2,0,0,wxWINDING_RULE);
403
404 // Set background and foreground colors for fill pattern
405 //the previous blacked out pixels are now merged with the layer color
406 //while the non blacked out pixels stay as they are.
407 memDC->SetTextForeground(*wxBLACK); // 0s --> 0x000000 (black)
408
409 //now define what will be the color of the fillpattern parts that are not transparent
410 // memDC->SetTextBackground(*wxBLUE);
411 memDC->SetTextBackground(m_owner->m_colourForeground);
412 memDC->SetLogicalFunction(wxOR);
413
414
415 //don't understand how but the outline is also depending on logicalfunction
416 memDC->SetPen( wxPen( "red", 4, wxSOLID) );
417 memDC->DrawPolygon(5,todraw2,0,0,wxWINDING_RULE);
418
419 memDC->SetLogicalFunction(wxCOPY);
420
421 memDC->SetPen( wxPen( "black", 4, wxSOLID) );
422 memDC->SetBrush( wxNullBrush);
423 memDC->SetBrush( *brush36 );
424 memDC->SetTextForeground(*wxBLACK); // 0s --> 0x000000 (black)
425 memDC->SetTextBackground(*wxWHITE); // 1s --> 0xFFFFFF (white)
426 memDC->SetLogicalFunction(wxAND_INVERT);
427
428 memDC->DrawRectangle( 10, 10, 200, 200 );
429
430 // Set background and foreground colors for fill pattern
431 //the previous blacked out pixels are now merged with the layer color
432 //while the non blacked out pixels stay as they are.
433 memDC->SetTextForeground(*wxBLACK); // 0s --> 0x000000 (black)
434 //now define what will be the color of the fillpattern parts that are not transparent
435 // memDC->SetTextBackground(*wxRED);
436 memDC->SetTextBackground(m_owner->m_colourBackground);
437 memDC->SetLogicalFunction(wxOR);
438
439 //don't understand how but the outline is also depending on logicalfunction
440 memDC->SetPen( wxPen( "yellow", 4, wxSOLID) );
441 memDC->DrawRectangle( 10, 10, 200, 200 );
442
443 memDC->SetBrush(wxNullBrush);
444 memDC->SetPen(wxNullPen);
445
446 memDC->EndDrawing();
447 dc.Blit(x,y,600,400,memDC,0,0,wxCOPY);
448 delete bmpBlit;
449 delete memDC;
450 break;
451 }
452 case 2: //now with transparent inversed fillpatterns
453 {
454 wxBitmap* bmpBlit = new wxBitmap(600,400);
455 wxMemoryDC* memDC= new wxMemoryDC();
456 wxBrush _clearbrush(*wxWHITE,wxSOLID);
457 memDC->SelectObject(*bmpBlit);
458 memDC->BeginDrawing();
459 memDC->SetBackground(_clearbrush);
460 memDC->Clear();
461 memDC->SetBackground(wxNullBrush);
462
463 memDC->SetPen( wxPen( "black", 4, wxSOLID) );
464 memDC->SetBrush( *brush4 );
465 memDC->SetTextBackground(*wxBLACK); // 0s --> 0x000000 (black)
466 memDC->SetTextForeground(*wxWHITE); // 1s --> 0xFFFFFF (white)
467 memDC->SetLogicalFunction(wxAND_INVERT);
468
469 // BLACK OUT the opaque pixels and leave the rest as is
470 memDC->DrawPolygon(5,todraw2,0,0,wxWINDING_RULE);
471
472 // Set background and foreground colors for fill pattern
473 //the previous blacked out pixels are now merged with the layer color
474 //while the non blacked out pixels stay as they are.
475 memDC->SetTextBackground(*wxBLACK); // 0s --> 0x000000 (black)
476
477 //now define what will be the color of the fillpattern parts that are not transparent
478 memDC->SetTextForeground(m_owner->m_colourForeground);
479 memDC->SetLogicalFunction(wxOR);
480
481
482 //don't understand how but the outline is also depending on logicalfunction
483 memDC->SetPen( wxPen( "red", 4, wxSOLID) );
484 memDC->DrawPolygon(5,todraw2,0,0,wxWINDING_RULE);
485
486 memDC->SetLogicalFunction(wxCOPY);
487
488 memDC->SetPen( wxPen( "black", 4, wxSOLID) );
489 memDC->SetBrush( *brush36 );
490 memDC->SetTextBackground(*wxBLACK); // 0s --> 0x000000 (black)
491 memDC->SetTextForeground(*wxWHITE); // 1s --> 0xFFFFFF (white)
492 memDC->SetLogicalFunction(wxAND_INVERT);
493
494 memDC->DrawRectangle( 10,10, 200, 200 );
495
496 // Set background and foreground colors for fill pattern
497 //the previous blacked out pixels are now merged with the layer color
498 //while the non blacked out pixels stay as they are.
499 memDC->SetTextBackground(*wxBLACK); // 0s --> 0x000000 (black)
500 //now define what will be the color of the fillpattern parts that are not transparent
501 memDC->SetTextForeground(m_owner->m_colourBackground);
502 memDC->SetLogicalFunction(wxOR);
503
504 //don't understand how but the outline is also depending on logicalfunction
505 memDC->SetPen( wxPen( "yellow", 4, wxSOLID) );
506 memDC->DrawRectangle( 10, 10, 200, 200 );
507
508 memDC->SetBrush(wxNullBrush);
509 memDC->SetPen(wxNullPen);
510 dc.Blit(x,y,600,400,memDC,0,0,wxCOPY);
511 delete bmpBlit;
512 delete memDC;
513 }
514 }
515
516 delete brush4;
517 delete brush36;
518 }
519
520 void MyCanvas::DrawTestLines( int x, int y, int width, wxDC &dc )
521 {
522 dc.SetPen( wxPen( "black", width, wxSOLID) );
523 dc.SetBrush( *wxRED_BRUSH );
524 dc.DrawRectangle( x+10, y+10, 100, 190 );
525
526 dc.SetPen( wxPen( "black", width, wxSOLID) );
527 dc.DrawLine( x+20, y+20, 100, y+20 );
528 dc.SetPen( wxPen( "black", width, wxDOT) );
529 dc.DrawLine( x+20, y+30, 100, y+30 );
530 dc.SetPen( wxPen( "black", width, wxSHORT_DASH) );
531 dc.DrawLine( x+20, y+40, 100, y+40 );
532 dc.SetPen( wxPen( "black", width, wxLONG_DASH) );
533 dc.DrawLine( x+20, y+50, 100, y+50 );
534 dc.SetPen( wxPen( "black", width, wxDOT_DASH) );
535 dc.DrawLine( x+20, y+60, 100, y+60 );
536
537 dc.SetPen( wxPen( "black", width, wxBDIAGONAL_HATCH) );
538 dc.DrawLine( x+20, y+70, 100, y+70 );
539 dc.SetPen( wxPen( "black", width, wxCROSSDIAG_HATCH) );
540 dc.DrawLine( x+20, y+80, 100, y+80 );
541 dc.SetPen( wxPen( "black", width, wxFDIAGONAL_HATCH) );
542 dc.DrawLine( x+20, y+90, 100, y+90 );
543 dc.SetPen( wxPen( "black", width, wxCROSS_HATCH) );
544 dc.DrawLine( x+20, y+100, 100, y+100 );
545 dc.SetPen( wxPen( "black", width, wxHORIZONTAL_HATCH) );
546 dc.DrawLine( x+20, y+110, 100, y+110 );
547 dc.SetPen( wxPen( "black", width, wxVERTICAL_HATCH) );
548 dc.DrawLine( x+20, y+120, 100, y+120 );
549
550 wxPen ud( "black", width, wxUSER_DASH );
551 wxDash dash1[1];
552 dash1[0] = 0;
553 ud.SetDashes( 1, dash1 );
554 dc.DrawLine( x+20, y+140, 100, y+140 );
555 dash1[0] = 1;
556 ud.SetDashes( 1, dash1 );
557 dc.DrawLine( x+20, y+150, 100, y+150 );
558 dash1[0] = 2;
559 ud.SetDashes( 1, dash1 );
560 dc.DrawLine( x+20, y+160, 100, y+160 );
561 dash1[0] = 0xFF;
562 ud.SetDashes( 1, dash1 );
563 dc.DrawLine( x+20, y+170, 100, y+170 );
564 }
565
566 void MyCanvas::DrawDefault(wxDC& dc)
567 {
568 // mark the origin
569 dc.DrawCircle(0, 0, 10);
570 #if !(defined __WXGTK__) && !(defined __WXMOTIF__)
571 // not implemented in wxGTK or wxMOTIF :-(
572 dc.FloodFill(0, 0, wxColour(255, 0, 0));
573 #endif //
574
575 dc.DrawIcon( wxICON(mondrian), 40, 40 );
576
577 dc.DrawCheckMark(5, 80, 15, 15);
578 dc.DrawCheckMark(25, 80, 30, 30);
579 dc.DrawCheckMark(60, 80, 60, 60);
580
581 // this is the test for "blitting bitmap into DC damages selected brush"
582 // bug
583 wxIcon icon = wxTheApp->GetStdIcon(wxICON_INFORMATION);
584 wxCoord rectSize = icon.GetWidth() + 10;
585 wxCoord x = 100;
586 dc.SetPen(*wxTRANSPARENT_PEN);
587 dc.SetBrush( *wxGREEN_BRUSH );
588 dc.DrawRectangle(x, 10, rectSize, rectSize);
589 dc.DrawBitmap(icon, x + 5, 15, TRUE);
590 x += rectSize + 10;
591 dc.DrawRectangle(x, 10, rectSize, rectSize);
592 dc.DrawIcon(wxTheApp->GetStdIcon(wxICON_INFORMATION), x + 5, 15);
593 x += rectSize + 10;
594 dc.DrawRectangle(x, 10, rectSize, rectSize);
595
596 // test for "transparent" bitmap drawing (it intersects with the last
597 // rectangle above)
598 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
599 #include "../image/smile.xpm"
600 wxBitmap bmp(smile_xpm);
601
602 if (bmp.Ok())
603 dc.DrawBitmap(bmp, x + rectSize - 20, rectSize - 10, TRUE);
604
605 dc.SetBrush( *wxBLACK_BRUSH );
606 dc.DrawRectangle( 0, 160, 1000, 300 );
607
608 // draw lines
609 wxBitmap bitmap(20,70);
610 wxMemoryDC memdc;
611 memdc.SelectObject( bitmap );
612 memdc.SetBrush( *wxBLACK_BRUSH );
613 memdc.SetPen( *wxWHITE_PEN );
614 memdc.DrawRectangle(0,0,20,70);
615 memdc.DrawLine( 10,0,10,70 );
616
617 // to the right
618 wxPen pen = *wxRED_PEN;
619 memdc.SetPen(pen);
620 memdc.DrawLine( 10, 5,10, 5 );
621 memdc.DrawLine( 10,10,11,10 );
622 memdc.DrawLine( 10,15,12,15 );
623 memdc.DrawLine( 10,20,13,20 );
624
625 /*
626 memdc.SetPen(*wxRED_PEN);
627 memdc.DrawLine( 12, 5,12, 5 );
628 memdc.DrawLine( 12,10,13,10 );
629 memdc.DrawLine( 12,15,14,15 );
630 memdc.DrawLine( 12,20,15,20 );
631 */
632
633 // same to the left
634 memdc.DrawLine( 10,25,10,25 );
635 memdc.DrawLine( 10,30, 9,30 );
636 memdc.DrawLine( 10,35, 8,35 );
637 memdc.DrawLine( 10,40, 7,40 );
638
639 // XOR draw lines
640 dc.SetPen(*wxWHITE_PEN);
641 memdc.SetLogicalFunction( wxINVERT );
642 memdc.SetPen( *wxWHITE_PEN );
643 memdc.DrawLine( 10,50,10,50 );
644 memdc.DrawLine( 10,55,11,55 );
645 memdc.DrawLine( 10,60,12,60 );
646 memdc.DrawLine( 10,65,13,65 );
647
648 memdc.DrawLine( 12,50,12,50 );
649 memdc.DrawLine( 12,55,13,55 );
650 memdc.DrawLine( 12,60,14,60 );
651 memdc.DrawLine( 12,65,15,65 );
652
653 memdc.SelectObject( wxNullBitmap );
654 dc.DrawBitmap( bitmap, 10, 170 );
655 wxImage image( bitmap );
656 image.Rescale( 60,210 );
657 bitmap = image.ConvertToBitmap();
658 dc.DrawBitmap( bitmap, 50, 170 );
659
660 // test the rectangle outline drawing - there should be one pixel between
661 // the rect and the lines
662 dc.SetPen(*wxWHITE_PEN);
663 dc.SetBrush( *wxTRANSPARENT_BRUSH );
664 dc.DrawRectangle(150, 170, 49, 29);
665 dc.DrawRectangle(200, 170, 49, 29);
666 dc.SetPen(*wxWHITE_PEN);
667 dc.DrawLine(250, 210, 250, 170);
668 dc.DrawLine(260, 200, 150, 200);
669
670 // test the rectangle filled drawing - there should be one pixel between
671 // the rect and the lines
672 dc.SetPen(*wxTRANSPARENT_PEN);
673 dc.SetBrush( *wxWHITE_BRUSH );
674 dc.DrawRectangle(300, 170, 49, 29);
675 dc.DrawRectangle(350, 170, 49, 29);
676 dc.SetPen(*wxWHITE_PEN);
677 dc.DrawLine(400, 170, 400, 210);
678 dc.DrawLine(300, 200, 410, 200);
679
680 // and now for filled rect with outline
681 dc.SetPen(*wxRED_PEN);
682 dc.SetBrush( *wxWHITE_BRUSH );
683 dc.DrawRectangle(500, 170, 49, 29);
684 dc.DrawRectangle(550, 170, 49, 29);
685 dc.SetPen(*wxWHITE_PEN);
686 dc.DrawLine(600, 170, 600, 210);
687 dc.DrawLine(500, 200, 610, 200);
688
689 // test the rectangle outline drawing - there should be one pixel between
690 // the rect and the lines
691 dc.SetPen(*wxWHITE_PEN);
692 dc.SetBrush( *wxTRANSPARENT_BRUSH );
693 dc.DrawRoundedRectangle(150, 270, 49, 29, 6);
694 dc.DrawRoundedRectangle(200, 270, 49, 29, 6);
695 dc.SetPen(*wxWHITE_PEN);
696 dc.DrawLine(250, 270, 250, 310);
697 dc.DrawLine(150, 300, 260, 300);
698
699 // test the rectangle filled drawing - there should be one pixel between
700 // the rect and the lines
701 dc.SetPen(*wxTRANSPARENT_PEN);
702 dc.SetBrush( *wxWHITE_BRUSH );
703 dc.DrawRoundedRectangle(300, 270, 49, 29, 6);
704 dc.DrawRoundedRectangle(350, 270, 49, 29, 6);
705 dc.SetPen(*wxWHITE_PEN);
706 dc.DrawLine(400, 270, 400, 310);
707 dc.DrawLine(300, 300, 410, 300);
708
709 // Added by JACS to demonstrate bizarre behaviour.
710 // With a size of 70, we get a missing red RHS,
711 // and the hight is too small, so we get yellow
712 // showing. With a size of 40, it draws as expected:
713 // it just shows a white rectangle with red outline.
714 int totalWidth = 70;
715 int totalHeight = 70;
716 wxBitmap bitmap2(totalWidth, totalHeight);
717
718 wxMemoryDC memdc2;
719 memdc2.SelectObject(bitmap2);
720
721 wxBrush yellowBrush(wxColour(255, 255, 0), wxSOLID);
722 memdc2.SetBackground(yellowBrush);
723 memdc2.Clear();
724
725 wxPen yellowPen(wxColour(255, 255, 0), 1, wxSOLID);
726
727 // Now draw a white rectangle with red outline. It should
728 // entirely eclipse the yellow background.
729 memdc2.SetPen(*wxRED_PEN);
730 memdc2.SetBrush(*wxWHITE_BRUSH);
731
732 memdc2.DrawRectangle(0, 0, totalWidth, totalHeight);
733
734 memdc2.SetPen(wxNullPen);
735 memdc2.SetBrush(wxNullBrush);
736 memdc2.SelectObject(wxNullBitmap);
737
738 dc.DrawBitmap(bitmap2, 500, 270);
739
740 // Repeat, but draw directly on dc
741 // Draw a yellow rectangle filling the bitmap
742
743 x = 600; int y = 270;
744 dc.SetPen(yellowPen);
745 dc.SetBrush(yellowBrush);
746 dc.DrawRectangle(x, y, totalWidth, totalHeight);
747
748 // Now draw a white rectangle with red outline. It should
749 // entirely eclipse the yellow background.
750 dc.SetPen(*wxRED_PEN);
751 dc.SetBrush(*wxWHITE_BRUSH);
752
753 dc.DrawRectangle(x, y, totalWidth, totalHeight);
754 }
755
756 void MyCanvas::DrawText(wxDC& dc)
757 {
758 // set underlined font for testing
759 dc.SetFont( wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, TRUE) );
760 dc.DrawText( "This is text", 110, 10 );
761 dc.DrawRotatedText( "That is text", 20, 10, -45 );
762
763 dc.SetFont( *wxNORMAL_FONT );
764
765 wxString text;
766 dc. SetBackgroundMode(wxTRANSPARENT);
767
768 for ( int n = -180; n < 180; n += 30 )
769 {
770 text.Printf(" %d rotated text", n);
771 dc.DrawRotatedText(text , 400, 400, n);
772 }
773
774 dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
775
776 dc.DrawText( "This is Swiss 18pt text.", 110, 40 );
777
778 long length;
779 long height;
780 long descent;
781 dc.GetTextExtent( "This is Swiss 18pt text.", &length, &height, &descent );
782 text.Printf( "Dimensions are length %ld, height %ld, descent %ld", length, height, descent );
783 dc.DrawText( text, 110, 80 );
784
785 text.Printf( "CharHeight() returns: %d", dc.GetCharHeight() );
786 dc.DrawText( text, 110, 120 );
787
788 dc.DrawRectangle( 100, 40, 4, height );
789 }
790
791 static const struct
792 {
793 const wxChar *name;
794 int rop;
795 } rasterOperations[] =
796 {
797 { "wxAND", wxAND },
798 { "wxAND_INVERT", wxAND_INVERT },
799 { "wxAND_REVERSE", wxAND_REVERSE },
800 { "wxCLEAR", wxCLEAR },
801 { "wxCOPY", wxCOPY },
802 { "wxEQUIV", wxEQUIV },
803 { "wxINVERT", wxINVERT },
804 { "wxNAND", wxNAND },
805 { "wxNO_OP", wxNO_OP },
806 { "wxOR", wxOR },
807 { "wxOR_INVERT", wxOR_INVERT },
808 { "wxOR_REVERSE", wxOR_REVERSE },
809 { "wxSET", wxSET },
810 { "wxSRC_INVERT", wxSRC_INVERT },
811 { "wxXOR", wxXOR },
812 };
813
814 void MyCanvas::DrawImages(wxDC& dc)
815 {
816 dc.DrawText("original image", 0, 0);
817 dc.DrawBitmap(gs_bmpNoMask, 0, 20, 0);
818 dc.DrawText("with colour mask", 0, 100);
819 dc.DrawBitmap(gs_bmpWithColMask, 0, 120, TRUE);
820 dc.DrawText("the mask image", 0, 200);
821 dc.DrawBitmap(gs_bmpMask, 0, 220, 0);
822 dc.DrawText("masked image", 0, 300);
823 dc.DrawBitmap(gs_bmpWithMask, 0, 320, TRUE);
824
825 int cx = gs_bmpWithColMask.GetWidth(),
826 cy = gs_bmpWithColMask.GetHeight();
827
828 wxMemoryDC memDC;
829 for ( size_t n = 0; n < WXSIZEOF(rasterOperations); n++ )
830 {
831 wxCoord x = 120 + 150*(n%4),
832 y = 20 + 100*(n/4);
833
834 dc.DrawText(rasterOperations[n].name, x, y - 20);
835 memDC.SelectObject(gs_bmpWithColMask);
836 dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, TRUE);
837 }
838 }
839
840 void MyCanvas::DrawWithLogicalOps(wxDC& dc)
841 {
842 static const wxCoord w = 60;
843 static const wxCoord h = 60;
844
845 // reuse the text colour here
846 dc.SetPen(wxPen(m_owner->m_colourForeground, 1, wxSOLID));
847 dc.SetBrush(*wxTRANSPARENT_BRUSH);
848
849 size_t n;
850 for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
851 {
852 wxCoord x = 20 + 150*(n%4),
853 y = 20 + 100*(n/4);
854
855 dc.DrawText(rasterOperations[n].name, x, y - 20);
856 dc.SetLogicalFunction(rasterOperations[n].rop);
857 dc.DrawRectangle(x, y, w, h);
858 dc.DrawLine(x, y, x + w, y + h);
859 dc.DrawLine(x + w, y, x, y + h);
860 }
861
862 // now some filled rectangles
863 dc.SetBrush(wxBrush(m_owner->m_colourForeground, wxSOLID));
864
865 for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
866 {
867 wxCoord x = 20 + 150*(n%4),
868 y = 500 + 100*(n/4);
869
870 dc.DrawText(rasterOperations[n].name, x, y - 20);
871 dc.SetLogicalFunction(rasterOperations[n].rop);
872 dc.DrawRectangle(x, y, w, h);
873 }
874 }
875
876 void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
877 {
878 wxPaintDC dc(this);
879 PrepareDC(dc);
880 m_owner->PrepareDC(dc);
881
882 dc.SetBackgroundMode( m_owner->m_backgroundMode );
883 if ( m_owner->m_backgroundBrush.Ok() )
884 dc.SetBackground( m_owner->m_backgroundBrush );
885 if ( m_owner->m_colourForeground.Ok() )
886 dc.SetTextForeground( m_owner->m_colourForeground );
887 if ( m_owner->m_colourBackground.Ok() )
888 dc.SetTextBackground( m_owner->m_colourBackground );
889
890 if ( m_owner->m_textureBackground) {
891 if ( ! m_owner->m_backgroundBrush.Ok() ) {
892 wxBrush b(wxColour(0,128,0), wxSOLID);
893 dc.SetBackground(b);
894 }
895 }
896
897 dc.Clear();
898
899 if ( m_owner->m_textureBackground) {
900 dc.SetPen(*wxMEDIUM_GREY_PEN);
901 for (int i=0; i<200; i++)
902 dc.DrawLine(0, i*10, i*10, 0);
903 }
904
905 switch ( m_show )
906 {
907 case Show_Default:
908 DrawDefault(dc);
909 break;
910
911 case Show_Text:
912 DrawText(dc);
913 break;
914
915 case Show_Lines:
916 DrawTestLines( 0, 100, 0, dc );
917 DrawTestLines( 0, 300, 1, dc );
918 DrawTestLines( 0, 500, 2, dc );
919 DrawTestLines( 0, 700, 6, dc );
920 break;
921
922 case Show_Polygons:
923 DrawTestPoly( 0, 100, dc, 0 );
924 DrawTestPoly( 33, 500, dc, 1 );
925 DrawTestPoly( 43, 1000, dc, 2 );
926 break;
927
928 case Show_Mask:
929 DrawImages(dc);
930 break;
931
932 case Show_Ops:
933 DrawWithLogicalOps(dc);
934 break;
935 }
936 }
937
938 void MyCanvas::OnMouseMove(wxMouseEvent &event)
939 {
940 wxClientDC dc(this);
941 PrepareDC(dc);
942 m_owner->PrepareDC(dc);
943
944 wxPoint pos = event.GetPosition();
945 long x = dc.DeviceToLogicalX( pos.x );
946 long y = dc.DeviceToLogicalY( pos.y );
947 wxString str;
948 str.Printf( "Current mouse position: %d,%d", (int)x, (int)y );
949 m_owner->SetStatusText( str );
950 }
951
952 // ----------------------------------------------------------------------------
953 // MyFrame
954 // ----------------------------------------------------------------------------
955
956 // the event tables connect the wxWindows events with the functions (event
957 // handlers) which process them. It can be also done at run-time, but for the
958 // simple menu events like this the static method is much simpler.
959 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
960 EVT_MENU (File_Quit, MyFrame::OnQuit)
961 EVT_MENU (File_About, MyFrame::OnAbout)
962
963 EVT_MENU_RANGE(MenuShow_First, MenuShow_Last, MyFrame::OnShow)
964
965 EVT_MENU_RANGE(MenuOption_First, MenuOption_Last, MyFrame::OnOption)
966 END_EVENT_TABLE()
967
968 // frame constructor
969 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
970 : wxFrame((wxFrame *)NULL, -1, title, pos, size)
971 {
972 // set the frame icon
973 SetIcon(wxICON(mondrian));
974
975 wxMenu *menuFile = new wxMenu;
976 menuFile->Append(File_ShowDefault, "&Default screen\tF1");
977 menuFile->Append(File_ShowText, "&Text screen\tF2");
978 menuFile->Append(File_ShowLines, "&Lines screen\tF3");
979 menuFile->Append(File_ShowPolygons, "&Polygons screen\tF4");
980 menuFile->Append(File_ShowMask, "wx&Mask screen\tF5");
981 menuFile->Append(File_ShowOps, "&ROP screen\tF6");
982 menuFile->AppendSeparator();
983 menuFile->Append(File_About, "&About...\tCtrl-A", "Show about dialog");
984 menuFile->AppendSeparator();
985 menuFile->Append(File_Quit, "E&xit\tAlt-X", "Quit this program");
986
987 wxMenu *menuMapMode = new wxMenu;
988 menuMapMode->Append( MapMode_Text, "&TEXT map mode" );
989 menuMapMode->Append( MapMode_Lometric, "&LOMETRIC map mode" );
990 menuMapMode->Append( MapMode_Twips, "T&WIPS map mode" );
991 menuMapMode->Append( MapMode_Points, "&POINTS map mode" );
992 menuMapMode->Append( MapMode_Metric, "&METRIC map mode" );
993
994 wxMenu *menuUserScale = new wxMenu;
995 menuUserScale->Append( UserScale_StretchHoriz, "Stretch horizontally\tCtrl-H" );
996 menuUserScale->Append( UserScale_ShrinkHoriz, "Shrink horizontally\tCtrl-G" );
997 menuUserScale->Append( UserScale_StretchVertic, "Stretch vertically\tCtrl-V" );
998 menuUserScale->Append( UserScale_ShrinkVertic, "Shrink vertically\tCtrl-W" );
999 menuUserScale->AppendSeparator();
1000 menuUserScale->Append( UserScale_Restore, "Restore to normal\tCtrl-0" );
1001
1002 wxMenu *menuAxis = new wxMenu;
1003 menuAxis->Append( AxisMirror_Horiz, "Mirror horizontally\tCtrl-M", "", TRUE );
1004 menuAxis->Append( AxisMirror_Vertic, "Mirror vertically\tCtrl-N", "", TRUE );
1005
1006 wxMenu *menuLogical = new wxMenu;
1007 menuLogical->Append( LogicalOrigin_MoveDown, "Move &down\tCtrl-D" );
1008 menuLogical->Append( LogicalOrigin_MoveUp, "Move &up\tCtrl-U" );
1009 menuLogical->Append( LogicalOrigin_MoveLeft, "Move &right\tCtrl-L" );
1010 menuLogical->Append( LogicalOrigin_MoveRight, "Move &left\tCtrl-R" );
1011
1012 wxMenu *menuColour = new wxMenu;
1013 menuColour->Append( Colour_TextForeground, "Text foreground..." );
1014 menuColour->Append( Colour_TextBackground, "Text background..." );
1015 menuColour->Append( Colour_Background, "Background colour..." );
1016 menuColour->Append( Colour_BackgroundMode, "Opaque/transparent\tCtrl-B", "", TRUE );
1017 menuColour->Append( Colour_TextureBackgound, "Draw textured background\tCtrl-T", "", TRUE);
1018
1019 // now append the freshly created menu to the menu bar...
1020 wxMenuBar *menuBar = new wxMenuBar;
1021 menuBar->Append(menuFile, "&File");
1022 menuBar->Append(menuMapMode, "&MapMode");
1023 menuBar->Append(menuUserScale, "&UserScale");
1024 menuBar->Append(menuAxis, "&Axis");
1025 menuBar->Append(menuLogical, "&LogicalOrigin");
1026 menuBar->Append(menuColour, "&Colours");
1027
1028 // ... and attach this menu bar to the frame
1029 SetMenuBar(menuBar);
1030
1031 // create a status bar just for fun (by default with 1 pane only)
1032 CreateStatusBar(2);
1033 SetStatusText("Welcome to wxWindows!");
1034
1035 m_mapMode = wxMM_TEXT;
1036 m_xUserScale = 1.0;
1037 m_yUserScale = 1.0;
1038 m_xLogicalOrigin = 0;
1039 m_yLogicalOrigin = 0;
1040 m_xAxisReversed =
1041 m_yAxisReversed = FALSE;
1042 m_backgroundMode = wxSOLID;
1043 m_colourForeground = *wxRED;
1044 m_colourBackground = *wxBLUE;
1045 m_textureBackground = FALSE;
1046
1047 m_canvas = new MyCanvas( this );
1048 m_canvas->SetScrollbars( 10, 10, 100, 240 );
1049 }
1050
1051 // event handlers
1052
1053 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1054 {
1055 // TRUE is to force the frame to close
1056 Close(TRUE);
1057 }
1058
1059 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1060 {
1061 wxString msg;
1062 msg.Printf( wxT("This is the about dialog of the drawing sample.\n")
1063 wxT("This sample tests various primitive drawing functions\n")
1064 wxT("without any tests to prevent flicker.\n")
1065 wxT("Copyright (c) Robert Roebling 1999")
1066 );
1067
1068 wxMessageBox(msg, "About Drawing", wxOK | wxICON_INFORMATION, this);
1069 }
1070
1071 void MyFrame::OnShow(wxCommandEvent& event)
1072 {
1073 m_canvas->Show((ScreenToShow)(event.GetInt() - MenuShow_First));
1074 }
1075
1076 void MyFrame::OnOption(wxCommandEvent& event)
1077 {
1078 switch (event.GetInt())
1079 {
1080 case MapMode_Text:
1081 m_mapMode = wxMM_TEXT;
1082 break;
1083 case MapMode_Lometric:
1084 m_mapMode = wxMM_LOMETRIC;
1085 break;
1086 case MapMode_Twips:
1087 m_mapMode = wxMM_TWIPS;
1088 break;
1089 case MapMode_Points:
1090 m_mapMode = wxMM_POINTS;
1091 break;
1092 case MapMode_Metric:
1093 m_mapMode = wxMM_METRIC;
1094 break;
1095
1096 case LogicalOrigin_MoveDown:
1097 m_yLogicalOrigin += 10;
1098 break;
1099 case LogicalOrigin_MoveUp:
1100 m_yLogicalOrigin -= 10;
1101 break;
1102 case LogicalOrigin_MoveLeft:
1103 m_xLogicalOrigin += 10;
1104 break;
1105 case LogicalOrigin_MoveRight:
1106 m_xLogicalOrigin -= 10;
1107 break;
1108
1109 case UserScale_StretchHoriz:
1110 m_xUserScale *= 1.10;
1111 break;
1112 case UserScale_ShrinkHoriz:
1113 m_xUserScale /= 1.10;
1114 break;
1115 case UserScale_StretchVertic:
1116 m_yUserScale *= 1.10;
1117 break;
1118 case UserScale_ShrinkVertic:
1119 m_yUserScale /= 1.10;
1120 break;
1121 case UserScale_Restore:
1122 m_xUserScale =
1123 m_yUserScale = 1.0;
1124 break;
1125
1126 case AxisMirror_Vertic:
1127 m_yAxisReversed = !m_yAxisReversed;
1128 break;
1129 case AxisMirror_Horiz:
1130 m_xAxisReversed = !m_xAxisReversed;
1131 break;
1132
1133 case Colour_TextForeground:
1134 m_colourForeground = SelectColour();
1135 break;
1136 case Colour_TextBackground:
1137 m_colourBackground = SelectColour();
1138 break;
1139 case Colour_Background:
1140 {
1141 wxColour col = SelectColour();
1142 if ( col.Ok() )
1143 {
1144 m_backgroundBrush.SetColour(col);
1145 }
1146 }
1147 break;
1148 case Colour_BackgroundMode:
1149 m_backgroundMode = m_backgroundMode == wxSOLID ? wxTRANSPARENT
1150 : wxSOLID;
1151 break;
1152
1153 case Colour_TextureBackgound:
1154 m_textureBackground = ! m_textureBackground;
1155 break;
1156
1157 default:
1158 // skip Refresh()
1159 return;
1160 }
1161
1162 m_canvas->Refresh();
1163 }
1164
1165 void MyFrame::PrepareDC(wxDC& dc)
1166 {
1167 dc.SetMapMode( m_mapMode );
1168 dc.SetUserScale( m_xUserScale, m_yUserScale );
1169 dc.SetLogicalOrigin( m_xLogicalOrigin, m_yLogicalOrigin );
1170 dc.SetAxisOrientation( !m_xAxisReversed, m_yAxisReversed );
1171 }
1172
1173 wxColour MyFrame::SelectColour()
1174 {
1175 wxColour col;
1176 wxColourData data;
1177 wxColourDialog dialog(this, &data);
1178
1179 if ( dialog.ShowModal() == wxID_OK )
1180 {
1181 col = dialog.GetColourData().GetColour();
1182 }
1183
1184 return col;
1185 }