]> git.saurik.com Git - wxWidgets.git/blame - samples/shaped/shaped.cpp
fixing infinite recursion for rotated text, introduced in cleanup r57915
[wxWidgets.git] / samples / shaped / shaped.cpp
CommitLineData
1542ea39
RD
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
1542ea39
RD
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"
6a7e6411 37 #include "wx/image.h"
1542ea39
RD
38#endif
39
40#include "wx/dcclient.h"
3b3ca9be 41#include "wx/image.h"
1542ea39 42
eed04c99 43
dd1406f5
VZ
44// ----------------------------------------------------------------------------
45// constants
46// ----------------------------------------------------------------------------
47
48// menu ids
49enum
50{
fb81ee21 51 Show_Shaped = 100,
376d7d97
VZ
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
dd1406f5
VZ
61};
62
1542ea39
RD
63// ----------------------------------------------------------------------------
64// private classes
65// ----------------------------------------------------------------------------
66
67// Define a new application type, each program should derive a class from wxApp
68class MyApp : public wxApp
69{
70public:
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
dd1406f5
VZ
81// Main frame just contains the menu items invoking the other tests
82class MainFrame : public wxFrame
83{
84public:
85 MainFrame();
86
87private:
88 void OnShowShaped(wxCommandEvent& event);
89 void OnShowTransparent(wxCommandEvent& event);
376d7d97 90 void OnShowEffect(wxCommandEvent& event);
dd1406f5
VZ
91
92 DECLARE_EVENT_TABLE()
93};
94
4488a1d3
VZ
95// Define a new frame type: this is going to the frame showing the
96// effect of wxFRAME_SHAPED
1542ea39
RD
97class ShapedFrame : public wxFrame
98{
99public:
100 // ctor(s)
4488a1d3 101 ShapedFrame(wxFrame *parent);
1542ea39
RD
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);
1542ea39
RD
111
112private:
113 bool m_hasShape;
114 wxBitmap m_bmp;
115 wxPoint m_delta;
116
be5a51fb 117 // any class wishing to process wxWidgets events must use this macro
1542ea39
RD
118 DECLARE_EVENT_TABLE()
119};
120
4488a1d3
VZ
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)
124class SeeThroughFrame : public wxFrame
125{
126public:
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);
4488a1d3
VZ
133
134private:
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
376d7d97
VZ
149class EffectFrame : public wxFrame
150{
151public:
152 EffectFrame(wxWindow *parent,
153 wxShowEffect effect,
154 // TODO: add menu command to the main frame to allow changing
155 // these parameters
eed04c99 156 unsigned timeout = 1000)
376d7d97
VZ
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),
eed04c99 162 m_timeout(timeout)
376d7d97
VZ
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
eed04c99 171 ShowWithEffect(m_effect, m_timeout);
376d7d97
VZ
172
173 Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(EffectFrame::OnClose));
174 }
175
176private:
177 static const char *GetEffectName(wxShowEffect effect)
178 {
179 static const char *names[] =
180 {
eed04c99
VS
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",
376d7d97
VZ
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 {
eed04c99 200 HideWithEffect(m_effect, m_timeout);
376d7d97
VZ
201
202 event.Skip();
203 }
204
205 wxShowEffect m_effect;
206 unsigned m_timeout;
376d7d97
VZ
207};
208
1542ea39
RD
209// ============================================================================
210// implementation
211// ============================================================================
212
213// ----------------------------------------------------------------------------
214// the application class
215// ----------------------------------------------------------------------------
216
dd1406f5
VZ
217IMPLEMENT_APP(MyApp)
218
1542ea39
RD
219// `Main program' equivalent: the program execution "starts" here
220bool MyApp::OnInit()
221{
45e6e6f8
VZ
222 if ( !wxApp::OnInit() )
223 return false;
224
1542ea39
RD
225 wxInitAllImageHandlers();
226
dd1406f5 227 new MainFrame;
1542ea39
RD
228
229 // success: wxApp::OnRun() will be called which will enter the main message
b62ca03d 230 // loop and the application will run. If we returned false here, the
1542ea39 231 // application would exit immediately.
b62ca03d 232 return true;
1542ea39
RD
233}
234
dd1406f5
VZ
235// ----------------------------------------------------------------------------
236// main frame
237// ----------------------------------------------------------------------------
238
239BEGIN_EVENT_TABLE(MainFrame, wxFrame)
240 EVT_MENU(Show_Shaped, MainFrame::OnShowShaped)
241 EVT_MENU(Show_Transparent, MainFrame::OnShowTransparent)
376d7d97 242 EVT_MENU_RANGE(Show_Effect_First, Show_Effect_Last, MainFrame::OnShowEffect)
dd1406f5
VZ
243END_EVENT_TABLE()
244
245MainFrame::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();
376d7d97
VZ
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();
dd1406f5
VZ
259 menuFrames->Append(wxID_EXIT, "E&xit");
260
261 mbar->Append(menuFrames, "&Show");
262 SetMenuBar(mbar);
263
264 Show();
265}
266
267void MainFrame::OnShowShaped(wxCommandEvent& WXUNUSED(event))
268{
269 ShapedFrame *shapedFrame = new ShapedFrame(this);
270 shapedFrame->Show(true);
271}
272
273void MainFrame::OnShowTransparent(wxCommandEvent& WXUNUSED(event))
274{
275 SeeThroughFrame *seeThroughFrame = new SeeThroughFrame();
276 seeThroughFrame->Show(true);
277}
278
376d7d97
VZ
279void MainFrame::OnShowEffect(wxCommandEvent& event)
280{
eed04c99 281 int effect = event.GetId();
fb81ee21
SC
282 static wxDirection direction = wxLEFT;
283 direction = (wxDirection)(((int)direction)<< 1);
284 if ( direction > wxDOWN )
285 direction = wxLEFT ;
eed04c99
VS
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);
376d7d97
VZ
345}
346
1542ea39 347// ----------------------------------------------------------------------------
4488a1d3 348// shaped frame
1542ea39
RD
349// ----------------------------------------------------------------------------
350
dd1406f5
VZ
351BEGIN_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)
dd1406f5 357 EVT_PAINT(ShapedFrame::OnPaint)
dd1406f5
VZ
358END_EVENT_TABLE()
359
360
1542ea39 361// frame constructor
4488a1d3
VZ
362ShapedFrame::ShapedFrame(wxFrame *parent)
363 : wxFrame(parent, wxID_ANY, wxEmptyString,
dd1406f5 364 wxDefaultPosition, wxSize(100, 100),
6a7e6411
RD
365 0
366 | wxFRAME_SHAPED
367 | wxSIMPLE_BORDER
368 | wxFRAME_NO_TASKBAR
369 | wxSTAY_ON_TOP
370 )
1542ea39 371{
b62ca03d 372 m_hasShape = false;
7df07b10 373 m_bmp = wxBitmap(_T("star.png"), wxBITMAP_TYPE_PNG);
1542ea39 374 SetSize(wxSize(m_bmp.GetWidth(), m_bmp.GetHeight()));
dd1406f5 375 SetToolTip(wxT("Right-click to close"));
1542ea39 376 SetWindowShape();
1542ea39
RD
377}
378
379void ShapedFrame::SetWindowShape()
380{
381 wxRegion region(m_bmp, *wxWHITE);
382 m_hasShape = SetShape(region);
383}
384
256b8649 385void ShapedFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
1542ea39
RD
386{
387 if (m_hasShape)
388 {
389 wxRegion region;
390 SetShape(region);
b62ca03d 391 m_hasShape = false;
1542ea39
RD
392 }
393 else
394 SetWindowShape();
395}
396
397void 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
256b8649 407void ShapedFrame::OnLeftUp(wxMouseEvent& WXUNUSED(evt))
1542ea39
RD
408{
409 if (HasCapture())
6a7e6411 410 {
1542ea39 411 ReleaseMouse();
256b8649 412 }
1542ea39
RD
413}
414
415void ShapedFrame::OnMouseMove(wxMouseEvent& evt)
416{
6a7e6411 417 wxPoint pt = evt.GetPosition();
1542ea39
RD
418 if (evt.Dragging() && evt.LeftIsDown())
419 {
6a7e6411 420 wxPoint pos = ClientToScreen(pt);
1542ea39
RD
421 Move(wxPoint(pos.x - m_delta.x, pos.y - m_delta.y));
422 }
423}
424
256b8649 425void ShapedFrame::OnExit(wxMouseEvent& WXUNUSED(evt))
1542ea39
RD
426{
427 Close();
428}
429
256b8649 430void ShapedFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
1542ea39
RD
431{
432 wxPaintDC dc(this);
b62ca03d 433 dc.DrawBitmap(m_bmp, 0, 0, true);
1542ea39
RD
434}
435
4488a1d3
VZ
436// ----------------------------------------------------------------------------
437// see-through frame
438// ----------------------------------------------------------------------------
439
dd1406f5
VZ
440BEGIN_EVENT_TABLE(SeeThroughFrame, wxFrame)
441 EVT_LEFT_DCLICK(SeeThroughFrame::OnDoubleClick)
442 EVT_PAINT(SeeThroughFrame::OnPaint)
443END_EVENT_TABLE()
444
4488a1d3
VZ
445SeeThroughFrame::SeeThroughFrame()
446 : wxFrame(NULL, wxID_ANY, "Transparency test: double click here",
447 wxPoint(100, 30), wxSize(300, 300),
dd1406f5
VZ
448 wxDEFAULT_FRAME_STYLE |
449 wxFULL_REPAINT_ON_RESIZE |
450 wxSTAY_ON_TOP),
4488a1d3
VZ
451 m_currentState(STATE_SEETHROUGH)
452{
453 SetBackgroundColour(wxColour(255, 255, 255, 255));
454 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
455}
456
4488a1d3
VZ
457// Paints a grid of varying hue and alpha
458void 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
489void 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