]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/nonownedwnd.cpp
Fix stc doxygen warnings and regen stc files.
[wxWidgets.git] / src / gtk / nonownedwnd.cpp
CommitLineData
a82afab3
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/nonownedwnd.cpp
3// Purpose: wxGTK implementation of wxNonOwnedWindow.
4// Author: Vadim Zeitlin
5// Created: 2011-10-12
a82afab3
VZ
6// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
7// Licence: wxWindows licence
8///////////////////////////////////////////////////////////////////////////////
9
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
18// for compilers that support precompilation, includes "wx.h".
19#include "wx/wxprec.h"
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
25#ifndef WX_PRECOMP
9dc44eff 26 #include "wx/nonownedwnd.h"
52bac4d8
VZ
27 #include "wx/dcclient.h"
28 #include "wx/dcmemory.h"
bb8823c9 29 #include "wx/region.h"
a82afab3
VZ
30#endif // WX_PRECOMP
31
46ea442c
VZ
32#include "wx/graphics.h"
33
9dc44eff
PC
34#include <gtk/gtk.h>
35#include "wx/gtk/private/gtk2-compat.h"
36
46ea442c
VZ
37// ----------------------------------------------------------------------------
38// wxNonOwnedWindowShapeImpl: base class for region and path-based classes.
39// ----------------------------------------------------------------------------
40
41// This class provides behaviour common to both region and path-based
42// implementations and defines SetShape() method and virtual dtor that can be
43// called by wxNonOwnedWindow when it's realized leaving just the
44// implementation of DoSetShape() to the derived classes.
45class wxNonOwnedWindowShapeImpl : public wxEvtHandler
a82afab3 46{
46ea442c
VZ
47public:
48 wxNonOwnedWindowShapeImpl(wxWindow* win) : m_win(win)
49 {
50 }
51
52 virtual ~wxNonOwnedWindowShapeImpl() { }
53
54 bool SetShape()
55 {
56 if ( m_win->m_wxwindow )
57 SetShapeIfNonNull(gtk_widget_get_window(m_win->m_wxwindow));
58
59 return SetShapeIfNonNull(gtk_widget_get_window(m_win->m_widget));
60 }
61
62 // Must be overridden to indicate if the data object must stay around or if
63 // it can be deleted once SetShape() was called.
64 virtual bool CanBeDeleted() const = 0;
65
66protected:
67 wxWindow* const m_win;
a82afab3 68
46ea442c
VZ
69private:
70 // SetShape to the given GDK window by calling DoSetShape() if it's non-NULL.
71 bool SetShapeIfNonNull(GdkWindow* window)
72 {
73 return window && DoSetShape(window);
74 }
75
76 // SetShape the shape to the given GDK window which can be either the window
77 // of m_widget or m_wxwindow of the wxWindow we're used with.
78 virtual bool DoSetShape(GdkWindow* window) = 0;
79
80 wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindowShapeImpl);
81};
82
83// Version not using any custom shape.
84class wxNonOwnedWindowShapeImplNone : public wxNonOwnedWindowShapeImpl
a82afab3 85{
46ea442c
VZ
86public:
87 wxNonOwnedWindowShapeImplNone(wxWindow* win) :
88 wxNonOwnedWindowShapeImpl(win)
a82afab3 89 {
a82afab3 90 }
a82afab3 91
46ea442c 92 virtual bool CanBeDeleted() const { return true; }
a82afab3 93
46ea442c
VZ
94private:
95 virtual bool DoSetShape(GdkWindow* window)
96 {
9dc44eff 97 gdk_window_shape_combine_region(window, NULL, 0, 0);
46ea442c
VZ
98
99 return true;
100 }
101};
102
103// Version using simple wxRegion.
104class wxNonOwnedWindowShapeImplRegion : public wxNonOwnedWindowShapeImpl
105{
106public:
107 wxNonOwnedWindowShapeImplRegion(wxWindow* win, const wxRegion& region) :
108 wxNonOwnedWindowShapeImpl(win),
109 m_region(region)
110 {
111 }
112
113 virtual bool CanBeDeleted() const { return true; }
114
115private:
116 virtual bool DoSetShape(GdkWindow* window)
117 {
118 gdk_window_shape_combine_region(window, m_region.GetRegion(), 0, 0);
119
120 return true;
121 }
122
123 wxRegion m_region;
124};
125
126#if wxUSE_GRAPHICS_CONTEXT
127
128// Version using more complex wxGraphicsPath.
129class wxNonOwnedWindowShapeImplPath : public wxNonOwnedWindowShapeImpl
130{
131public:
132 wxNonOwnedWindowShapeImplPath(wxWindow* win, const wxGraphicsPath& path) :
133 wxNonOwnedWindowShapeImpl(win),
134 m_path(path),
135 m_mask(CreateShapeBitmap(path), *wxBLACK)
136 {
137
138 m_win->Connect
139 (
140 wxEVT_PAINT,
141 wxPaintEventHandler(wxNonOwnedWindowShapeImplPath::OnPaint),
142 NULL,
143 this
144 );
145 }
146
147 virtual ~wxNonOwnedWindowShapeImplPath()
148 {
149 m_win->Disconnect
150 (
151 wxEVT_PAINT,
152 wxPaintEventHandler(wxNonOwnedWindowShapeImplPath::OnPaint),
153 NULL,
154 this
155 );
156 }
157
158 // Currently we always return false from here, if drawing the border
159 // becomes optional, we could return true if we don't need to draw it.
160 virtual bool CanBeDeleted() const { return false; }
161
162private:
163 wxBitmap CreateShapeBitmap(const wxGraphicsPath& path)
164 {
165 // Draw the path on a bitmap to get the mask we need.
166 //
167 // Notice that using monochrome bitmap here doesn't work because of an
168 // apparent wxGraphicsContext bug in wxGTK, so use a bitmap of screen
169 // depth even if this is wasteful.
170 wxBitmap bmp(m_win->GetSize());
171
172 wxMemoryDC dc(bmp);
173
174 dc.SetBackground(*wxBLACK);
175 dc.Clear();
176
9dc44eff
PC
177#ifdef __WXGTK3__
178 wxGraphicsContext* context = dc.GetGraphicsContext();
179#else
46ea442c 180 wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
9dc44eff 181#endif
46ea442c
VZ
182 context->SetBrush(*wxWHITE);
183 context->FillPath(path);
184
185 return bmp;
186 }
187
188 virtual bool DoSetShape(GdkWindow *window)
189 {
5ca21fe7 190 if (!m_mask)
46ea442c
VZ
191 return false;
192
9dc44eff 193#ifdef __WXGTK3__
5ca21fe7 194 cairo_region_t* region = gdk_cairo_region_create_from_surface(m_mask);
9dc44eff
PC
195 gdk_window_shape_combine_region(window, region, 0, 0);
196 cairo_region_destroy(region);
197#else
5ca21fe7 198 gdk_window_shape_combine_mask(window, m_mask, 0, 0);
9dc44eff 199#endif
46ea442c
VZ
200
201 return true;
202 }
203
204 // Draw a shaped window border.
205 void OnPaint(wxPaintEvent& event)
206 {
207 event.Skip();
208
209 wxPaintDC dc(m_win);
9dc44eff
PC
210#ifdef __WXGTK3__
211 wxGraphicsContext* context = dc.GetGraphicsContext();
212#else
46ea442c 213 wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
9dc44eff 214#endif
46ea442c
VZ
215 context->SetPen(wxPen(*wxLIGHT_GREY, 2));
216 context->StrokePath(m_path);
217 }
218
219 wxGraphicsPath m_path;
220 wxMask m_mask;
221};
222
223#endif // wxUSE_GRAPHICS_CONTEXT
a82afab3
VZ
224
225// ============================================================================
226// wxNonOwnedWindow implementation
227// ============================================================================
228
46ea442c
VZ
229wxNonOwnedWindow::~wxNonOwnedWindow()
230{
231 delete m_shapeImpl;
232}
233
a82afab3
VZ
234void wxNonOwnedWindow::GTKHandleRealized()
235{
236 wxNonOwnedWindowBase::GTKHandleRealized();
237
46ea442c
VZ
238 if ( m_shapeImpl )
239 {
240 m_shapeImpl->SetShape();
241
242 // We can destroy wxNonOwnedWindowShapeImplRegion immediately but need
243 // to keep wxNonOwnedWindowShapeImplPath around as it draws the border
244 // on every repaint.
245 if ( m_shapeImpl->CanBeDeleted() )
246 {
247 delete m_shapeImpl;
248 m_shapeImpl = NULL;
249 }
250 }
a82afab3
VZ
251}
252
46ea442c 253bool wxNonOwnedWindow::DoClearShape()
a82afab3 254{
46ea442c
VZ
255 if ( !m_shapeImpl )
256 {
257 // Nothing to do, we don't have any custom shape.
258 return true;
259 }
a82afab3
VZ
260
261 if ( gtk_widget_get_realized(m_widget) )
262 {
46ea442c
VZ
263 // Reset the existing shape immediately.
264 wxNonOwnedWindowShapeImplNone data(this);
265 data.SetShape();
266 }
267 //else: just do nothing, deleting m_shapeImpl is enough to ensure that we
268 // don't set the custom shape later when we're realized.
a82afab3 269
46ea442c
VZ
270 delete m_shapeImpl;
271 m_shapeImpl = NULL;
272
273 return true;
274}
275
276bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region)
277{
278 // In any case get rid of the old data.
279 delete m_shapeImpl;
280 m_shapeImpl = NULL;
281
282 if ( gtk_widget_get_realized(m_widget) )
283 {
284 // We can avoid an unnecessary heap allocation and just set the shape
285 // immediately.
286 wxNonOwnedWindowShapeImplRegion data(this, region);
287 return data.SetShape();
a82afab3 288 }
46ea442c 289 else // Create an object that will set shape when we're realized.
a82afab3 290 {
46ea442c 291 m_shapeImpl = new wxNonOwnedWindowShapeImplRegion(this, region);
a82afab3 292
46ea442c
VZ
293 // In general we don't know whether we are going to succeed or not, so
294 // be optimistic.
a82afab3
VZ
295 return true;
296 }
297}
46ea442c
VZ
298
299#if wxUSE_GRAPHICS_CONTEXT
300
301bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path)
302{
303 // The logic here is simpler than above because we always create
304 // wxNonOwnedWindowShapeImplPath on the heap as we must keep it around,
305 // even if we're already realized
306
307 delete m_shapeImpl;
308 m_shapeImpl = new wxNonOwnedWindowShapeImplPath(this, path);
309
310 if ( gtk_widget_get_realized(m_widget) )
311 {
312 return m_shapeImpl->SetShape();
313 }
314 //else: will be done later from GTKHandleRealized().
315
316 return true;
317}
318
319#endif // wxUSE_GRAPHICS_CONTEXT