#endif
#include "wx/dcclient.h"
+#include "wx/graphics.h"
#include "wx/image.h"
+#ifndef wxHAS_IMAGES_IN_RESOURCES
+ #include "../sample.xpm"
+#endif
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// menu ids
+enum
+{
+ Show_Shaped = 100,
+ Show_Transparent,
+
+ // must be consecutive and in the same order as wxShowEffect enum elements
+ Show_Effect_First,
+ Show_Effect_Roll = Show_Effect_First,
+ Show_Effect_Slide,
+ Show_Effect_Blend,
+ Show_Effect_Expand,
+ Show_Effect_Last = Show_Effect_Expand
+};
+
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
};
-// Define a new frame type: this is going to be our main frame
+// Main frame just contains the menu items invoking the other tests
+class MainFrame : public wxFrame
+{
+public:
+ MainFrame();
+
+private:
+ void OnShowShaped(wxCommandEvent& event);
+ void OnShowTransparent(wxCommandEvent& event);
+ void OnShowEffect(wxCommandEvent& event);
+ void OnExit(wxCommandEvent& event);
+
+ DECLARE_EVENT_TABLE()
+};
+
+// Define a new frame type: this is going to the frame showing the
+// effect of wxFRAME_SHAPED
class ShapedFrame : public wxFrame
{
public:
// ctor(s)
- ShapedFrame();
+ ShapedFrame(wxFrame *parent);
void SetWindowShape();
// event handlers (these functions should _not_ be virtual)
void OnMouseMove(wxMouseEvent& evt);
void OnExit(wxMouseEvent& evt);
void OnPaint(wxPaintEvent& evt);
- void OnWindowCreate(wxWindowCreateEvent& evt);
private:
- bool m_hasShape;
+ enum ShapeKind
+ {
+ Shape_None,
+ Shape_Star,
+#if wxUSE_GRAPHICS_CONTEXT
+ Shape_Circle,
+#endif // wxUSE_GRAPHICS_CONTEXT
+ Shape_Max
+ } m_shapeKind;
+
wxBitmap m_bmp;
wxPoint m_delta;
DECLARE_EVENT_TABLE()
};
+// Define a new frame type: this is going to the frame showing the
+// effect of wxWindow::SetTransparent and of
+// wxWindow::SetBackgroundStyle(wxBG_STYLE_TRANSPARENT)
+class SeeThroughFrame : public wxFrame
+{
+public:
+ // ctor(s)
+ SeeThroughFrame();
-// ----------------------------------------------------------------------------
-// event tables and other macros for wxWidgets
-// ----------------------------------------------------------------------------
+ // event handlers (these functions should _not_ be virtual)
+ void OnDoubleClick(wxMouseEvent& evt);
+ void OnPaint(wxPaintEvent& evt);
-// the event tables connect the wxWidgets events with the functions (event
-// handlers) which process them. It can be also done at run-time, but for the
-// simple menu events like this the static method is much simpler.
-BEGIN_EVENT_TABLE(ShapedFrame, wxFrame)
- EVT_LEFT_DCLICK(ShapedFrame::OnDoubleClick)
- EVT_LEFT_DOWN(ShapedFrame::OnLeftDown)
- EVT_LEFT_UP(ShapedFrame::OnLeftUp)
- EVT_MOTION(ShapedFrame::OnMouseMove)
- EVT_RIGHT_UP(ShapedFrame::OnExit)
+private:
+ enum State
+ {
+ STATE_SEETHROUGH,
+ STATE_TRANSPARENT,
+ STATE_OPAQUE,
+ STATE_MAX
+ };
- EVT_PAINT(ShapedFrame::OnPaint)
+ State m_currentState;
-#ifdef __WXGTK__
- EVT_WINDOW_CREATE(ShapedFrame::OnWindowCreate)
-#endif
-END_EVENT_TABLE()
+ // any class wishing to process wxWidgets events must use this macro
+ DECLARE_EVENT_TABLE()
+};
+
+class EffectFrame : public wxFrame
+{
+public:
+ EffectFrame(wxWindow *parent,
+ wxShowEffect effect,
+ // TODO: add menu command to the main frame to allow changing
+ // these parameters
+ unsigned timeout = 1000)
+ : wxFrame(parent, wxID_ANY,
+ wxString::Format("Frame shown with %s effect",
+ GetEffectName(effect)),
+ wxDefaultPosition, wxSize(450, 300)),
+ m_effect(effect),
+ m_timeout(timeout)
+ {
+ new wxStaticText(this, wxID_ANY,
+ wxString::Format("Effect: %s", GetEffectName(effect)),
+ wxPoint(20, 20));
+ new wxStaticText(this, wxID_ANY,
+ wxString::Format("Timeout: %ums", m_timeout),
+ wxPoint(20, 60));
+ ShowWithEffect(m_effect, m_timeout);
-// Create a new application object: this macro will allow wxWidgets to create
-// the application object during program execution (it's better than using a
-// static object for many reasons) and also declares the accessor function
-// wxGetApp() which will return the reference of the right type (i.e. MyApp and
-// not wxApp)
-IMPLEMENT_APP(MyApp)
+ Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(EffectFrame::OnClose));
+ }
+
+private:
+ static const char *GetEffectName(wxShowEffect effect)
+ {
+ static const char *names[] =
+ {
+ "none",
+ "roll to left",
+ "roll to right",
+ "roll to top",
+ "roll to bottom",
+ "slide to left",
+ "slide to right",
+ "slide to top",
+ "slide to bottom",
+ "fade",
+ "expand",
+ };
+ wxCOMPILE_TIME_ASSERT( WXSIZEOF(names) == wxSHOW_EFFECT_MAX,
+ EffectNamesMismatch );
+
+ return names[effect];
+ }
+
+ void OnClose(wxCloseEvent& event)
+ {
+ HideWithEffect(m_effect, m_timeout);
+
+ event.Skip();
+ }
+
+ wxShowEffect m_effect;
+ unsigned m_timeout;
+};
// ============================================================================
// implementation
// the application class
// ----------------------------------------------------------------------------
+IMPLEMENT_APP(MyApp)
+
// `Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
+ if ( !wxApp::OnInit() )
+ return false;
+
wxInitAllImageHandlers();
- // Create the main application window
- ShapedFrame *frame = new ShapedFrame();
- frame->Show(true);
- SetTopWindow(frame);
+ new MainFrame;
// success: wxApp::OnRun() will be called which will enter the main message
// loop and the application will run. If we returned false here, the
// main frame
// ----------------------------------------------------------------------------
+BEGIN_EVENT_TABLE(MainFrame, wxFrame)
+ EVT_MENU(Show_Shaped, MainFrame::OnShowShaped)
+ EVT_MENU(Show_Transparent, MainFrame::OnShowTransparent)
+ EVT_MENU_RANGE(Show_Effect_First, Show_Effect_Last, MainFrame::OnShowEffect)
+ EVT_MENU(wxID_EXIT, MainFrame::OnExit)
+END_EVENT_TABLE()
+
+MainFrame::MainFrame()
+ : wxFrame(NULL, wxID_ANY, "wxWidgets Shaped Sample",
+ wxDefaultPosition, wxSize(200, 100))
+{
+ SetIcon(wxICON(sample));
+
+ wxMenuBar * const mbar = new wxMenuBar;
+ wxMenu * const menuFrames = new wxMenu;
+ menuFrames->Append(Show_Shaped, "Show &shaped window\tCtrl-S");
+ menuFrames->Append(Show_Transparent, "Show &transparent window\tCtrl-T");
+ menuFrames->AppendSeparator();
+ menuFrames->Append(Show_Effect_Roll, "Show &rolled effect\tCtrl-R");
+ menuFrames->Append(Show_Effect_Slide, "Show s&lide effect\tCtrl-L");
+ menuFrames->Append(Show_Effect_Blend, "Show &fade effect\tCtrl-F");
+ menuFrames->Append(Show_Effect_Expand, "Show &expand effect\tCtrl-E");
+ menuFrames->AppendSeparator();
+ menuFrames->Append(wxID_EXIT, "E&xit");
+
+ mbar->Append(menuFrames, "&Show");
+ SetMenuBar(mbar);
+
+ Show();
+}
+
+void MainFrame::OnShowShaped(wxCommandEvent& WXUNUSED(event))
+{
+ ShapedFrame *shapedFrame = new ShapedFrame(this);
+ shapedFrame->Show(true);
+}
+
+void MainFrame::OnShowTransparent(wxCommandEvent& WXUNUSED(event))
+{
+ SeeThroughFrame *seeThroughFrame = new SeeThroughFrame();
+ seeThroughFrame->Show(true);
+}
+
+void MainFrame::OnShowEffect(wxCommandEvent& event)
+{
+ int effect = event.GetId();
+ static wxDirection direction = wxLEFT;
+ direction = (wxDirection)(((int)direction)<< 1);
+ if ( direction > wxDOWN )
+ direction = wxLEFT ;
+
+ wxShowEffect eff;
+ switch ( effect )
+ {
+ case Show_Effect_Roll:
+ switch ( direction )
+ {
+ case wxLEFT:
+ eff = wxSHOW_EFFECT_ROLL_TO_LEFT;
+ break;
+ case wxRIGHT:
+ eff = wxSHOW_EFFECT_ROLL_TO_RIGHT;
+ break;
+ case wxTOP:
+ eff = wxSHOW_EFFECT_ROLL_TO_TOP;
+ break;
+ case wxBOTTOM:
+ eff = wxSHOW_EFFECT_ROLL_TO_BOTTOM;
+ break;
+ default:
+ wxFAIL_MSG( "invalid direction" );
+ return;
+ }
+ break;
+ case Show_Effect_Slide:
+ switch ( direction )
+ {
+ case wxLEFT:
+ eff = wxSHOW_EFFECT_SLIDE_TO_LEFT;
+ break;
+ case wxRIGHT:
+ eff = wxSHOW_EFFECT_SLIDE_TO_RIGHT;
+ break;
+ case wxTOP:
+ eff = wxSHOW_EFFECT_SLIDE_TO_TOP;
+ break;
+ case wxBOTTOM:
+ eff = wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
+ break;
+ default:
+ wxFAIL_MSG( "invalid direction" );
+ return;
+ }
+ break;
+
+ case Show_Effect_Blend:
+ eff = wxSHOW_EFFECT_BLEND;
+ break;
+
+ case Show_Effect_Expand:
+ eff = wxSHOW_EFFECT_EXPAND;
+ break;
+
+ default:
+ wxFAIL_MSG( "invalid effect" );
+ return;
+ }
+
+ new EffectFrame(this, eff, 1000);
+}
+
+void MainFrame::OnExit(wxCommandEvent& WXUNUSED(event))
+{
+ Close();
+}
+
+// ----------------------------------------------------------------------------
+// shaped frame
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(ShapedFrame, wxFrame)
+ EVT_LEFT_DCLICK(ShapedFrame::OnDoubleClick)
+ EVT_LEFT_DOWN(ShapedFrame::OnLeftDown)
+ EVT_LEFT_UP(ShapedFrame::OnLeftUp)
+ EVT_MOTION(ShapedFrame::OnMouseMove)
+ EVT_RIGHT_UP(ShapedFrame::OnExit)
+ EVT_PAINT(ShapedFrame::OnPaint)
+END_EVENT_TABLE()
+
+
// frame constructor
-ShapedFrame::ShapedFrame()
- : wxFrame((wxFrame *)NULL, wxID_ANY, wxEmptyString,
- wxDefaultPosition, wxSize(100, 100), //wxDefaultSize,
+ShapedFrame::ShapedFrame(wxFrame *parent)
+ : wxFrame(parent, wxID_ANY, wxEmptyString,
+ wxDefaultPosition, wxSize(100, 100),
0
| wxFRAME_SHAPED
| wxSIMPLE_BORDER
| wxSTAY_ON_TOP
)
{
- m_hasShape = false;
- m_bmp = wxBitmap(_T("star.png"), wxBITMAP_TYPE_PNG);
+ m_shapeKind = Shape_None;
+ m_bmp = wxBitmap(wxT("star.png"), wxBITMAP_TYPE_PNG);
SetSize(wxSize(m_bmp.GetWidth(), m_bmp.GetHeight()));
- SetToolTip(wxT("Right-click to exit"));
-
-#ifndef __WXGTK__
- // On wxGTK we can't do this yet because the window hasn't been created
- // yet so we wait until the EVT_WINDOW_CREATE event happens. On wxMSW and
- // wxMac the window has been created at this point so we go ahead and set
- // the shape now.
+ SetToolTip(wxT("Right-click to close, double click to cycle shape"));
SetWindowShape();
-#endif
}
void ShapedFrame::SetWindowShape()
{
- wxRegion region(m_bmp, *wxWHITE);
- m_hasShape = SetShape(region);
+ switch ( m_shapeKind )
+ {
+ case Shape_None:
+ SetShape(wxRegion());
+ break;
+
+ case Shape_Star:
+ SetShape(wxRegion(m_bmp, *wxWHITE));
+ break;
+
+#if wxUSE_GRAPHICS_CONTEXT
+ case Shape_Circle:
+ {
+ wxGraphicsPath
+ path = wxGraphicsRenderer::GetDefaultRenderer()->CreatePath();
+ path.AddCircle(m_bmp.GetWidth()/2, m_bmp.GetHeight()/2, 30);
+ SetShape(path);
+ }
+ break;
+#endif // wxUSE_GRAPHICS_CONTEXT
+
+ case Shape_Max:
+ wxFAIL_MSG( "invalid shape kind" );
+ break;
+ }
}
void ShapedFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
{
- if (m_hasShape)
- {
- wxRegion region;
- SetShape(region);
- m_hasShape = false;
- }
- else
- SetWindowShape();
+ m_shapeKind = static_cast<ShapeKind>((m_shapeKind + 1) % Shape_Max);
+ SetWindowShape();
}
void ShapedFrame::OnLeftDown(wxMouseEvent& evt)
{
CaptureMouse();
- //printf("Mouse captured\n");
wxPoint pos = ClientToScreen(evt.GetPosition());
wxPoint origin = GetPosition();
int dx = pos.x - origin.x;
if (HasCapture())
{
ReleaseMouse();
- //printf("Mouse released\n");
}
}
void ShapedFrame::OnMouseMove(wxMouseEvent& evt)
{
wxPoint pt = evt.GetPosition();
- //printf("x:%d y:%d\n", pt.x, pt.y);
if (evt.Dragging() && evt.LeftIsDown())
{
wxPoint pos = ClientToScreen(pt);
dc.DrawBitmap(m_bmp, 0, 0, true);
}
-void ShapedFrame::OnWindowCreate(wxWindowCreateEvent& WXUNUSED(evt))
+// ----------------------------------------------------------------------------
+// see-through frame
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(SeeThroughFrame, wxFrame)
+ EVT_LEFT_DCLICK(SeeThroughFrame::OnDoubleClick)
+ EVT_PAINT(SeeThroughFrame::OnPaint)
+END_EVENT_TABLE()
+
+SeeThroughFrame::SeeThroughFrame()
+ : wxFrame(NULL, wxID_ANY, "Transparency test: double click here",
+ wxPoint(100, 30), wxSize(300, 300),
+ wxDEFAULT_FRAME_STYLE |
+ wxFULL_REPAINT_ON_RESIZE |
+ wxSTAY_ON_TOP),
+ m_currentState(STATE_SEETHROUGH)
{
- SetWindowShape();
+ SetBackgroundColour(wxColour(255, 255, 255, 255));
+ SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
+}
+
+// Paints a grid of varying hue and alpha
+void SeeThroughFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
+{
+ wxPaintDC dc(this);
+ dc.SetPen(wxNullPen);
+
+ int xcount = 8;
+ int ycount = 8;
+
+ float xstep = 1. / xcount;
+ float ystep = 1. / ycount;
+
+ int width = GetClientSize().GetWidth();
+ int height = GetClientSize().GetHeight();
+
+ for ( float x = 0.; x < 1.; x += xstep )
+ {
+ for ( float y = 0.; y < 1.; y += ystep )
+ {
+ wxImage::RGBValue v = wxImage::HSVtoRGB(wxImage::HSVValue(x, 1., 1.));
+ dc.SetBrush(wxBrush(wxColour(v.red, v.green, v.blue,
+ (int)(255*(1. - y)))));
+ int x1 = (int)(x * width);
+ int y1 = (int)(y * height);
+ int x2 = (int)((x + xstep) * width);
+ int y2 = (int)((y + ystep) * height);
+ dc.DrawRectangle(x1, y1, x2 - x1, y2 - y1);
+ }
+ }
+}
+
+// Switches between colour and transparent background on doubleclick
+void SeeThroughFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
+{
+ m_currentState = (State)((m_currentState + 1) % STATE_MAX);
+
+ switch ( m_currentState )
+ {
+ case STATE_OPAQUE:
+ SetBackgroundStyle(wxBG_STYLE_COLOUR);
+ SetTransparent(255);
+ SetTitle("Opaque");
+ break;
+
+ case STATE_SEETHROUGH:
+ SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
+ SetTransparent(255);
+ SetTitle("See through");
+ break;
+
+ case STATE_TRANSPARENT:
+ SetBackgroundStyle(wxBG_STYLE_COLOUR);
+ SetTransparent(128);
+ SetTitle("Semi-transparent");
+ break;
+
+ case STATE_MAX:
+ wxFAIL_MSG( "unreachable" );
+ }
+
+ Refresh();
}