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 child
->MoveChildren(m_vSwpClient
.cy
- clientH
);
165 ::WinQueryWindowPos(GetHwnd(), &m_vSwpClient
);
171 // The default implementation for the close window event.
172 void wxTopLevelWindowBase::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
177 bool wxTopLevelWindowBase::SendIconizeEvent(bool iconized
)
179 wxIconizeEvent
event(GetId(), iconized
);
180 event
.SetEventObject(this);
182 return GetEventHandler()->ProcessEvent(event
);
186 // ----------------------------------------------------------------------------
187 // interactive manipulation
188 // ----------------------------------------------------------------------------
190 #ifdef __WXUNIVERSAL__
192 #define wxINTERACTIVE_RESIZE_DIR \
193 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E | \
194 wxINTERACTIVE_RESIZE_S | wxINTERACTIVE_RESIZE_N)
196 struct wxInteractiveMoveData
198 wxTopLevelWindowBase
*m_window
;
199 wxEventLoop
*m_evtLoop
;
204 wxSize m_minSize
, m_maxSize
;
207 class wxInteractiveMoveHandler
: public wxEvtHandler
210 wxInteractiveMoveHandler(wxInteractiveMoveData
& data
) : m_data(data
) {}
213 DECLARE_EVENT_TABLE()
214 void OnMouseMove(wxMouseEvent
& event
);
215 void OnMouseDown(wxMouseEvent
& event
);
216 void OnMouseUp(wxMouseEvent
& event
);
217 void OnKeyDown(wxKeyEvent
& event
);
219 wxInteractiveMoveData
& m_data
;
222 BEGIN_EVENT_TABLE(wxInteractiveMoveHandler
, wxEvtHandler
)
223 EVT_MOTION(wxInteractiveMoveHandler::OnMouseMove
)
224 EVT_LEFT_DOWN(wxInteractiveMoveHandler::OnMouseDown
)
225 EVT_LEFT_UP(wxInteractiveMoveHandler::OnMouseUp
)
226 EVT_KEY_DOWN(wxInteractiveMoveHandler::OnKeyDown
)
230 static inline LINKAGEMODE
231 void wxApplyResize(wxInteractiveMoveData
& data
, const wxPoint
& diff
)
233 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_W
)
235 data
.m_rect
.x
+= diff
.x
;
236 data
.m_rect
.width
-= diff
.x
;
238 else if ( data
.m_flags
& wxINTERACTIVE_RESIZE_E
)
240 data
.m_rect
.width
+= diff
.x
;
242 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_N
)
244 data
.m_rect
.y
+= diff
.y
;
245 data
.m_rect
.height
-= diff
.y
;
247 else if ( data
.m_flags
& wxINTERACTIVE_RESIZE_S
)
249 data
.m_rect
.height
+= diff
.y
;
252 if ( data
.m_minSize
.x
!= -1 && data
.m_rect
.width
< data
.m_minSize
.x
)
254 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_W
)
255 data
.m_rect
.x
-= data
.m_minSize
.x
- data
.m_rect
.width
;
256 data
.m_rect
.width
= data
.m_minSize
.x
;
258 if ( data
.m_maxSize
.x
!= -1 && data
.m_rect
.width
> data
.m_maxSize
.x
)
260 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_W
)
261 data
.m_rect
.x
-= data
.m_minSize
.x
- data
.m_rect
.width
;
262 data
.m_rect
.width
= data
.m_maxSize
.x
;
264 if ( data
.m_minSize
.y
!= -1 && data
.m_rect
.height
< data
.m_minSize
.y
)
266 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_N
)
267 data
.m_rect
.y
-= data
.m_minSize
.y
- data
.m_rect
.height
;
268 data
.m_rect
.height
= data
.m_minSize
.y
;
270 if ( data
.m_maxSize
.y
!= -1 && data
.m_rect
.height
> data
.m_maxSize
.y
)
272 if ( data
.m_flags
& wxINTERACTIVE_RESIZE_N
)
273 data
.m_rect
.y
-= data
.m_minSize
.y
- data
.m_rect
.height
;
274 data
.m_rect
.height
= data
.m_maxSize
.y
;
278 void wxInteractiveMoveHandler::OnMouseMove(wxMouseEvent
& event
)
280 if ( m_data
.m_flags
& wxINTERACTIVE_WAIT_FOR_INPUT
)
283 else if ( m_data
.m_flags
& wxINTERACTIVE_MOVE
)
285 wxPoint diff
= wxGetMousePosition() - m_data
.m_pos
;
286 m_data
.m_rect
= m_data
.m_rectOrig
;
287 m_data
.m_rect
.Offset(diff
);
288 m_data
.m_window
->Move(m_data
.m_rect
.GetPosition());
291 else if ( m_data
.m_flags
& wxINTERACTIVE_RESIZE
)
293 wxPoint diff
= wxGetMousePosition() - m_data
.m_pos
;
294 m_data
.m_rect
= m_data
.m_rectOrig
;
295 wxApplyResize(m_data
, diff
);
296 m_data
.m_window
->SetSize(m_data
.m_rect
);
300 void wxInteractiveMoveHandler::OnMouseDown(wxMouseEvent
& event
)
302 if ( m_data
.m_flags
& wxINTERACTIVE_WAIT_FOR_INPUT
)
304 m_data
.m_flags
&= ~wxINTERACTIVE_WAIT_FOR_INPUT
;
305 m_data
.m_pos
= wxGetMousePosition();
309 void wxInteractiveMoveHandler::OnKeyDown(wxKeyEvent
& event
)
311 if ( m_data
.m_flags
& wxINTERACTIVE_WAIT_FOR_INPUT
)
313 m_data
.m_flags
&= ~wxINTERACTIVE_WAIT_FOR_INPUT
;
314 m_data
.m_pos
= wxGetMousePosition();
319 switch ( event
.GetKeyCode() )
321 case WXK_UP
: diff
= wxPoint(0, -16); break;
322 case WXK_DOWN
: diff
= wxPoint(0, 16); break;
323 case WXK_LEFT
: diff
= wxPoint(-16, 0); break;
324 case WXK_RIGHT
: diff
= wxPoint(16, 0); break;
326 m_data
.m_window
->SetSize(m_data
.m_rectOrig
);
327 m_data
.m_evtLoop
->Exit();
330 m_data
.m_evtLoop
->Exit();
336 if ( m_data
.m_flags
& wxINTERACTIVE_MOVE
)
338 m_data
.m_rect
.Offset(diff
);
339 m_data
.m_window
->Move(m_data
.m_rect
.GetPosition());
341 else /* wxINTERACTIVE_RESIZE */
343 if ( !(m_data
.m_flags
& wxINTERACTIVE_RESIZE_DIR
) )
346 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_N
;
347 else if ( diff
.y
> 0 )
348 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_S
;
350 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_W
;
351 else if ( diff
.x
> 0 )
352 m_data
.m_flags
|= wxINTERACTIVE_RESIZE_E
;
355 wxApplyResize(m_data
, diff
);
356 m_data
.m_window
->SetSize(m_data
.m_rect
);
361 void wxInteractiveMoveHandler::OnMouseUp(wxMouseEvent
& event
)
363 m_data
.m_evtLoop
->Exit();
367 void wxTopLevelWindowBase::InteractiveMove(int flags
)
369 wxASSERT_MSG( !((flags
& wxINTERACTIVE_MOVE
) && (flags
& wxINTERACTIVE_RESIZE
)),
370 wxT("can't move and resize window at the same time") );
372 wxASSERT_MSG( !(flags
& wxINTERACTIVE_RESIZE
) ||
373 (flags
& wxINTERACTIVE_WAIT_FOR_INPUT
) ||
374 (flags
& wxINTERACTIVE_RESIZE_DIR
),
375 wxT("direction of resizing not specified") );
377 wxInteractiveMoveData data
;
379 wxWindow
*focus
= FindFocus();
381 // FIXME - display resize cursor if waiting for initial input
383 data
.m_window
= this;
384 data
.m_evtLoop
= &loop
;
385 data
.m_flags
= flags
;
386 data
.m_rect
= data
.m_rectOrig
= GetRect();
387 data
.m_pos
= wxGetMousePosition();
388 data
.m_minSize
= wxSize(GetMinWidth(), GetMinHeight());
389 data
.m_maxSize
= wxSize(GetMaxWidth(), GetMaxHeight());
391 this->PushEventHandler(new wxInteractiveMoveHandler(data
));
393 focus
->PushEventHandler(new wxInteractiveMoveHandler(data
));
399 this->PopEventHandler(TRUE
/*delete*/);
401 focus
->PopEventHandler(TRUE
/*delete*/);
404 #endif // __WXUNIVERSAL__