1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/toplvcmn.cpp
3 // Purpose: common (for all platforms) wxTopLevelWindow functions
4 // Author: Julian Smart, Vadim Zeitlin
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
20 #pragma implementation "toplevelbase.h"
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
31 #include "wx/toplevel.h"
32 #include "wx/dcclient.h"
35 #include "wx/evtloop.h"
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
41 BEGIN_EVENT_TABLE(wxTopLevelWindowBase
, wxWindow
)
42 EVT_CLOSE(wxTopLevelWindowBase::OnCloseWindow
)
43 EVT_SIZE(wxTopLevelWindowBase::OnSize
)
46 // ============================================================================
48 // ============================================================================
50 // FIXME: some platforms don't have wxTopLevelWindow yet
51 #ifdef wxTopLevelWindowNative
52 IMPLEMENT_DYNAMIC_CLASS(wxTopLevelWindow
, wxWindow
)
55 // ----------------------------------------------------------------------------
56 // construction/destruction
57 // ----------------------------------------------------------------------------
59 wxTopLevelWindowBase::wxTopLevelWindowBase()
63 wxTopLevelWindowBase::~wxTopLevelWindowBase()
65 // this destructor is required for Darwin
68 bool wxTopLevelWindowBase::Destroy()
70 // delayed destruction: the frame will be deleted during the next idle
72 if ( !wxPendingDelete
.Member(this) )
73 wxPendingDelete
.Append(this);
78 // ----------------------------------------------------------------------------
79 // wxTopLevelWindow size management: we exclude the areas taken by
80 // menu/status/toolbars from the client area, so the client area is what's
81 // really available for the frame contents
82 // ----------------------------------------------------------------------------
84 void wxTopLevelWindowBase::DoScreenToClient(int *x
, int *y
) const
86 wxWindow::DoScreenToClient(x
, y
);
88 // translate the wxWindow client coords to our client coords
89 wxPoint
pt(GetClientAreaOrigin());
96 void wxTopLevelWindowBase::DoClientToScreen(int *x
, int *y
) const
98 // our client area origin (0, 0) may be really something like (0, 30) for
99 // wxWindow if we have a toolbar, account for it before translating
100 wxPoint
pt(GetClientAreaOrigin());
106 wxWindow::DoClientToScreen(x
, y
);
110 // ----------------------------------------------------------------------------
112 // ----------------------------------------------------------------------------
114 // default resizing behaviour - if only ONE subwindow, resize to fill the
116 void wxTopLevelWindowBase::OnSize(wxSizeEvent
& WXUNUSED(event
))
118 // if we're using constraints - do use them
119 #if wxUSE_CONSTRAINTS
120 if ( GetAutoLayout() )
125 #endif // wxUSE_CONSTRAINTS
127 // do we have _exactly_ one child?
128 wxWindow
*child
= (wxWindow
*)NULL
;
129 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
131 node
= node
->GetNext() )
133 wxWindow
*win
= node
->GetData();
135 // exclude top level and managed windows (status bar isn't
136 // currently in the children list except under wxMac anyhow, but
137 // it makes no harm to test for it)
138 if ( !win
->IsTopLevel() && !IsOneOfBars(win
) )
145 return; // it's our second subwindow - nothing to do
152 // do we have any children at all?
155 // exactly one child - set it's size to fill the whole frame
156 int clientW
, clientH
;
157 DoGetClientSize(&clientW
, &clientH
);
159 // for whatever reasons, wxGTK wants to have a small offset - it
160 // probably looks better with it?
162 static const int ofs
= 1;
164 static const int ofs
= 0;
167 child
->SetSize(ofs
, ofs
, clientW
- 2*ofs
, clientH
- 2*ofs
);
169 UpdateInternalSize(child
, clientH
);
175 // The default implementation for the close window event.
176 void wxTopLevelWindowBase::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
181 bool wxTopLevelWindowBase::SendIconizeEvent(bool iconized
)
183 wxIconizeEvent
event(GetId(), iconized
);
184 event
.SetEventObject(this);
186 return GetEventHandler()->ProcessEvent(event
);
189 // ----------------------------------------------------------------------------
190 // interactive manipulation
191 // ----------------------------------------------------------------------------
193 #ifdef __WXUNIVERSAL__
195 #define wxINTERACTIVE_RESIZE_DIR \
196 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E | \
197 wxINTERACTIVE_RESIZE_S | wxINTERACTIVE_RESIZE_N)
199 struct wxInteractiveMoveData
201 wxTopLevelWindowBase
*m_window
;
202 wxEventLoop
*m_evtLoop
;
207 wxSize m_minSize
, m_maxSize
;
210 class wxInteractiveMoveHandler
: public wxEvtHandler
213 wxInteractiveMoveHandler(wxInteractiveMoveData
& data
) : m_data(data
) {}
216 DECLARE_EVENT_TABLE()
217 void OnMouseMove(wxMouseEvent
& event
);
218 void OnMouseDown(wxMouseEvent
& event
);
219 void OnMouseUp(wxMouseEvent
& event
);
220 void OnKeyDown(wxKeyEvent
& event
);
222 wxInteractiveMoveData
& m_data
;
225 BEGIN_EVENT_TABLE(wxInteractiveMoveHandler
, wxEvtHandler
)
226 EVT_MOTION(wxInteractiveMoveHandler::OnMouseMove
)
227 EVT_LEFT_DOWN(wxInteractiveMoveHandler::OnMouseDown
)
228 EVT_LEFT_UP(wxInteractiveMoveHandler::OnMouseUp
)
229 EVT_KEY_DOWN(wxInteractiveMoveHandler::OnKeyDown
)
233 static inline LINKAGEMODE
234 void wxApplyResize(wxInteractiveMoveData
& data
, const wxPoint
& diff
)
236 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_W
)
238 data
.m_rect
.x
+= diff
.x
;
239 data
.m_rect
.width
-= diff
.x
;
241 else if ( data
.m_flags
& wxINTERACTIVE_RESIZE_E
)
243 data
.m_rect
.width
+= diff
.x
;
245 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_N
)
247 data
.m_rect
.y
+= diff
.y
;
248 data
.m_rect
.height
-= diff
.y
;
250 else if ( data
.m_flags
& wxINTERACTIVE_RESIZE_S
)
252 data
.m_rect
.height
+= diff
.y
;
255 if ( data
.m_minSize
.x
!= -1 && data
.m_rect
.width
< data
.m_minSize
.x
)
257 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_W
)
258 data
.m_rect
.x
-= data
.m_minSize
.x
- data
.m_rect
.width
;
259 data
.m_rect
.width
= data
.m_minSize
.x
;
261 if ( data
.m_maxSize
.x
!= -1 && data
.m_rect
.width
> data
.m_maxSize
.x
)
263 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_W
)
264 data
.m_rect
.x
-= data
.m_minSize
.x
- data
.m_rect
.width
;
265 data
.m_rect
.width
= data
.m_maxSize
.x
;
267 if ( data
.m_minSize
.y
!= -1 && data
.m_rect
.height
< data
.m_minSize
.y
)
269 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_N
)
270 data
.m_rect
.y
-= data
.m_minSize
.y
- data
.m_rect
.height
;
271 data
.m_rect
.height
= data
.m_minSize
.y
;
273 if ( data
.m_maxSize
.y
!= -1 && data
.m_rect
.height
> data
.m_maxSize
.y
)
275 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_N
)
276 data
.m_rect
.y
-= data
.m_minSize
.y
- data
.m_rect
.height
;
277 data
.m_rect
.height
= data
.m_maxSize
.y
;
281 void wxInteractiveMoveHandler::OnMouseMove(wxMouseEvent
& event
)
283 if ( m_data
.m_flags
& wxINTERACTIVE_WAIT_FOR_INPUT
)
286 else if ( m_data
.m_flags
& wxINTERACTIVE_MOVE
)
288 wxPoint diff
= wxGetMousePosition() - m_data
.m_pos
;
289 m_data
.m_rect
= m_data
.m_rectOrig
;
290 m_data
.m_rect
.Offset(diff
);
291 m_data
.m_window
->Move(m_data
.m_rect
.GetPosition());
294 else if ( m_data
.m_flags
& wxINTERACTIVE_RESIZE
)
296 wxPoint diff
= wxGetMousePosition() - m_data
.m_pos
;
297 m_data
.m_rect
= m_data
.m_rectOrig
;
298 wxApplyResize(m_data
, diff
);
299 m_data
.m_window
->SetSize(m_data
.m_rect
);
303 void wxInteractiveMoveHandler::OnMouseDown(wxMouseEvent
& event
)
305 if ( m_data
.m_flags
& wxINTERACTIVE_WAIT_FOR_INPUT
)
307 m_data
.m_flags
&= ~wxINTERACTIVE_WAIT_FOR_INPUT
;
308 m_data
.m_pos
= wxGetMousePosition();
312 void wxInteractiveMoveHandler::OnKeyDown(wxKeyEvent
& event
)
314 if ( m_data
.m_flags
& wxINTERACTIVE_WAIT_FOR_INPUT
)
316 m_data
.m_flags
&= ~wxINTERACTIVE_WAIT_FOR_INPUT
;
317 m_data
.m_pos
= wxGetMousePosition();
322 switch ( event
.GetKeyCode() )
324 case WXK_UP
: diff
= wxPoint(0, -16); break;
325 case WXK_DOWN
: diff
= wxPoint(0, 16); break;
326 case WXK_LEFT
: diff
= wxPoint(-16, 0); break;
327 case WXK_RIGHT
: diff
= wxPoint(16, 0); break;
329 m_data
.m_window
->SetSize(m_data
.m_rectOrig
);
330 m_data
.m_evtLoop
->Exit();
333 m_data
.m_evtLoop
->Exit();
339 if ( m_data
.m_flags
& wxINTERACTIVE_MOVE
)
341 m_data
.m_rect
.Offset(diff
);
342 m_data
.m_window
->Move(m_data
.m_rect
.GetPosition());
344 else /* wxINTERACTIVE_RESIZE */
346 if ( !(m_data
.m_flags
& wxINTERACTIVE_RESIZE_DIR
) )
349 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_N
;
350 else if ( diff
.y
> 0 )
351 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_S
;
353 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_W
;
354 else if ( diff
.x
> 0 )
355 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_E
;
358 wxApplyResize(m_data
, diff
);
359 m_data
.m_window
->SetSize(m_data
.m_rect
);
364 void wxInteractiveMoveHandler::OnMouseUp(wxMouseEvent
& event
)
366 m_data
.m_evtLoop
->Exit();
370 void wxTopLevelWindowBase::InteractiveMove(int flags
)
372 wxASSERT_MSG( !((flags
& wxINTERACTIVE_MOVE
) && (flags
& wxINTERACTIVE_RESIZE
)),
373 wxT("can't move and resize window at the same time") );
375 wxASSERT_MSG( !(flags
& wxINTERACTIVE_RESIZE
) ||
376 (flags
& wxINTERACTIVE_WAIT_FOR_INPUT
) ||
377 (flags
& wxINTERACTIVE_RESIZE_DIR
),
378 wxT("direction of resizing not specified") );
380 wxInteractiveMoveData data
;
382 wxWindow
*focus
= FindFocus();
384 // FIXME - display resize cursor if waiting for initial input
386 data
.m_window
= this;
387 data
.m_evtLoop
= &loop
;
388 data
.m_flags
= flags
;
389 data
.m_rect
= data
.m_rectOrig
= GetRect();
390 data
.m_pos
= wxGetMousePosition();
391 data
.m_minSize
= wxSize(GetMinWidth(), GetMinHeight());
392 data
.m_maxSize
= wxSize(GetMaxWidth(), GetMaxHeight());
394 this->PushEventHandler(new wxInteractiveMoveHandler(data
));
396 focus
->PushEventHandler(new wxInteractiveMoveHandler(data
));
402 this->PopEventHandler(TRUE
/*delete*/);
404 focus
->PopEventHandler(TRUE
/*delete*/);
407 #endif // __WXUNIVERSAL__