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