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