introduce wxBG_STYLE_{ERASE,PAINT} and implement their documented semantics in wxGTK
[wxWidgets.git] / samples / erase / erase.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/erase/erase.cpp
3 // Purpose: Erase wxWidgets sample
4 // Author: Robert Roebling, Vadim Zeitlin
5 // Created: 04/01/98
6 // RCS-ID: $Id$
7 // Copyright: (c) 1998 Robert Roebling
8 // (c) 2009 Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers)
29 #ifndef WX_PRECOMP
30 #include "wx/wx.h"
31 #endif
32
33 #include "wx/dcbuffer.h"
34
35 // ----------------------------------------------------------------------------
36 // resources
37 // ----------------------------------------------------------------------------
38 // the application icon
39 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
40 #include "mondrian.xpm"
41 #endif
42
43 // ----------------------------------------------------------------------------
44 // private classes
45 // ----------------------------------------------------------------------------
46
47 class MyApp : public wxApp
48 {
49 public:
50 virtual bool OnInit();
51 };
52
53
54 class MyCanvas : public wxScrolledWindow
55 {
56 public:
57 MyCanvas(wxFrame *parent);
58
59 void UseBuffer(bool useBuffer) { m_useBuffer = useBuffer; Refresh(); }
60 bool UsesBuffer() const { return m_useBuffer; }
61
62 private:
63 void OnPaint( wxPaintEvent &event );
64 void OnChar( wxKeyEvent &event );
65 void OnEraseBackground( wxEraseEvent &event );
66
67 void DoPaint(wxDC& dc);
68
69
70 wxBitmap m_bitmap;
71 wxString m_text;
72
73 // use wxMemoryDC in OnPaint()?
74 bool m_useBuffer;
75
76
77 DECLARE_EVENT_TABLE()
78 };
79
80 class MyFrame : public wxFrame
81 {
82 public:
83 MyFrame();
84
85 private:
86 void OnUseBuffer(wxCommandEvent& event);
87 void OnChangeBgStyle(wxCommandEvent& event);
88 void OnQuit(wxCommandEvent& event);
89 void OnAbout(wxCommandEvent& event);
90
91 // we can only use double-buffering with wxBG_STYLE_PAINT
92 void OnUpdateUIUseBuffer(wxUpdateUIEvent& event)
93 {
94 event.Enable( m_canvas->GetBackgroundStyle() == wxBG_STYLE_PAINT );
95 }
96
97 void OnUpdateUIChangeBgStyle(wxUpdateUIEvent& event)
98 {
99 event.Enable( !m_canvas->UsesBuffer() );
100 }
101
102 MyCanvas *m_canvas;
103
104 DECLARE_EVENT_TABLE()
105 };
106
107
108 // ----------------------------------------------------------------------------
109 // constants
110 // ----------------------------------------------------------------------------
111
112 enum
113 {
114 // menu items
115 Erase_Menu_UseBuffer = 100,
116 Erase_Menu_BgStyleErase,
117 Erase_Menu_BgStyleSystem,
118 Erase_Menu_BgStylePaint,
119 Erase_Menu_Exit = wxID_EXIT,
120 Erase_Menu_About = wxID_ABOUT
121 };
122
123
124 // ----------------------------------------------------------------------------
125 // the application class
126 // ----------------------------------------------------------------------------
127
128 IMPLEMENT_APP(MyApp)
129
130 bool MyApp::OnInit()
131 {
132 if ( !wxApp::OnInit() )
133 return false;
134
135 MyFrame *frame = new MyFrame;
136
137 frame->Show(true);
138
139 return true;
140 }
141
142 // ----------------------------------------------------------------------------
143 // main frame
144 // ----------------------------------------------------------------------------
145
146 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
147 EVT_MENU(Erase_Menu_UseBuffer, MyFrame::OnUseBuffer)
148 EVT_MENU_RANGE(Erase_Menu_BgStyleErase, Erase_Menu_BgStylePaint,
149 MyFrame::OnChangeBgStyle)
150
151 EVT_MENU(Erase_Menu_Exit, MyFrame::OnQuit)
152 EVT_MENU(Erase_Menu_About, MyFrame::OnAbout)
153
154 EVT_UPDATE_UI(Erase_Menu_UseBuffer, MyFrame::OnUpdateUIUseBuffer)
155 EVT_UPDATE_UI_RANGE(Erase_Menu_BgStyleErase, Erase_Menu_BgStylePaint,
156 MyFrame::OnUpdateUIChangeBgStyle)
157 END_EVENT_TABLE()
158
159 // frame constructor
160 MyFrame::MyFrame()
161 : wxFrame(NULL, wxID_ANY, "Erase sample",
162 wxPoint(50, 50), wxSize(450, 340))
163 {
164 SetIcon(wxICON(mondrian));
165
166 wxMenu *menuFile = new wxMenu("", wxMENU_TEAROFF);
167 menuFile->AppendCheckItem(Erase_Menu_UseBuffer, "&Use memory DC\tCtrl-M");
168 menuFile->AppendSeparator();
169 menuFile->AppendRadioItem(Erase_Menu_BgStyleErase,
170 "Use wxBG_STYLE_&ERASE\tCtrl-E");
171 menuFile->AppendRadioItem(Erase_Menu_BgStyleSystem,
172 "Use wxBG_STYLE_&SYSTEM\tCtrl-S");
173 menuFile->AppendRadioItem(Erase_Menu_BgStylePaint,
174 "Use wxBG_STYLE_&PAINT\tCtrl-P");
175 menuFile->AppendSeparator();
176 menuFile->Append(Erase_Menu_Exit, "E&xit\tAlt-X", "Quit this program");
177
178
179 wxMenu *helpMenu = new wxMenu;
180 helpMenu->Append(Erase_Menu_About, "&About...\tCtrl-A", "Show about dialog");
181
182 wxMenuBar *menuBar = new wxMenuBar();
183 menuBar->Append(menuFile, "&File");
184 menuBar->Append(helpMenu, "&Help");
185
186 SetMenuBar(menuBar);
187
188 m_canvas = new MyCanvas( this );
189 }
190
191
192 void MyFrame::OnUseBuffer(wxCommandEvent& event)
193 {
194 m_canvas->UseBuffer(event.IsChecked());
195 }
196
197 void MyFrame::OnChangeBgStyle(wxCommandEvent& event)
198 {
199 int style = wxBG_STYLE_ERASE + event.GetId() - Erase_Menu_BgStyleErase;
200 m_canvas->SetBackgroundStyle(static_cast<wxBackgroundStyle>(style));
201
202 m_canvas->Refresh();
203 }
204
205 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
206 {
207 Close(true);
208 }
209
210 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
211 {
212 wxMessageBox
213 (
214 "This sample shows differences between different background styles "
215 "and how you may draw custom background.\n"
216 "\n"
217 "(c) 1998 Robert Roebling\n"
218 "(c) 2009 Vadim Zeitlin\n",
219 "About Erase Sample",
220 wxOK | wxICON_INFORMATION,
221 this
222 );
223 }
224
225
226 BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
227 EVT_PAINT(MyCanvas::OnPaint)
228 EVT_CHAR(MyCanvas::OnChar)
229 EVT_ERASE_BACKGROUND(MyCanvas::OnEraseBackground)
230 END_EVENT_TABLE()
231
232 MyCanvas::MyCanvas(wxFrame *parent)
233 : wxScrolledWindow(parent, wxID_ANY)
234 {
235 m_useBuffer = false;
236
237 SetScrollbars( 10, 10, 40, 100, 0, 0 );
238
239 m_bitmap = wxBitmap( wxICON(mondrian) );
240
241 new wxStaticBitmap( this, wxID_ANY, m_bitmap, wxPoint(80,20) );
242
243 SetFocusIgnoringChildren();
244 SetBackgroundColour(*wxBLUE);
245 }
246
247 void MyCanvas::OnChar( wxKeyEvent &event )
248 {
249 #if wxUSE_UNICODE
250 if (event.m_uniChar)
251 {
252 m_text += event.m_uniChar;
253 Refresh();
254 return;
255 }
256 #endif
257
258 // some test cases
259 switch (event.m_keyCode)
260 {
261 case WXK_UP: m_text += wxT( "<UP>" ); break;
262 case WXK_LEFT: m_text += wxT( "<LEFT>" ); break;
263 case WXK_RIGHT: m_text += wxT( "<RIGHT>" ); break;
264 case WXK_DOWN: m_text += wxT( "<DOWN>" ); break;
265 case WXK_RETURN: m_text += wxT( "<ENTER>" ); break;
266 default: m_text += (wxChar)event.m_keyCode; break;
267 }
268 }
269
270 void MyCanvas::DoPaint(wxDC& dc)
271 {
272 dc.SetBrush( *wxBLACK_BRUSH );
273 dc.DrawRectangle( 10,10,60,50 );
274
275 dc.DrawBitmap( m_bitmap, 20, 20, true );
276
277 dc.SetTextForeground(*wxWHITE);
278 dc.DrawText("This text is drawn from OnPaint", 65, 65);
279
280 wxString tmp;
281 tmp.Printf("Hit any key to display more text: %s", m_text);
282
283 int w,h;
284 dc.GetTextExtent( tmp, &w, &h );
285 dc.DrawRectangle( 65, 85, w, h );
286 dc.DrawText( tmp, 65, 85 );
287 }
288
289 void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) )
290 {
291 if ( m_useBuffer )
292 {
293 wxAutoBufferedPaintDC dc(this);
294 PrepareDC(dc);
295
296 DoPaint(dc);
297 }
298 else
299 {
300 wxPaintDC dc(this);
301 PrepareDC(dc);
302
303 DoPaint(dc);
304 }
305 }
306
307 void MyCanvas::OnEraseBackground( wxEraseEvent& event )
308 {
309 wxASSERT_MSG
310 (
311 GetBackgroundStyle() == wxBG_STYLE_ERASE,
312 "shouldn't be called unless background style is \"erase\""
313 );
314
315 wxDC& dc = *event.GetDC();
316 dc.SetPen(*wxGREEN_PEN);
317
318 PrepareDC( dc );
319
320 // clear any junk currently displayed
321 dc.Clear();
322
323 const wxSize size = GetClientSize();
324 for ( int x = 0; x < size.x; x += 15 )
325 {
326 dc.DrawLine(x, 0, x, size.y);
327 }
328
329 for ( int y = 0; y < size.y; y += 15 )
330 {
331 dc.DrawLine(0, y, size.x, y);
332 }
333
334 dc.SetTextForeground(*wxRED);
335 dc.SetBackgroundMode(wxSOLID);
336 dc.DrawText("This text is drawn from OnEraseBackground", 60, 160);
337 }
338