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