30 #include <OCPN_AUIManager.h>
32 #include "ocpn_frame.h"
35 #include <wx/msw/wrapwin.h>
36 #include <wx/msw/private.h>
37 #include <wx/msw/dc.h>
42 static wxBitmap wxOPaneCreateStippleBitmap() {
43 unsigned char data[] = {0, 0, 0, 192, 192, 192, 192, 192, 192, 0, 0, 0};
44 wxImage img(2, 2, data,
true);
48 static void ODrawResizeHint(wxDC& dc,
const wxRect& rect) {
50 wxBitmap stipple = wxOPaneCreateStippleBitmap();
51 wxBrush brush(stipple);
54 wxMSWDCImpl* impl = (wxMSWDCImpl*)dc.GetImpl();
55 PatBlt(GetHdcOf(*impl), rect.GetX(), rect.GetY(), rect.GetWidth(),
56 rect.GetHeight(), PATINVERT);
58 dc.SetPen(*wxTRANSPARENT_PEN);
60 dc.SetLogicalFunction(wxXOR);
61 dc.DrawRectangle(rect);
67 bool OAuiManager_HasLiveResize(wxAuiManager& manager) {
70 #if defined(__WXMAC__)
74 return (manager.GetFlags() & wxAUI_MGR_LIVE_RESIZE) == wxAUI_MGR_LIVE_RESIZE;
81 EVT_AUI_PANE_BUTTON(wxAuiManager::OnPaneButton)
82 EVT_AUI_RENDER(wxAuiManager::OnRender)
83 EVT_PAINT(OCPN_AUIManager::OnPaint)
84 EVT_ERASE_BACKGROUND(OCPN_AUIManager::OnEraseBackground)
85 EVT_SIZE(OCPN_AUIManager::OnSize)
86 EVT_SET_CURSOR(OCPN_AUIManager::OnSetCursor)
87 EVT_LEFT_DOWN(OCPN_AUIManager::OnLeftDown)
88 EVT_LEFT_UP(OCPN_AUIManager::OnLeftUp)
89 EVT_MOTION(OCPN_AUIManager::OnMotionx)
90 EVT_LEAVE_WINDOW(OCPN_AUIManager::OnLeaveWindow)
91 EVT_MOUSE_CAPTURE_LOST(OCPN_AUIManager::OnCaptureLost)
92 EVT_CHILD_FOCUS(OCPN_AUIManager::OnChildFocus)
93 EVT_AUI_FIND_MANAGER(OCPN_AUIManager::OnFindManager)
97 : wxAuiManager(managed_wnd, flags)
101 OCPN_AUIManager::~OCPN_AUIManager() {}
103 void OCPN_AUIManager::OnMotionx(wxMouseEvent& event) {
110 wxPoint mouse_pos =
event.GetPosition();
111 if (m_lastMouseMove == mouse_pos)
return;
112 m_lastMouseMove = mouse_pos;
114 if (m_action == actionResize) {
117 if (m_currentDragItem != -1)
118 m_actionPart = &(m_uiParts.Item(m_currentDragItem));
120 m_currentDragItem = m_uiParts.Index(*m_actionPart);
123 wxPoint pos = m_actionPart->rect.GetPosition();
124 if (m_actionPart->orientation == wxHORIZONTAL)
125 pos.y = wxMax(0, event.m_y - m_actionOffset.y);
127 pos.x = wxMax(0, event.m_x - m_actionOffset.x);
129 wxSize client_size = m_frame->GetClientSize();
130 int used_width = 0, used_height = 0;
132 size_t dock_i, dock_count = m_docks.GetCount();
133 for (dock_i = 0; dock_i < dock_count; ++dock_i) {
134 wxAuiDockInfo& dock = m_docks.Item(dock_i);
135 if (dock.dock_direction == wxAUI_DOCK_TOP ||
136 dock.dock_direction == wxAUI_DOCK_BOTTOM) {
137 used_height += dock.size;
139 if (dock.dock_direction == wxAUI_DOCK_LEFT ||
140 dock.dock_direction == wxAUI_DOCK_RIGHT) {
141 used_width += dock.size;
147 if (OAuiManager_HasLiveResize(*
this)) {
148 m_frame->ReleaseMouse();
149 if ((used_width < client_size.x * 9 / 10) &&
150 (used_width > client_size.x * 1 / 10))
151 DoEndResizeAction(event);
153 m_frame->CaptureMouse();
155 bool bhasMouse = m_frame->HasCapture();
157 if (bhasMouse) m_frame->ReleaseMouse();
162 if (pmf) pmf->NotifyChildrenResize();
164 wxRect rect(m_frame->ClientToScreen(pos), m_actionPart->rect.GetSize());
167 if (!m_0actionHintRect.IsEmpty()) {
169 ODrawResizeHint(dc, m_0actionHintRect);
170 m_0actionHintRect = wxRect();
173 wxRect frameScreenRect = m_frame->GetScreenRect();
176 wxMax(rect.x, frameScreenRect.x + frameScreenRect.width * 1 / 10);
178 wxMin(rect.x, frameScreenRect.x + frameScreenRect.width * 9 / 10);
182 ODrawResizeHint(dc, rect);
183 m_0actionHintRect = rect;
186 if (bhasMouse) m_frame->CaptureMouse();
194 bool OCPN_AUIManager::DoEndResizeAction(wxMouseEvent& event) {
196 if (m_actionPart && m_actionPart->type == wxAuiDockUIPart::typeDockSizer) {
198 int sashSize = m_art->GetMetric(wxAUI_DOCKART_SASH_SIZE);
200 int used_width = 0, used_height = 0;
202 wxSize client_size = m_frame->GetClientSize();
204 size_t dock_i, dock_count = m_docks.GetCount();
205 for (dock_i = 0; dock_i < dock_count; ++dock_i) {
206 wxAuiDockInfo& dock = m_docks.Item(dock_i);
207 if (dock.dock_direction == wxAUI_DOCK_TOP ||
208 dock.dock_direction == wxAUI_DOCK_BOTTOM) {
209 used_height += dock.size;
211 if (dock.dock_direction == wxAUI_DOCK_LEFT ||
212 dock.dock_direction == wxAUI_DOCK_RIGHT) {
213 used_width += dock.size;
215 if (dock.resizable) used_width += sashSize;
218 int available_width = client_size.GetWidth() - used_width;
219 int available_height = client_size.GetHeight() - used_height;
224 if (wxDynamicCast(m_frame, wxFrame)) {
225 wxFrame* frame =
static_cast<wxFrame*
>(m_frame);
226 wxStatusBar* status = frame->GetStatusBar();
228 wxSize status_client_size = status->GetClientSize();
229 available_height -= status_client_size.GetHeight();
234 wxRect& rect = m_actionPart->dock->rect;
236 wxPoint new_pos(event.m_x - m_actionOffset.x, event.m_y - m_actionOffset.y);
237 int new_size, old_size = m_actionPart->dock->size;
239 switch (m_actionPart->dock->dock_direction) {
240 case wxAUI_DOCK_LEFT:
241 new_size = new_pos.x - rect.x;
242 if (new_size - old_size > available_width)
243 new_size = old_size + available_width;
244 m_actionPart->dock->size = new_size;
247 new_size = new_pos.y - rect.y;
248 if (new_size - old_size > available_height)
249 new_size = old_size + available_height;
250 m_actionPart->dock->size = new_size;
252 case wxAUI_DOCK_RIGHT:
254 rect.x + rect.width - new_pos.x - m_actionPart->rect.GetWidth();
255 if (new_size - old_size > available_width)
256 new_size = old_size + available_width;
257 m_actionPart->dock->size = new_size;
259 m_actionPart->dock->size =
260 wxMax(m_actionPart->dock->size, client_size.x * 1 / 10);
261 m_actionPart->dock->size =
262 wxMin(m_actionPart->dock->size, client_size.x * 9 / 10);
265 case wxAUI_DOCK_BOTTOM:
267 rect.y + rect.height - new_pos.y - m_actionPart->rect.GetHeight();
268 if (new_size - old_size > available_height)
269 new_size = old_size + available_height;
270 m_actionPart->dock->size = new_size;
276 }
else if (m_actionPart &&
277 m_actionPart->type == wxAuiDockUIPart::typePaneSizer) {
278 wxAuiDockInfo& dock = *m_actionPart->dock;
279 wxAuiPaneInfo& pane = *m_actionPart->pane;
281 int total_proportion = 0;
285 int caption_size = m_art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE);
286 int pane_borderSize = m_art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE);
287 int sashSize = m_art->GetMetric(wxAUI_DOCKART_SASH_SIZE);
289 wxPoint new_pos(event.m_x - m_actionOffset.x, event.m_y - m_actionOffset.y);
292 wxAuiDockUIPart* pane_part = GetPanePart(pane.window);
293 wxASSERT_MSG(pane_part,
294 wxT(
"Pane border part not found -- shouldn't happen"));
298 if (dock.IsHorizontal())
299 new_pixsize = new_pos.x - pane_part->rect.x;
301 new_pixsize = new_pos.y - pane_part->rect.y;
304 if (dock.IsHorizontal())
305 dock_pixels = dock.rect.GetWidth();
307 dock_pixels = dock.rect.GetHeight();
312 int i, dock_pane_count = dock.panes.GetCount();
313 int pane_position = -1;
314 for (i = 0; i < dock_pane_count; ++i) {
315 wxAuiPaneInfo& p = *dock.panes.Item(i);
316 if (p.window == pane.window) pane_position = i;
321 if (i > 0) dock_pixels -= sashSize;
327 if (dock.IsHorizontal())
328 dock_pixels -= p.best_size.x;
330 dock_pixels -= p.best_size.y;
332 total_proportion += p.dock_proportion;
337 if (new_pixsize > dock_pixels) new_pixsize = dock_pixels;
343 int borrow_pane = -1;
344 for (i = pane_position + 1; i < dock_pane_count; ++i) {
345 wxAuiPaneInfo& p = *dock.panes.Item(i);
354 wxASSERT_MSG(pane_position != -1, wxT(
"Pane not found in dock"));
357 if (dock_pixels == 0 || total_proportion == 0 || borrow_pane == -1) {
358 m_action = actionNone;
363 int new_proportion = (new_pixsize * total_proportion) / dock_pixels;
372 if (pane.min_size.IsFullySpecified()) {
375 if (pane.HasBorder()) min_size += (pane_borderSize * 2);
378 if (pane_part->orientation == wxVERTICAL) {
379 min_size += pane.min_size.y;
380 if (pane.HasCaption()) min_size += caption_size;
382 min_size += pane.min_size.x;
392 int min_proportion = (min_size * total_proportion) / dock_pixels;
394 if (new_proportion < min_proportion) new_proportion = min_proportion;
396 int prop_diff = new_proportion - pane.dock_proportion;
401 int prop_borrow = dock.panes.Item(borrow_pane)->dock_proportion;
403 if (prop_borrow - prop_diff < 0) {
406 prop_borrow = min_proportion;
408 prop_borrow -= prop_diff;
411 dock.panes.Item(borrow_pane)->dock_proportion = prop_borrow;
412 pane.dock_proportion = new_proportion;
422 void OCPN_AUIManager::OnLeftUp(wxMouseEvent& event) {
423 if (m_action == actionResize) {
424 m_frame->ReleaseMouse();
426 if (!OAuiManager_HasLiveResize(*
this)) {
429 ODrawResizeHint(dc, m_0actionHintRect);
431 if (m_currentDragItem != -1 && OAuiManager_HasLiveResize(*
this))
432 m_actionPart = &(m_uiParts.Item(m_currentDragItem));
434 DoEndResizeAction(event);
436 m_currentDragItem = -1;
438 }
else if (m_action == actionClickButton) {
439 m_hoverButton = NULL;
440 m_frame->ReleaseMouse();
443 UpdateButtonOnScreen(m_actionPart, event);
446 if (m_actionPart == HitTest(event.GetX(), event.GetY())) {
448 wxAuiManagerEvent e(wxEVT_AUI_PANE_BUTTON);
450 e.SetPane(m_actionPart->pane);
452 #if wxCHECK_VERSION(3, 1, 4)
453 e.SetButton(m_actionPart->button);
455 e.SetButton(m_actionPart->button->button_id);
460 }
else if (m_action == actionClickCaption) {
461 m_frame->ReleaseMouse();
462 }
else if (m_action == actionDragFloatingPane) {
463 m_frame->ReleaseMouse();
466 else if (m_action == actionDragToolbarPane)
468 m_frame->ReleaseMouse();
470 wxAuiPaneInfo& pane = GetPane(m_actionWindow);
471 wxASSERT_MSG(pane.IsOk(), wxT(
"Pane window not found"));
474 wxAuiDockInfoPtrArray docks;
475 FindDocks(m_docks, pane.dock_direction,
476 pane.dock_layer, pane.dock_row, docks);
477 if (docks.GetCount() == 1)
479 wxAuiDockInfo& dock = *docks.Item(0);
481 wxArrayInt pane_positions, pane_sizes;
482 GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
484 int i, dock_pane_count = dock.panes.GetCount();
485 for (i = 0; i < dock_pane_count; ++i)
486 dock.panes.Item(i)->dock_pos = pane_positions[i];
489 pane.state &= ~wxAuiPaneInfo::actionPane;
497 m_action = actionNone;
498 m_lastMouseMove = wxPoint();
504 static void OCPNFindDocks(wxAuiDockInfoArray& docks,
int dock_direction,
505 int dock_layer,
int dock_row,
506 wxAuiDockInfoPtrArray& arr) {
507 int begin_layer = dock_layer;
508 int end_layer = dock_layer;
509 int begin_row = dock_row;
510 int end_row = dock_row;
511 int dock_count = docks.GetCount();
512 int layer, row, i, max_row = 0, max_layer = 0;
515 for (i = 0; i < dock_count; ++i) {
516 max_row = wxMax(max_row, docks.Item(i).dock_row);
517 max_layer = wxMax(max_layer, docks.Item(i).dock_layer);
521 if (dock_layer == -1) {
523 end_layer = max_layer;
527 if (dock_row == -1) {
534 for (layer = begin_layer; layer <= end_layer; ++layer)
535 for (row = begin_row; row <= end_row; ++row)
536 for (i = 0; i < dock_count; ++i) {
537 wxAuiDockInfo& d = docks.Item(i);
538 if (dock_direction == -1 || dock_direction == d.dock_direction) {
539 if (d.dock_layer == layer && d.dock_row == row) arr.Add(&d);
544 wxAuiDockInfo* OCPN_AUIManager::FindDock(wxAuiPaneInfo& pane) {
545 wxAuiDockInfoPtrArray arr;
546 OCPNFindDocks(m_docks, pane.dock_direction, pane.dock_layer, pane.dock_row,
554 void OCPN_AUIManager::SetDockSize(wxAuiDockInfo* dock,
int size) {
561 bool OCPN_AUIManager::ProcessDockResult(wxAuiPaneInfo& target,
562 const wxAuiPaneInfo& new_pos) {
569 if (new_pos.window->GetName().IsSameAs(_T(
"panel"))) {
571 if ( (new_pos.dock_direction ==
577 if (GetCanvasCount() > 1) {
578 if (GetCanvasIndexUnderMouse() > 0) {
579 if (new_pos.dock_layer == 0)
return false;
584 return wxAuiManager::ProcessDockResult(target, new_pos);