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