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 bool wxTopLevelWindowBase::Destroy()
65 // delayed destruction: the frame will be deleted during the next idle
67 if ( !wxPendingDelete
.Member(this) )
68 wxPendingDelete
.Append(this);
73 // ----------------------------------------------------------------------------
74 // wxTopLevelWindow size management: we exclude the areas taken by
75 // menu/status/toolbars from the client area, so the client area is what's
76 // really available for the frame contents
77 // ----------------------------------------------------------------------------
79 void wxTopLevelWindowBase::DoScreenToClient(int *x
, int *y
) const
81 wxWindow::DoScreenToClient(x
, y
);
83 // translate the wxWindow client coords to our client coords
84 wxPoint
pt(GetClientAreaOrigin());
91 void wxTopLevelWindowBase::DoClientToScreen(int *x
, int *y
) const
93 // our client area origin (0, 0) may be really something like (0, 30) for
94 // wxWindow if we have a toolbar, account for it before translating
95 wxPoint
pt(GetClientAreaOrigin());
101 wxWindow::DoClientToScreen(x
, y
);
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
109 // default resizing behaviour - if only ONE subwindow, resize to fill the
111 void wxTopLevelWindowBase::OnSize(wxSizeEvent
& WXUNUSED(event
))
113 // if we're using constraints - do use them
114 #if wxUSE_CONSTRAINTS
115 if ( GetAutoLayout() )
120 #endif // wxUSE_CONSTRAINTS
122 // do we have _exactly_ one child?
123 wxWindow
*child
= (wxWindow
*)NULL
;
124 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
126 node
= node
->GetNext() )
128 wxWindow
*win
= node
->GetData();
130 // exclude top level and managed windows (status bar isn't
131 // currently in the children list except under wxMac anyhow, but
132 // it makes no harm to test for it)
133 if ( !win
->IsTopLevel() && !IsOneOfBars(win
) )
140 return; // it's our second subwindow - nothing to do
147 // do we have any children at all?
150 // exactly one child - set it's size to fill the whole frame
151 int clientW
, clientH
;
152 DoGetClientSize(&clientW
, &clientH
);
154 // for whatever reasons, wxGTK wants to have a small offset - it
155 // probably looks better with it?
157 static const int ofs
= 1;
159 static const int ofs
= 0;
162 child
->SetSize(ofs
, ofs
, clientW
- 2*ofs
, clientH
- 2*ofs
);
164 UpdateInternalSize(child
, clientH
);
170 // The default implementation for the close window event.
171 void wxTopLevelWindowBase::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
176 bool wxTopLevelWindowBase::SendIconizeEvent(bool iconized
)
178 wxIconizeEvent
event(GetId(), iconized
);
179 event
.SetEventObject(this);
181 return GetEventHandler()->ProcessEvent(event
);
184 // ----------------------------------------------------------------------------
185 // interactive manipulation
186 // ----------------------------------------------------------------------------
188 #ifdef __WXUNIVERSAL__
190 #define wxINTERACTIVE_RESIZE_DIR \
191 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E | \
192 wxINTERACTIVE_RESIZE_S | wxINTERACTIVE_RESIZE_N)
194 struct wxInteractiveMoveData
196 wxTopLevelWindowBase
*m_window
;
197 wxEventLoop
*m_evtLoop
;
202 wxSize m_minSize
, m_maxSize
;
205 class wxInteractiveMoveHandler
: public wxEvtHandler
208 wxInteractiveMoveHandler(wxInteractiveMoveData
& data
) : m_data(data
) {}
211 DECLARE_EVENT_TABLE()
212 void OnMouseMove(wxMouseEvent
& event
);
213 void OnMouseDown(wxMouseEvent
& event
);
214 void OnMouseUp(wxMouseEvent
& event
);
215 void OnKeyDown(wxKeyEvent
& event
);
217 wxInteractiveMoveData
& m_data
;
220 BEGIN_EVENT_TABLE(wxInteractiveMoveHandler
, wxEvtHandler
)
221 EVT_MOTION(wxInteractiveMoveHandler::OnMouseMove
)
222 EVT_LEFT_DOWN(wxInteractiveMoveHandler::OnMouseDown
)
223 EVT_LEFT_UP(wxInteractiveMoveHandler::OnMouseUp
)
224 EVT_KEY_DOWN(wxInteractiveMoveHandler::OnKeyDown
)
228 static inline LINKAGEMODE
229 void wxApplyResize(wxInteractiveMoveData
& data
, const wxPoint
& diff
)
231 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_W
)
233 data
.m_rect
.x
+= diff
.x
;
234 data
.m_rect
.width
-= diff
.x
;
236 else if ( data
.m_flags
& wxINTERACTIVE_RESIZE_E
)
238 data
.m_rect
.width
+= diff
.x
;
240 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_N
)
242 data
.m_rect
.y
+= diff
.y
;
243 data
.m_rect
.height
-= diff
.y
;
245 else if ( data
.m_flags
& wxINTERACTIVE_RESIZE_S
)
247 data
.m_rect
.height
+= diff
.y
;
250 if ( data
.m_minSize
.x
!= -1 && data
.m_rect
.width
< data
.m_minSize
.x
)
252 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_W
)
253 data
.m_rect
.x
-= data
.m_minSize
.x
- data
.m_rect
.width
;
254 data
.m_rect
.width
= data
.m_minSize
.x
;
256 if ( data
.m_maxSize
.x
!= -1 && data
.m_rect
.width
> data
.m_maxSize
.x
)
258 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_W
)
259 data
.m_rect
.x
-= data
.m_minSize
.x
- data
.m_rect
.width
;
260 data
.m_rect
.width
= data
.m_maxSize
.x
;
262 if ( data
.m_minSize
.y
!= -1 && data
.m_rect
.height
< data
.m_minSize
.y
)
264 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_N
)
265 data
.m_rect
.y
-= data
.m_minSize
.y
- data
.m_rect
.height
;
266 data
.m_rect
.height
= data
.m_minSize
.y
;
268 if ( data
.m_maxSize
.y
!= -1 && data
.m_rect
.height
> data
.m_maxSize
.y
)
270 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_N
)
271 data
.m_rect
.y
-= data
.m_minSize
.y
- data
.m_rect
.height
;
272 data
.m_rect
.height
= data
.m_maxSize
.y
;
276 void wxInteractiveMoveHandler::OnMouseMove(wxMouseEvent
& event
)
278 if ( m_data
.m_flags
& wxINTERACTIVE_WAIT_FOR_INPUT
)
281 else if ( m_data
.m_flags
& wxINTERACTIVE_MOVE
)
283 wxPoint diff
= wxGetMousePosition() - m_data
.m_pos
;
284 m_data
.m_rect
= m_data
.m_rectOrig
;
285 m_data
.m_rect
.Offset(diff
);
286 m_data
.m_window
->Move(m_data
.m_rect
.GetPosition());
289 else if ( m_data
.m_flags
& wxINTERACTIVE_RESIZE
)
291 wxPoint diff
= wxGetMousePosition() - m_data
.m_pos
;
292 m_data
.m_rect
= m_data
.m_rectOrig
;
293 wxApplyResize(m_data
, diff
);
294 m_data
.m_window
->SetSize(m_data
.m_rect
);
298 void wxInteractiveMoveHandler::OnMouseDown(wxMouseEvent
& event
)
300 if ( m_data
.m_flags
& wxINTERACTIVE_WAIT_FOR_INPUT
)
302 m_data
.m_flags
&= ~wxINTERACTIVE_WAIT_FOR_INPUT
;
303 m_data
.m_pos
= wxGetMousePosition();
307 void wxInteractiveMoveHandler::OnKeyDown(wxKeyEvent
& event
)
309 if ( m_data
.m_flags
& wxINTERACTIVE_WAIT_FOR_INPUT
)
311 m_data
.m_flags
&= ~wxINTERACTIVE_WAIT_FOR_INPUT
;
312 m_data
.m_pos
= wxGetMousePosition();
317 switch ( event
.GetKeyCode() )
319 case WXK_UP
: diff
= wxPoint(0, -16); break;
320 case WXK_DOWN
: diff
= wxPoint(0, 16); break;
321 case WXK_LEFT
: diff
= wxPoint(-16, 0); break;
322 case WXK_RIGHT
: diff
= wxPoint(16, 0); break;
324 m_data
.m_window
->SetSize(m_data
.m_rectOrig
);
325 m_data
.m_evtLoop
->Exit();
328 m_data
.m_evtLoop
->Exit();
334 if ( m_data
.m_flags
& wxINTERACTIVE_MOVE
)
336 m_data
.m_rect
.Offset(diff
);
337 m_data
.m_window
->Move(m_data
.m_rect
.GetPosition());
339 else /* wxINTERACTIVE_RESIZE */
341 if ( !(m_data
.m_flags
& wxINTERACTIVE_RESIZE_DIR
) )
344 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_N
;
345 else if ( diff
.y
> 0 )
346 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_S
;
348 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_W
;
349 else if ( diff
.x
> 0 )
350 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_E
;
353 wxApplyResize(m_data
, diff
);
354 m_data
.m_window
->SetSize(m_data
.m_rect
);
359 void wxInteractiveMoveHandler::OnMouseUp(wxMouseEvent
& event
)
361 m_data
.m_evtLoop
->Exit();
365 void wxTopLevelWindowBase::InteractiveMove(int flags
)
367 wxASSERT_MSG( !((flags
& wxINTERACTIVE_MOVE
) && (flags
& wxINTERACTIVE_RESIZE
)),
368 wxT("can't move and resize window at the same time") );
370 wxASSERT_MSG( !(flags
& wxINTERACTIVE_RESIZE
) ||
371 (flags
& wxINTERACTIVE_WAIT_FOR_INPUT
) ||
372 (flags
& wxINTERACTIVE_RESIZE_DIR
),
373 wxT("direction of resizing not specified") );
375 wxInteractiveMoveData data
;
377 wxWindow
*focus
= FindFocus();
379 // FIXME - display resize cursor if waiting for initial input
381 data
.m_window
= this;
382 data
.m_evtLoop
= &loop
;
383 data
.m_flags
= flags
;
384 data
.m_rect
= data
.m_rectOrig
= GetRect();
385 data
.m_pos
= wxGetMousePosition();
386 data
.m_minSize
= wxSize(GetMinWidth(), GetMinHeight());
387 data
.m_maxSize
= wxSize(GetMaxWidth(), GetMaxHeight());
389 this->PushEventHandler(new wxInteractiveMoveHandler(data
));
391 focus
->PushEventHandler(new wxInteractiveMoveHandler(data
));
397 this->PopEventHandler(TRUE
/*delete*/);
399 focus
->PopEventHandler(TRUE
/*delete*/);
402 #endif // __WXUNIVERSAL__