avoiding menu id = 0 , adding rotating through direction each time an effect is called
[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 = 100,
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 static wxDirection direction = wxLEFT;
277 direction = (wxDirection)(((int)direction)<< 1);
278 if ( direction > wxDOWN )
279 direction = wxLEFT ;
280 new EffectFrame(this, wx_static_cast(wxShowEffect, effect),1000,direction);
281 }
282
283 // ----------------------------------------------------------------------------
284 // shaped frame
285 // ----------------------------------------------------------------------------
286
287 BEGIN_EVENT_TABLE(ShapedFrame, wxFrame)
288 EVT_LEFT_DCLICK(ShapedFrame::OnDoubleClick)
289 EVT_LEFT_DOWN(ShapedFrame::OnLeftDown)
290 EVT_LEFT_UP(ShapedFrame::OnLeftUp)
291 EVT_MOTION(ShapedFrame::OnMouseMove)
292 EVT_RIGHT_UP(ShapedFrame::OnExit)
293
294 EVT_PAINT(ShapedFrame::OnPaint)
295
296 #ifdef __WXGTK__
297 EVT_WINDOW_CREATE(ShapedFrame::OnWindowCreate)
298 #endif
299 END_EVENT_TABLE()
300
301
302 // frame constructor
303 ShapedFrame::ShapedFrame(wxFrame *parent)
304 : wxFrame(parent, wxID_ANY, wxEmptyString,
305 wxDefaultPosition, wxSize(100, 100),
306 0
307 | wxFRAME_SHAPED
308 | wxSIMPLE_BORDER
309 | wxFRAME_NO_TASKBAR
310 | wxSTAY_ON_TOP
311 )
312 {
313 m_hasShape = false;
314 m_bmp = wxBitmap(_T("star.png"), wxBITMAP_TYPE_PNG);
315 SetSize(wxSize(m_bmp.GetWidth(), m_bmp.GetHeight()));
316 SetToolTip(wxT("Right-click to close"));
317
318 #ifndef __WXGTK__
319 // On wxGTK we can't do this yet because the window hasn't been created
320 // yet so we wait until the EVT_WINDOW_CREATE event happens. On wxMSW and
321 // wxMac the window has been created at this point so we go ahead and set
322 // the shape now.
323 SetWindowShape();
324 #endif
325 }
326
327 void ShapedFrame::SetWindowShape()
328 {
329 wxRegion region(m_bmp, *wxWHITE);
330 m_hasShape = SetShape(region);
331 }
332
333 void ShapedFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
334 {
335 if (m_hasShape)
336 {
337 wxRegion region;
338 SetShape(region);
339 m_hasShape = false;
340 }
341 else
342 SetWindowShape();
343 }
344
345 void ShapedFrame::OnLeftDown(wxMouseEvent& evt)
346 {
347 CaptureMouse();
348 wxPoint pos = ClientToScreen(evt.GetPosition());
349 wxPoint origin = GetPosition();
350 int dx = pos.x - origin.x;
351 int dy = pos.y - origin.y;
352 m_delta = wxPoint(dx, dy);
353 }
354
355 void ShapedFrame::OnLeftUp(wxMouseEvent& WXUNUSED(evt))
356 {
357 if (HasCapture())
358 {
359 ReleaseMouse();
360 }
361 }
362
363 void ShapedFrame::OnMouseMove(wxMouseEvent& evt)
364 {
365 wxPoint pt = evt.GetPosition();
366 if (evt.Dragging() && evt.LeftIsDown())
367 {
368 wxPoint pos = ClientToScreen(pt);
369 Move(wxPoint(pos.x - m_delta.x, pos.y - m_delta.y));
370 }
371 }
372
373 void ShapedFrame::OnExit(wxMouseEvent& WXUNUSED(evt))
374 {
375 Close();
376 }
377
378 void ShapedFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
379 {
380 wxPaintDC dc(this);
381 dc.DrawBitmap(m_bmp, 0, 0, true);
382 }
383
384 void ShapedFrame::OnWindowCreate(wxWindowCreateEvent& WXUNUSED(evt))
385 {
386 SetWindowShape();
387 }
388
389 // ----------------------------------------------------------------------------
390 // see-through frame
391 // ----------------------------------------------------------------------------
392
393 BEGIN_EVENT_TABLE(SeeThroughFrame, wxFrame)
394 EVT_LEFT_DCLICK(SeeThroughFrame::OnDoubleClick)
395 EVT_PAINT(SeeThroughFrame::OnPaint)
396 END_EVENT_TABLE()
397
398 SeeThroughFrame::SeeThroughFrame()
399 : wxFrame(NULL, wxID_ANY, "Transparency test: double click here",
400 wxPoint(100, 30), wxSize(300, 300),
401 wxDEFAULT_FRAME_STYLE |
402 wxFULL_REPAINT_ON_RESIZE |
403 wxSTAY_ON_TOP),
404 m_currentState(STATE_SEETHROUGH)
405 {
406 SetBackgroundColour(wxColour(255, 255, 255, 255));
407 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
408 }
409
410 // Paints a grid of varying hue and alpha
411 void SeeThroughFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
412 {
413 wxPaintDC dc(this);
414 dc.SetPen(wxNullPen);
415
416 int xcount = 8;
417 int ycount = 8;
418
419 float xstep = 1. / xcount;
420 float ystep = 1. / ycount;
421
422 int width = GetClientSize().GetWidth();
423 int height = GetClientSize().GetHeight();
424
425 for ( float x = 0.; x < 1.; x += xstep )
426 {
427 for ( float y = 0.; y < 1.; y += ystep )
428 {
429 wxImage::RGBValue v = wxImage::HSVtoRGB(wxImage::HSVValue(x, 1., 1.));
430 dc.SetBrush(wxBrush(wxColour(v.red, v.green, v.blue,
431 (int)(255*(1. - y)))));
432 int x1 = (int)(x * width);
433 int y1 = (int)(y * height);
434 int x2 = (int)((x + xstep) * width);
435 int y2 = (int)((y + ystep) * height);
436 dc.DrawRectangle(x1, y1, x2 - x1, y2 - y1);
437 }
438 }
439 }
440
441 // Switches between colour and transparent background on doubleclick
442 void SeeThroughFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
443 {
444 m_currentState = (State)((m_currentState + 1) % STATE_MAX);
445
446 switch ( m_currentState )
447 {
448 case STATE_OPAQUE:
449 SetBackgroundStyle(wxBG_STYLE_COLOUR);
450 SetTransparent(255);
451 SetTitle("Opaque");
452 break;
453
454 case STATE_SEETHROUGH:
455 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
456 SetTransparent(255);
457 SetTitle("See through");
458 break;
459
460 case STATE_TRANSPARENT:
461 SetBackgroundStyle(wxBG_STYLE_COLOUR);
462 SetTransparent(128);
463 SetTitle("Semi-transparent");
464 break;
465
466 case STATE_MAX:
467 wxFAIL_MSG( "unreachable" );
468 }
469
470 Refresh();
471 }
472