1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/aui/floatpane.cpp
3 // Purpose:     wxaui: wx advanced user interface - docking window manager
4 // Author:      Benjamin I. Williams
5 // Modified by:
6 // Created:     2005-05-17
7 // RCS-ID:      $Id: floatpane.cpp 54904 2008-08-01 16:07:46Z BIW $
8 // Copyright:   (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
9 // Licence:     wxWindows Library Licence, Version 3.1
10 ///////////////////////////////////////////////////////////////////////////////
11 
12 // ============================================================================
13 // declarations
14 // ============================================================================
15 
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19 
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 #if 1//wxUSE_AUI
27 
28 #include "wx/aui/framemanager.h"
29 #include "wx/aui/floatpane.h"
30 #include "wx/aui/dockart.h"
31 
32 #ifndef WX_PRECOMP
33 #endif
34 
35 #ifdef __WXMSW__
36 #include "wx/msw/private.h"
37 #endif
38 
IMPLEMENT_CLASS(wxAuiFloatingFrame,wxAuiFloatingFrameBaseClass)39 IMPLEMENT_CLASS(wxAuiFloatingFrame, wxAuiFloatingFrameBaseClass)
40 
41 wxAuiFloatingFrame::wxAuiFloatingFrame(wxWindow* parent,
42                 wxAuiManager* owner_mgr,
43                 const wxAuiPaneInfo& pane,
44                 wxWindowID id /*= wxID_ANY*/,
45                 long style /*=wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION |
46                               wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT |
47                               wxCLIP_CHILDREN
48                            */)
49                 : wxAuiFloatingFrameBaseClass(parent, id, wxEmptyString,
50                         pane.floating_pos, pane.floating_size,
51                         style |
52                         (pane.HasCloseButton()?wxCLOSE_BOX:0) |
53                         (pane.HasMaximizeButton()?wxMAXIMIZE_BOX:0) |
54                         (pane.IsFixed()?0:wxRESIZE_BORDER)
55                         )
56 {
57     m_owner_mgr = owner_mgr;
58     m_moving = false;
59     m_mgr.SetManagedWindow(this);
60     m_solid_drag = true;
61 
62     // find out if the system supports solid window drag.
63     // on non-msw systems, this is assumed to be the case
64 #ifdef __WXMSW__
65     BOOL b = TRUE;
66     SystemParametersInfo(38 /*SPI_GETDRAGFULLWINDOWS*/, 0, &b, 0);
67     m_solid_drag = b ? true : false;
68 #endif
69 
70     SetExtraStyle(wxWS_EX_PROCESS_IDLE);
71 }
72 
~wxAuiFloatingFrame()73 wxAuiFloatingFrame::~wxAuiFloatingFrame()
74 {
75     // if we do not do this, then we can crash...
76     if(m_owner_mgr && m_owner_mgr->m_action_window == this)
77     {
78         m_owner_mgr->m_action_window = NULL;
79     }
80     m_mgr.UnInit();
81 }
82 
SetPaneWindow(const wxAuiPaneInfo & pane)83 void wxAuiFloatingFrame::SetPaneWindow(const wxAuiPaneInfo& pane)
84 {
85     m_pane_window = pane.window;
86     m_pane_window->Reparent(this);
87 
88     wxAuiPaneInfo contained_pane = pane;
89     contained_pane.Dock().Center().Show().
90                     CaptionVisible(false).
91                     PaneBorder(false).
92                     Layer(0).Row(0).Position(0);
93 
94     // Carry over the minimum size
95     wxSize pane_min_size = pane.window->GetMinSize();
96 
97     // if the frame window's max size is greater than the min size
98     // then set the max size to the min size as well
99     wxSize cur_max_size = GetMaxSize();
100     if (cur_max_size.IsFullySpecified() &&
101           (cur_max_size.x < pane.min_size.x ||
102            cur_max_size.y < pane.min_size.y)
103        )
104     {
105         SetMaxSize(pane_min_size);
106     }
107 
108     SetMinSize(pane.window->GetMinSize());
109 
110     m_mgr.AddPane(m_pane_window, contained_pane);
111     m_mgr.Update();
112 
113     if (pane.min_size.IsFullySpecified())
114     {
115         // because SetSizeHints() calls Fit() too (which sets the window
116         // size to its minimum allowed), we keep the size before calling
117         // SetSizeHints() and reset it afterwards...
118         wxSize tmp = GetSize();
119         GetSizer()->SetSizeHints(this);
120         SetSize(tmp);
121     }
122 
123     SetTitle(pane.caption);
124 
125     if (pane.floating_size != wxDefaultSize)
126     {
127         SetSize(pane.floating_size);
128     }
129         else
130     {
131         wxSize size = pane.best_size;
132         if (size == wxDefaultSize)
133             size = pane.min_size;
134         if (size == wxDefaultSize)
135             size = m_pane_window->GetSize();
136         if (pane.HasGripper())
137         {
138             if (pane.HasGripperTop())
139                 size.y += m_owner_mgr->m_art->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE);
140             else
141                 size.x += m_owner_mgr->m_art->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE);
142         }
143 
144         SetClientSize(size);
145     }
146 
147     if (pane.IsFixed())
148     {
149         SetWindowStyleFlag(GetWindowStyleFlag() & ~wxRESIZE_BORDER);
150     }
151 }
152 
GetOwnerManager() const153 wxAuiManager* wxAuiFloatingFrame::GetOwnerManager() const
154 {
155     return m_owner_mgr;
156 }
157 
158 
OnSize(wxSizeEvent & event)159 void wxAuiFloatingFrame::OnSize(wxSizeEvent& event)
160 {
161     m_owner_mgr->OnFloatingPaneResized(m_pane_window, event.GetSize());
162 }
163 
OnClose(wxCloseEvent & evt)164 void wxAuiFloatingFrame::OnClose(wxCloseEvent& evt)
165 {
166     m_owner_mgr->OnFloatingPaneClosed(m_pane_window, evt);
167     if (!evt.GetVeto()) {
168 	m_mgr.DetachPane(m_pane_window);
169         Destroy();
170     }
171 }
172 
OnMoveEvent(wxMoveEvent & event)173 void wxAuiFloatingFrame::OnMoveEvent(wxMoveEvent& event)
174 {
175     if (!m_solid_drag)
176     {
177         // systems without solid window dragging need to be
178         // handled slightly differently, due to the lack of
179         // the constant stream of EVT_MOVING events
180         if (!isMouseDown())
181             return;
182         OnMoveStart();
183         OnMoving(event.GetRect(), wxNORTH);
184         m_moving = true;
185         return;
186     }
187 
188 
189     wxRect win_rect = GetRect();
190 
191     if (win_rect == m_last_rect)
192         return;
193 
194     // skip the first move event
195     if (m_last_rect.IsEmpty())
196     {
197         m_last_rect = win_rect;
198         return;
199     }
200 
201     // skip if moving too fast to avoid massive redraws and
202     // jumping hint windows
203     if ((abs(win_rect.x - m_last_rect.x) > 3) ||
204         (abs(win_rect.y - m_last_rect.y) > 3))
205     {
206         m_last3_rect = m_last2_rect;
207         m_last2_rect = m_last_rect;
208         m_last_rect = win_rect;
209         return;
210     }
211 
212     // prevent frame redocking during resize
213     if (m_last_rect.GetSize() != win_rect.GetSize())
214     {
215         m_last3_rect = m_last2_rect;
216         m_last2_rect = m_last_rect;
217         m_last_rect = win_rect;
218         return;
219     }
220 
221     wxDirection dir = wxALL;
222 
223     int horiz_dist = abs(win_rect.x - m_last3_rect.x);
224     int vert_dist = abs(win_rect.y - m_last3_rect.y);
225 
226     if (vert_dist >= horiz_dist)
227     {
228         if (win_rect.y < m_last3_rect.y)
229             dir = wxNORTH;
230         else
231             dir = wxSOUTH;
232     }
233     else
234     {
235         if (win_rect.x < m_last3_rect.x)
236             dir = wxWEST;
237         else
238             dir = wxEAST;
239     }
240 
241     m_last3_rect = m_last2_rect;
242     m_last2_rect = m_last_rect;
243     m_last_rect = win_rect;
244 
245     if (!isMouseDown())
246         return;
247 
248     if (!m_moving)
249     {
250         OnMoveStart();
251         m_moving = true;
252     }
253 
254     if (m_last3_rect.IsEmpty())
255         return;
256 
257     OnMoving(event.GetRect(), dir);
258 }
259 
OnIdle(wxIdleEvent & event)260 void wxAuiFloatingFrame::OnIdle(wxIdleEvent& event)
261 {
262     if (m_moving)
263     {
264         if (!isMouseDown())
265         {
266             m_moving = false;
267             OnMoveFinished();
268         }
269          else
270         {
271             event.RequestMore();
272         }
273     }
274 }
275 
OnMoveStart()276 void wxAuiFloatingFrame::OnMoveStart()
277 {
278     // notify the owner manager that the pane has started to move
279     m_owner_mgr->OnFloatingPaneMoveStart(m_pane_window);
280 }
281 
OnMoving(const wxRect & WXUNUSED (window_rect),wxDirection dir)282 void wxAuiFloatingFrame::OnMoving(const wxRect& WXUNUSED(window_rect), wxDirection dir)
283 {
284     // notify the owner manager that the pane is moving
285     m_owner_mgr->OnFloatingPaneMoving(m_pane_window, dir);
286     m_lastDirection = dir;
287 }
288 
OnMoveFinished()289 void wxAuiFloatingFrame::OnMoveFinished()
290 {
291     // notify the owner manager that the pane has finished moving
292     m_owner_mgr->OnFloatingPaneMoved(m_pane_window, m_lastDirection);
293 }
294 
OnActivate(wxActivateEvent & event)295 void wxAuiFloatingFrame::OnActivate(wxActivateEvent& event)
296 {
297     if (event.GetActive())
298     {
299         m_owner_mgr->OnFloatingPaneActivated(m_pane_window);
300     }
301 }
302 
303 // utility function which determines the state of the mouse button
304 // (independant of having a wxMouseEvent handy) - utimately a better
305 // mechanism for this should be found (possibly by adding the
306 // functionality to wxWidgets itself)
isMouseDown()307 bool wxAuiFloatingFrame::isMouseDown()
308 {
309     return wxGetMouseState().LeftDown();
310 }
311 
312 
313 BEGIN_EVENT_TABLE(wxAuiFloatingFrame, wxAuiFloatingFrameBaseClass)
314     EVT_SIZE(wxAuiFloatingFrame::OnSize)
315     EVT_MOVE(wxAuiFloatingFrame::OnMoveEvent)
316     EVT_MOVING(wxAuiFloatingFrame::OnMoveEvent)
317     EVT_CLOSE(wxAuiFloatingFrame::OnClose)
318     EVT_IDLE(wxAuiFloatingFrame::OnIdle)
319     EVT_ACTIVATE(wxAuiFloatingFrame::OnActivate)
320 END_EVENT_TABLE()
321 
322 
323 #endif // wxUSE_AUI
324