]> git.saurik.com Git - wxWidgets.git/blob - samples/shaped/shaped.cpp
Fix crash in wxFileConfig when deleting last entry of the root group.
[wxWidgets.git] / samples / shaped / shaped.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: shaped.cpp
3 // Purpose: Shaped Window sample
4 // Author: Robin Dunn
5 // Modified by:
6 // Created: 28-Mar-2003
7 // RCS-ID: $Id$
8 // Copyright: (c) Robin Dunn
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
28 #ifndef WX_PRECOMP
29 #include "wx/app.h"
30 #include "wx/log.h"
31 #include "wx/frame.h"
32 #include "wx/panel.h"
33 #include "wx/stattext.h"
34 #include "wx/menu.h"
35 #include "wx/layout.h"
36 #include "wx/msgdlg.h"
37 #include "wx/image.h"
38 #endif
39
40 #include "wx/dcclient.h"
41 #include "wx/graphics.h"
42 #include "wx/image.h"
43
44 #ifndef wxHAS_IMAGES_IN_RESOURCES
45 #include "../sample.xpm"
46 #endif
47
48 // ----------------------------------------------------------------------------
49 // constants
50 // ----------------------------------------------------------------------------
51
52 // menu ids
53 enum
54 {
55 Show_Shaped = 100,
56 Show_Transparent,
57
58 // must be consecutive and in the same order as wxShowEffect enum elements
59 Show_Effect_First,
60 Show_Effect_Roll = Show_Effect_First,
61 Show_Effect_Slide,
62 Show_Effect_Blend,
63 Show_Effect_Expand,
64 Show_Effect_Last = Show_Effect_Expand
65 };
66
67 // ----------------------------------------------------------------------------
68 // private classes
69 // ----------------------------------------------------------------------------
70
71 // Define a new application type, each program should derive a class from wxApp
72 class MyApp : public wxApp
73 {
74 public:
75 // override base class virtuals
76 // ----------------------------
77
78 // this one is called on application startup and is a good place for the app
79 // initialization (doing it here and not in the ctor allows to have an error
80 // return: if OnInit() returns false, the application terminates)
81 virtual bool OnInit();
82 };
83
84
85 // Main frame just contains the menu items invoking the other tests
86 class MainFrame : public wxFrame
87 {
88 public:
89 MainFrame();
90
91 private:
92 void OnShowShaped(wxCommandEvent& event);
93 void OnShowTransparent(wxCommandEvent& event);
94 void OnShowEffect(wxCommandEvent& event);
95 void OnExit(wxCommandEvent& event);
96
97 DECLARE_EVENT_TABLE()
98 };
99
100 // Define a new frame type: this is going to the frame showing the
101 // effect of wxFRAME_SHAPED
102 class ShapedFrame : public wxFrame
103 {
104 public:
105 // ctor(s)
106 ShapedFrame(wxFrame *parent);
107 void SetWindowShape();
108
109 // event handlers (these functions should _not_ be virtual)
110 void OnDoubleClick(wxMouseEvent& evt);
111 void OnLeftDown(wxMouseEvent& evt);
112 void OnLeftUp(wxMouseEvent& evt);
113 void OnMouseMove(wxMouseEvent& evt);
114 void OnExit(wxMouseEvent& evt);
115 void OnPaint(wxPaintEvent& evt);
116
117 private:
118 enum ShapeKind
119 {
120 Shape_None,
121 Shape_Star,
122 #if wxUSE_GRAPHICS_CONTEXT
123 Shape_Circle,
124 #endif // wxUSE_GRAPHICS_CONTEXT
125 Shape_Max
126 } m_shapeKind;
127
128 wxBitmap m_bmp;
129 wxPoint m_delta;
130
131 // any class wishing to process wxWidgets events must use this macro
132 DECLARE_EVENT_TABLE()
133 };
134
135 // Define a new frame type: this is going to the frame showing the
136 // effect of wxWindow::SetTransparent and of
137 // wxWindow::SetBackgroundStyle(wxBG_STYLE_TRANSPARENT)
138 class SeeThroughFrame : public wxFrame
139 {
140 public:
141 // ctor(s)
142 SeeThroughFrame();
143
144 // event handlers (these functions should _not_ be virtual)
145 void OnDoubleClick(wxMouseEvent& evt);
146 void OnPaint(wxPaintEvent& evt);
147
148 private:
149 enum State
150 {
151 STATE_SEETHROUGH,
152 STATE_TRANSPARENT,
153 STATE_OPAQUE,
154 STATE_MAX
155 };
156
157 State m_currentState;
158
159 // any class wishing to process wxWidgets events must use this macro
160 DECLARE_EVENT_TABLE()
161 };
162
163 class EffectFrame : public wxFrame
164 {
165 public:
166 EffectFrame(wxWindow *parent,
167 wxShowEffect effect,
168 // TODO: add menu command to the main frame to allow changing
169 // these parameters
170 unsigned timeout = 1000)
171 : wxFrame(parent, wxID_ANY,
172 wxString::Format("Frame shown with %s effect",
173 GetEffectName(effect)),
174 wxDefaultPosition, wxSize(450, 300)),
175 m_effect(effect),
176 m_timeout(timeout)
177 {
178 new wxStaticText(this, wxID_ANY,
179 wxString::Format("Effect: %s", GetEffectName(effect)),
180 wxPoint(20, 20));
181 new wxStaticText(this, wxID_ANY,
182 wxString::Format("Timeout: %ums", m_timeout),
183 wxPoint(20, 60));
184
185 ShowWithEffect(m_effect, m_timeout);
186
187 Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(EffectFrame::OnClose));
188 }
189
190 private:
191 static const char *GetEffectName(wxShowEffect effect)
192 {
193 static const char *names[] =
194 {
195 "none",
196 "roll to left",
197 "roll to right",
198 "roll to top",
199 "roll to bottom",
200 "slide to left",
201 "slide to right",
202 "slide to top",
203 "slide to bottom",
204 "fade",
205 "expand",
206 };
207 wxCOMPILE_TIME_ASSERT( WXSIZEOF(names) == wxSHOW_EFFECT_MAX,
208 EffectNamesMismatch );
209
210 return names[effect];
211 }
212
213 void OnClose(wxCloseEvent& event)
214 {
215 HideWithEffect(m_effect, m_timeout);
216
217 event.Skip();
218 }
219
220 wxShowEffect m_effect;
221 unsigned m_timeout;
222 };
223
224 // ============================================================================
225 // implementation
226 // ============================================================================
227
228 // ----------------------------------------------------------------------------
229 // the application class
230 // ----------------------------------------------------------------------------
231
232 IMPLEMENT_APP(MyApp)
233
234 // `Main program' equivalent: the program execution "starts" here
235 bool MyApp::OnInit()
236 {
237 if ( !wxApp::OnInit() )
238 return false;
239
240 wxInitAllImageHandlers();
241
242 new MainFrame;
243
244 // success: wxApp::OnRun() will be called which will enter the main message
245 // loop and the application will run. If we returned false here, the
246 // application would exit immediately.
247 return true;
248 }
249
250 // ----------------------------------------------------------------------------
251 // main frame
252 // ----------------------------------------------------------------------------
253
254 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
255 EVT_MENU(Show_Shaped, MainFrame::OnShowShaped)
256 EVT_MENU(Show_Transparent, MainFrame::OnShowTransparent)
257 EVT_MENU_RANGE(Show_Effect_First, Show_Effect_Last, MainFrame::OnShowEffect)
258 EVT_MENU(wxID_EXIT, MainFrame::OnExit)
259 END_EVENT_TABLE()
260
261 MainFrame::MainFrame()
262 : wxFrame(NULL, wxID_ANY, "wxWidgets Shaped Sample",
263 wxDefaultPosition, wxSize(200, 100))
264 {
265 SetIcon(wxICON(sample));
266
267 wxMenuBar * const mbar = new wxMenuBar;
268 wxMenu * const menuFrames = new wxMenu;
269 menuFrames->Append(Show_Shaped, "Show &shaped window\tCtrl-S");
270 menuFrames->Append(Show_Transparent, "Show &transparent window\tCtrl-T");
271 menuFrames->AppendSeparator();
272 menuFrames->Append(Show_Effect_Roll, "Show &rolled effect\tCtrl-R");
273 menuFrames->Append(Show_Effect_Slide, "Show s&lide effect\tCtrl-L");
274 menuFrames->Append(Show_Effect_Blend, "Show &fade effect\tCtrl-F");
275 menuFrames->Append(Show_Effect_Expand, "Show &expand effect\tCtrl-E");
276 menuFrames->AppendSeparator();
277 menuFrames->Append(wxID_EXIT, "E&xit");
278
279 mbar->Append(menuFrames, "&Show");
280 SetMenuBar(mbar);
281
282 Show();
283 }
284
285 void MainFrame::OnShowShaped(wxCommandEvent& WXUNUSED(event))
286 {
287 ShapedFrame *shapedFrame = new ShapedFrame(this);
288 shapedFrame->Show(true);
289 }
290
291 void MainFrame::OnShowTransparent(wxCommandEvent& WXUNUSED(event))
292 {
293 SeeThroughFrame *seeThroughFrame = new SeeThroughFrame();
294 seeThroughFrame->Show(true);
295 }
296
297 void MainFrame::OnShowEffect(wxCommandEvent& event)
298 {
299 int effect = event.GetId();
300 static wxDirection direction = wxLEFT;
301 direction = (wxDirection)(((int)direction)<< 1);
302 if ( direction > wxDOWN )
303 direction = wxLEFT ;
304
305 wxShowEffect eff;
306 switch ( effect )
307 {
308 case Show_Effect_Roll:
309 switch ( direction )
310 {
311 case wxLEFT:
312 eff = wxSHOW_EFFECT_ROLL_TO_LEFT;
313 break;
314 case wxRIGHT:
315 eff = wxSHOW_EFFECT_ROLL_TO_RIGHT;
316 break;
317 case wxTOP:
318 eff = wxSHOW_EFFECT_ROLL_TO_TOP;
319 break;
320 case wxBOTTOM:
321 eff = wxSHOW_EFFECT_ROLL_TO_BOTTOM;
322 break;
323 default:
324 wxFAIL_MSG( "invalid direction" );
325 return;
326 }
327 break;
328 case Show_Effect_Slide:
329 switch ( direction )
330 {
331 case wxLEFT:
332 eff = wxSHOW_EFFECT_SLIDE_TO_LEFT;
333 break;
334 case wxRIGHT:
335 eff = wxSHOW_EFFECT_SLIDE_TO_RIGHT;
336 break;
337 case wxTOP:
338 eff = wxSHOW_EFFECT_SLIDE_TO_TOP;
339 break;
340 case wxBOTTOM:
341 eff = wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
342 break;
343 default:
344 wxFAIL_MSG( "invalid direction" );
345 return;
346 }
347 break;
348
349 case Show_Effect_Blend:
350 eff = wxSHOW_EFFECT_BLEND;
351 break;
352
353 case Show_Effect_Expand:
354 eff = wxSHOW_EFFECT_EXPAND;
355 break;
356
357 default:
358 wxFAIL_MSG( "invalid effect" );
359 return;
360 }
361
362 new EffectFrame(this, eff, 1000);
363 }
364
365 void MainFrame::OnExit(wxCommandEvent& WXUNUSED(event))
366 {
367 Close();
368 }
369
370 // ----------------------------------------------------------------------------
371 // shaped frame
372 // ----------------------------------------------------------------------------
373
374 BEGIN_EVENT_TABLE(ShapedFrame, wxFrame)
375 EVT_LEFT_DCLICK(ShapedFrame::OnDoubleClick)
376 EVT_LEFT_DOWN(ShapedFrame::OnLeftDown)
377 EVT_LEFT_UP(ShapedFrame::OnLeftUp)
378 EVT_MOTION(ShapedFrame::OnMouseMove)
379 EVT_RIGHT_UP(ShapedFrame::OnExit)
380 EVT_PAINT(ShapedFrame::OnPaint)
381 END_EVENT_TABLE()
382
383
384 // frame constructor
385 ShapedFrame::ShapedFrame(wxFrame *parent)
386 : wxFrame(parent, wxID_ANY, wxEmptyString,
387 wxDefaultPosition, wxSize(100, 100),
388 0
389 | wxFRAME_SHAPED
390 | wxSIMPLE_BORDER
391 | wxFRAME_NO_TASKBAR
392 | wxSTAY_ON_TOP
393 )
394 {
395 m_shapeKind = Shape_None;
396 m_bmp = wxBitmap(wxT("star.png"), wxBITMAP_TYPE_PNG);
397 SetSize(wxSize(m_bmp.GetWidth(), m_bmp.GetHeight()));
398 SetToolTip(wxT("Right-click to close, double click to cycle shape"));
399 SetWindowShape();
400 }
401
402 void ShapedFrame::SetWindowShape()
403 {
404 switch ( m_shapeKind )
405 {
406 case Shape_None:
407 SetShape(wxRegion());
408 break;
409
410 case Shape_Star:
411 SetShape(wxRegion(m_bmp, *wxWHITE));
412 break;
413
414 #if wxUSE_GRAPHICS_CONTEXT
415 case Shape_Circle:
416 {
417 wxGraphicsPath
418 path = wxGraphicsRenderer::GetDefaultRenderer()->CreatePath();
419 path.AddCircle(m_bmp.GetWidth()/2, m_bmp.GetHeight()/2, 30);
420 SetShape(path);
421 }
422 break;
423 #endif // wxUSE_GRAPHICS_CONTEXT
424
425 case Shape_Max:
426 wxFAIL_MSG( "invalid shape kind" );
427 break;
428 }
429 }
430
431 void ShapedFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
432 {
433 m_shapeKind = static_cast<ShapeKind>((m_shapeKind + 1) % Shape_Max);
434 SetWindowShape();
435 }
436
437 void ShapedFrame::OnLeftDown(wxMouseEvent& evt)
438 {
439 CaptureMouse();
440 wxPoint pos = ClientToScreen(evt.GetPosition());
441 wxPoint origin = GetPosition();
442 int dx = pos.x - origin.x;
443 int dy = pos.y - origin.y;
444 m_delta = wxPoint(dx, dy);
445 }
446
447 void ShapedFrame::OnLeftUp(wxMouseEvent& WXUNUSED(evt))
448 {
449 if (HasCapture())
450 {
451 ReleaseMouse();
452 }
453 }
454
455 void ShapedFrame::OnMouseMove(wxMouseEvent& evt)
456 {
457 wxPoint pt = evt.GetPosition();
458 if (evt.Dragging() && evt.LeftIsDown())
459 {
460 wxPoint pos = ClientToScreen(pt);
461 Move(wxPoint(pos.x - m_delta.x, pos.y - m_delta.y));
462 }
463 }
464
465 void ShapedFrame::OnExit(wxMouseEvent& WXUNUSED(evt))
466 {
467 Close();
468 }
469
470 void ShapedFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
471 {
472 wxPaintDC dc(this);
473 dc.DrawBitmap(m_bmp, 0, 0, true);
474 }
475
476 // ----------------------------------------------------------------------------
477 // see-through frame
478 // ----------------------------------------------------------------------------
479
480 BEGIN_EVENT_TABLE(SeeThroughFrame, wxFrame)
481 EVT_LEFT_DCLICK(SeeThroughFrame::OnDoubleClick)
482 EVT_PAINT(SeeThroughFrame::OnPaint)
483 END_EVENT_TABLE()
484
485 SeeThroughFrame::SeeThroughFrame()
486 : wxFrame(NULL, wxID_ANY, "Transparency test: double click here",
487 wxPoint(100, 30), wxSize(300, 300),
488 wxDEFAULT_FRAME_STYLE |
489 wxFULL_REPAINT_ON_RESIZE |
490 wxSTAY_ON_TOP),
491 m_currentState(STATE_SEETHROUGH)
492 {
493 SetBackgroundColour(wxColour(255, 255, 255, 255));
494 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
495 }
496
497 // Paints a grid of varying hue and alpha
498 void SeeThroughFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
499 {
500 wxPaintDC dc(this);
501 dc.SetPen(wxNullPen);
502
503 int xcount = 8;
504 int ycount = 8;
505
506 float xstep = 1. / xcount;
507 float ystep = 1. / ycount;
508
509 int width = GetClientSize().GetWidth();
510 int height = GetClientSize().GetHeight();
511
512 for ( float x = 0.; x < 1.; x += xstep )
513 {
514 for ( float y = 0.; y < 1.; y += ystep )
515 {
516 wxImage::RGBValue v = wxImage::HSVtoRGB(wxImage::HSVValue(x, 1., 1.));
517 dc.SetBrush(wxBrush(wxColour(v.red, v.green, v.blue,
518 (int)(255*(1. - y)))));
519 int x1 = (int)(x * width);
520 int y1 = (int)(y * height);
521 int x2 = (int)((x + xstep) * width);
522 int y2 = (int)((y + ystep) * height);
523 dc.DrawRectangle(x1, y1, x2 - x1, y2 - y1);
524 }
525 }
526 }
527
528 // Switches between colour and transparent background on doubleclick
529 void SeeThroughFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
530 {
531 m_currentState = (State)((m_currentState + 1) % STATE_MAX);
532
533 switch ( m_currentState )
534 {
535 case STATE_OPAQUE:
536 SetBackgroundStyle(wxBG_STYLE_COLOUR);
537 SetTransparent(255);
538 SetTitle("Opaque");
539 break;
540
541 case STATE_SEETHROUGH:
542 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
543 SetTransparent(255);
544 SetTitle("See through");
545 break;
546
547 case STATE_TRANSPARENT:
548 SetBackgroundStyle(wxBG_STYLE_COLOUR);
549 SetTransparent(128);
550 SetTitle("Semi-transparent");
551 break;
552
553 case STATE_MAX:
554 wxFAIL_MSG( "unreachable" );
555 }
556
557 Refresh();
558 }
559