added Show/HideWithEffect() and implemented them using AnimateWindow() for Win32
[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 // constants
45 // ----------------------------------------------------------------------------
46
47 // menu ids
48 enum
49 {
50 Show_Shaped,
51 Show_Transparent,
52
53 // must be consecutive and in the same order as wxShowEffect enum elements
54 Show_Effect_First,
55 Show_Effect_Roll = Show_Effect_First,
56 Show_Effect_Slide,
57 Show_Effect_Blend,
58 Show_Effect_Expand,
59 Show_Effect_Last = Show_Effect_Expand
60 };
61
62 // ----------------------------------------------------------------------------
63 // private classes
64 // ----------------------------------------------------------------------------
65
66 // Define a new application type, each program should derive a class from wxApp
67 class MyApp : public wxApp
68 {
69 public:
70 // override base class virtuals
71 // ----------------------------
72
73 // this one is called on application startup and is a good place for the app
74 // initialization (doing it here and not in the ctor allows to have an error
75 // return: if OnInit() returns false, the application terminates)
76 virtual bool OnInit();
77 };
78
79
80 // Main frame just contains the menu items invoking the other tests
81 class MainFrame : public wxFrame
82 {
83 public:
84 MainFrame();
85
86 private:
87 void OnShowShaped(wxCommandEvent& event);
88 void OnShowTransparent(wxCommandEvent& event);
89 void OnShowEffect(wxCommandEvent& event);
90
91 DECLARE_EVENT_TABLE()
92 };
93
94 // Define a new frame type: this is going to the frame showing the
95 // effect of wxFRAME_SHAPED
96 class ShapedFrame : public wxFrame
97 {
98 public:
99 // ctor(s)
100 ShapedFrame(wxFrame *parent);
101 void SetWindowShape();
102
103 // event handlers (these functions should _not_ be virtual)
104 void OnDoubleClick(wxMouseEvent& evt);
105 void OnLeftDown(wxMouseEvent& evt);
106 void OnLeftUp(wxMouseEvent& evt);
107 void OnMouseMove(wxMouseEvent& evt);
108 void OnExit(wxMouseEvent& evt);
109 void OnPaint(wxPaintEvent& evt);
110 void OnWindowCreate(wxWindowCreateEvent& 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 wxDirection dir = wxBOTTOM)
158 : wxFrame(parent, wxID_ANY,
159 wxString::Format("Frame shown with %s effect",
160 GetEffectName(effect)),
161 wxDefaultPosition, wxSize(450, 300)),
162 m_effect(effect),
163 m_timeout(timeout),
164 m_dir(dir)
165 {
166 new wxStaticText(this, wxID_ANY,
167 wxString::Format("Effect: %s", GetEffectName(effect)),
168 wxPoint(20, 20));
169 new wxStaticText(this, wxID_ANY,
170 wxString::Format("Timeout: %ums", m_timeout),
171 wxPoint(20, 60));
172
173 ShowWithEffect(m_effect, m_timeout, m_dir);
174
175 Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(EffectFrame::OnClose));
176 }
177
178 private:
179 static const char *GetEffectName(wxShowEffect effect)
180 {
181 static const char *names[] =
182 {
183 "roll", "slide", "fade", "expand",
184 };
185 wxCOMPILE_TIME_ASSERT( WXSIZEOF(names) == wxSHOW_EFFECT_MAX,
186 EffectNamesMismatch );
187
188 return names[effect];
189 }
190
191 void OnClose(wxCloseEvent& event)
192 {
193 HideWithEffect(m_effect, m_timeout, m_dir);
194
195 event.Skip();
196 }
197
198 wxShowEffect m_effect;
199 unsigned m_timeout;
200 wxDirection m_dir;
201 };
202
203 // ============================================================================
204 // implementation
205 // ============================================================================
206
207 // ----------------------------------------------------------------------------
208 // the application class
209 // ----------------------------------------------------------------------------
210
211 IMPLEMENT_APP(MyApp)
212
213 // `Main program' equivalent: the program execution "starts" here
214 bool MyApp::OnInit()
215 {
216 if ( !wxApp::OnInit() )
217 return false;
218
219 wxInitAllImageHandlers();
220
221 new MainFrame;
222
223 // success: wxApp::OnRun() will be called which will enter the main message
224 // loop and the application will run. If we returned false here, the
225 // application would exit immediately.
226 return true;
227 }
228
229 // ----------------------------------------------------------------------------
230 // main frame
231 // ----------------------------------------------------------------------------
232
233 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
234 EVT_MENU(Show_Shaped, MainFrame::OnShowShaped)
235 EVT_MENU(Show_Transparent, MainFrame::OnShowTransparent)
236 EVT_MENU_RANGE(Show_Effect_First, Show_Effect_Last, MainFrame::OnShowEffect)
237 END_EVENT_TABLE()
238
239 MainFrame::MainFrame()
240 : wxFrame(NULL, wxID_ANY, "wxWidgets Shaped Sample",
241 wxDefaultPosition, wxSize(200, 100))
242 {
243 wxMenuBar * const mbar = new wxMenuBar;
244 wxMenu * const menuFrames = new wxMenu;
245 menuFrames->Append(Show_Shaped, "Show &shaped window\tCtrl-S");
246 menuFrames->Append(Show_Transparent, "Show &transparent window\tCtrl-T");
247 menuFrames->AppendSeparator();
248 menuFrames->Append(Show_Effect_Roll, "Show &rolled effect\tCtrl-R");
249 menuFrames->Append(Show_Effect_Slide, "Show s&lide effect\tCtrl-L");
250 menuFrames->Append(Show_Effect_Blend, "Show &fade effect\tCtrl-F");
251 menuFrames->Append(Show_Effect_Expand, "Show &expand effect\tCtrl-E");
252 menuFrames->AppendSeparator();
253 menuFrames->Append(wxID_EXIT, "E&xit");
254
255 mbar->Append(menuFrames, "&Show");
256 SetMenuBar(mbar);
257
258 Show();
259 }
260
261 void MainFrame::OnShowShaped(wxCommandEvent& WXUNUSED(event))
262 {
263 ShapedFrame *shapedFrame = new ShapedFrame(this);
264 shapedFrame->Show(true);
265 }
266
267 void MainFrame::OnShowTransparent(wxCommandEvent& WXUNUSED(event))
268 {
269 SeeThroughFrame *seeThroughFrame = new SeeThroughFrame();
270 seeThroughFrame->Show(true);
271 }
272
273 void MainFrame::OnShowEffect(wxCommandEvent& event)
274 {
275 int effect = wxSHOW_EFFECT_ROLL + event.GetId() - Show_Effect_Roll;
276 new EffectFrame(this, wx_static_cast(wxShowEffect, effect));
277 }
278
279 // ----------------------------------------------------------------------------
280 // shaped frame
281 // ----------------------------------------------------------------------------
282
283 BEGIN_EVENT_TABLE(ShapedFrame, wxFrame)
284 EVT_LEFT_DCLICK(ShapedFrame::OnDoubleClick)
285 EVT_LEFT_DOWN(ShapedFrame::OnLeftDown)
286 EVT_LEFT_UP(ShapedFrame::OnLeftUp)
287 EVT_MOTION(ShapedFrame::OnMouseMove)
288 EVT_RIGHT_UP(ShapedFrame::OnExit)
289
290 EVT_PAINT(ShapedFrame::OnPaint)
291
292 #ifdef __WXGTK__
293 EVT_WINDOW_CREATE(ShapedFrame::OnWindowCreate)
294 #endif
295 END_EVENT_TABLE()
296
297
298 // frame constructor
299 ShapedFrame::ShapedFrame(wxFrame *parent)
300 : wxFrame(parent, wxID_ANY, wxEmptyString,
301 wxDefaultPosition, wxSize(100, 100),
302 0
303 | wxFRAME_SHAPED
304 | wxSIMPLE_BORDER
305 | wxFRAME_NO_TASKBAR
306 | wxSTAY_ON_TOP
307 )
308 {
309 m_hasShape = false;
310 m_bmp = wxBitmap(_T("star.png"), wxBITMAP_TYPE_PNG);
311 SetSize(wxSize(m_bmp.GetWidth(), m_bmp.GetHeight()));
312 SetToolTip(wxT("Right-click to close"));
313
314 #ifndef __WXGTK__
315 // On wxGTK we can't do this yet because the window hasn't been created
316 // yet so we wait until the EVT_WINDOW_CREATE event happens. On wxMSW and
317 // wxMac the window has been created at this point so we go ahead and set
318 // the shape now.
319 SetWindowShape();
320 #endif
321 }
322
323 void ShapedFrame::SetWindowShape()
324 {
325 wxRegion region(m_bmp, *wxWHITE);
326 m_hasShape = SetShape(region);
327 }
328
329 void ShapedFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
330 {
331 if (m_hasShape)
332 {
333 wxRegion region;
334 SetShape(region);
335 m_hasShape = false;
336 }
337 else
338 SetWindowShape();
339 }
340
341 void ShapedFrame::OnLeftDown(wxMouseEvent& evt)
342 {
343 CaptureMouse();
344 wxPoint pos = ClientToScreen(evt.GetPosition());
345 wxPoint origin = GetPosition();
346 int dx = pos.x - origin.x;
347 int dy = pos.y - origin.y;
348 m_delta = wxPoint(dx, dy);
349 }
350
351 void ShapedFrame::OnLeftUp(wxMouseEvent& WXUNUSED(evt))
352 {
353 if (HasCapture())
354 {
355 ReleaseMouse();
356 }
357 }
358
359 void ShapedFrame::OnMouseMove(wxMouseEvent& evt)
360 {
361 wxPoint pt = evt.GetPosition();
362 if (evt.Dragging() && evt.LeftIsDown())
363 {
364 wxPoint pos = ClientToScreen(pt);
365 Move(wxPoint(pos.x - m_delta.x, pos.y - m_delta.y));
366 }
367 }
368
369 void ShapedFrame::OnExit(wxMouseEvent& WXUNUSED(evt))
370 {
371 Close();
372 }
373
374 void ShapedFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
375 {
376 wxPaintDC dc(this);
377 dc.DrawBitmap(m_bmp, 0, 0, true);
378 }
379
380 void ShapedFrame::OnWindowCreate(wxWindowCreateEvent& WXUNUSED(evt))
381 {
382 SetWindowShape();
383 }
384
385 // ----------------------------------------------------------------------------
386 // see-through frame
387 // ----------------------------------------------------------------------------
388
389 BEGIN_EVENT_TABLE(SeeThroughFrame, wxFrame)
390 EVT_LEFT_DCLICK(SeeThroughFrame::OnDoubleClick)
391 EVT_PAINT(SeeThroughFrame::OnPaint)
392 END_EVENT_TABLE()
393
394 SeeThroughFrame::SeeThroughFrame()
395 : wxFrame(NULL, wxID_ANY, "Transparency test: double click here",
396 wxPoint(100, 30), wxSize(300, 300),
397 wxDEFAULT_FRAME_STYLE |
398 wxFULL_REPAINT_ON_RESIZE |
399 wxSTAY_ON_TOP),
400 m_currentState(STATE_SEETHROUGH)
401 {
402 SetBackgroundColour(wxColour(255, 255, 255, 255));
403 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
404 }
405
406 // Paints a grid of varying hue and alpha
407 void SeeThroughFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
408 {
409 wxPaintDC dc(this);
410 dc.SetPen(wxNullPen);
411
412 int xcount = 8;
413 int ycount = 8;
414
415 float xstep = 1. / xcount;
416 float ystep = 1. / ycount;
417
418 int width = GetClientSize().GetWidth();
419 int height = GetClientSize().GetHeight();
420
421 for ( float x = 0.; x < 1.; x += xstep )
422 {
423 for ( float y = 0.; y < 1.; y += ystep )
424 {
425 wxImage::RGBValue v = wxImage::HSVtoRGB(wxImage::HSVValue(x, 1., 1.));
426 dc.SetBrush(wxBrush(wxColour(v.red, v.green, v.blue,
427 (int)(255*(1. - y)))));
428 int x1 = (int)(x * width);
429 int y1 = (int)(y * height);
430 int x2 = (int)((x + xstep) * width);
431 int y2 = (int)((y + ystep) * height);
432 dc.DrawRectangle(x1, y1, x2 - x1, y2 - y1);
433 }
434 }
435 }
436
437 // Switches between colour and transparent background on doubleclick
438 void SeeThroughFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
439 {
440 m_currentState = (State)((m_currentState + 1) % STATE_MAX);
441
442 switch ( m_currentState )
443 {
444 case STATE_OPAQUE:
445 SetBackgroundStyle(wxBG_STYLE_COLOUR);
446 SetTransparent(255);
447 SetTitle("Opaque");
448 break;
449
450 case STATE_SEETHROUGH:
451 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
452 SetTransparent(255);
453 SetTitle("See through");
454 break;
455
456 case STATE_TRANSPARENT:
457 SetBackgroundStyle(wxBG_STYLE_COLOUR);
458 SetTransparent(128);
459 SetTitle("Semi-transparent");
460 break;
461
462 case STATE_MAX:
463 wxFAIL_MSG( "unreachable" );
464 }
465
466 Refresh();
467 }
468