#include "wx/aui/dockart.h"
#include "wx/aui/floatpane.h"
#include "wx/aui/tabmdi.h"
+#include "wx/aui/auibar.h"
#ifndef WX_PRECOMP
#include "wx/panel.h"
// a few defines to avoid nameclashes
#define __MAC_OS_X_MEMORY_MANAGER_CLEAN__ 1
#define __AIFF__
- #include "wx/mac/private.h"
+ #include "wx/osx/private.h"
+#endif
+
+#ifdef __WXMSW__
+ #include "wx/msw/wrapwin.h"
+ #include "wx/msw/private.h"
+ #include "wx/msw/dc.h"
#endif
IMPLEMENT_DYNAMIC_CLASS(wxAuiManagerEvent, wxEvent)
const int auiToolBarLayer = 10;
+#ifndef __WXGTK20__
+
class wxPseudoTransparentFrame : public wxFrame
{
wxRect rect(upd.GetRect());
dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
- upd++;
+ ++upd;
}
}
END_EVENT_TABLE()
+#else
+ // __WXGTK20__
+
+#include <gtk/gtk.h>
+
+static void
+gtk_pseudo_window_realized_callback( GtkWidget *m_widget, void *WXUNUSED(win) )
+{
+ wxSize disp = wxGetDisplaySize();
+ int amount = 128;
+ wxRegion region;
+ for (int y=0; y<disp.y; y++)
+ {
+ // Reverse the order of the bottom 4 bits
+ int j=((y&8)?1:0)|((y&4)?2:0)|((y&2)?4:0)|((y&1)?8:0);
+ if ((j*16+8)<amount)
+ region.Union(0, y, disp.x, 1);
+ }
+ gdk_window_shape_combine_region(m_widget->window, region.GetRegion(), 0, 0);
+}
+
+
+class wxPseudoTransparentFrame: public wxFrame
+{
+public:
+ wxPseudoTransparentFrame(wxWindow* parent = NULL,
+ wxWindowID id = wxID_ANY,
+ const wxString& title = wxEmptyString,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxDEFAULT_FRAME_STYLE,
+ const wxString &name = wxT("frame"))
+ {
+ if (!CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
+ return;
+
+ m_title = title;
+
+ m_widget = gtk_window_new( GTK_WINDOW_POPUP );
+ g_object_ref(m_widget);
+
+ if (parent) parent->AddChild(this);
+
+ g_signal_connect( m_widget, "realize",
+ G_CALLBACK (gtk_pseudo_window_realized_callback), this );
+
+ GdkColor col;
+ col.red = 128 * 256;
+ col.green = 192 * 256;
+ col.blue = 255 * 256;
+ gtk_widget_modify_bg( m_widget, GTK_STATE_NORMAL, &col );
+ }
+
+ bool SetTransparent(wxByte WXUNUSED(alpha))
+ {
+ return true;
+ }
+
+private:
+ DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxPseudoTransparentFrame, wxFrame)
+
+#endif
+ // __WXGTK20__
+
+
+
// -- static utility functions --
static wxBitmap wxPaneCreateStippleBitmap()
wxBitmap stipple = wxPaneCreateStippleBitmap();
wxBrush brush(stipple);
dc.SetBrush(brush);
+#ifdef __WXMSW__
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
+ PatBlt(GetHdcOf(*impl), rect.GetX(), rect.GetY(), rect.GetWidth(), rect.GetHeight(), PATINVERT);
+#else
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetLogicalFunction(wxXOR);
dc.DrawRectangle(rect);
+#endif
}
}
}
+/*
+// This function works fine, and may be used in the future
+
// RenumberDockRows() takes a dock and assigns sequential numbers
// to existing rows. Basically it takes out the gaps; so if a
// dock has rows with numbers 0,2,5, they will become 0,1,2
static void RenumberDockRows(wxAuiDockInfoPtrArray& docks)
{
- int i, dock_count, j, pane_count;
+ int i, dock_count;
for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
{
wxAuiDockInfo& dock = *docks.Item(i);
dock.dock_row = i;
+
+ int j, pane_count;
for (j = 0, pane_count = dock.panes.GetCount(); j < pane_count; ++j)
dock.panes.Item(j)->dock_row = i;
}
}
+*/
// SetActivePane() sets the active pane, as well as cycles through
EVT_LEFT_UP(wxAuiManager::OnLeftUp)
EVT_MOTION(wxAuiManager::OnMotion)
EVT_LEAVE_WINDOW(wxAuiManager::OnLeaveWindow)
+ EVT_MOUSE_CAPTURE_LOST(wxAuiManager::OnCaptureLost)
EVT_CHILD_FOCUS(wxAuiManager::OnChildFocus)
EVT_AUI_FIND_MANAGER(wxAuiManager::OnFindManager)
EVT_TIMER(101, wxAuiManager::OnHintFadeTimer)
wxAuiManager::~wxAuiManager()
{
+ // NOTE: It's possible that the windows have already been destroyed by the
+ // time this dtor is called, so this loop can result in memory access via
+ // invalid pointers, resulting in a crash. So it will be disabled while
+ // waiting for a better solution.
+#if 0
for ( size_t i = 0; i < m_panes.size(); i++ )
{
wxAuiPaneInfo& pinfo = m_panes[i];
if (pinfo.window && !pinfo.window->GetParent())
delete pinfo.window;
}
+#endif
delete m_art;
}
return new wxAuiFloatingFrame(parent, this, pane_info);
}
+bool wxAuiManager::CanDockPanel(const wxAuiPaneInfo & WXUNUSED(p))
+{
+ // if a key modifier is pressed while dragging the frame,
+ // don't dock the window
+ return !(wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT));
+}
+
// GetPane() looks up a wxAuiPaneInfo structure based
// on the supplied window pointer. Upon failure, GetPane()
// returns an empty wxAuiPaneInfo, a condition which can be checked
{
wxFrame* f = static_cast<wxFrame*>(w);
can_do_transparent = f->CanSetTransparent();
+
break;
}
wxDefaultPosition, wxSize(1,1),
wxFRAME_FLOAT_ON_PARENT
| wxFRAME_TOOL_WINDOW );
+ m_hint_wnd->Connect(wxEVT_ACTIVATE,
+ wxActivateEventHandler(wxAuiManager::OnHintActivate), NULL, this);
// Can't set the bg colour of a Frame in wxMac
wxPanel* p = new wxPanel(m_hint_wnd);
wxAuiPaneInfo().Name(wxT("mdiclient")).
CenterPane().PaneBorder(false));
}
- else if (m_frame->IsKindOf(CLASSINFO(wxAuiMDIParentFrame)))
+ else if (m_frame->IsKindOf(CLASSINFO(wxAuiMDIParentFrame)))
{
wxAuiMDIParentFrame* mdi_frame = (wxAuiMDIParentFrame*)m_frame;
wxAuiMDIClientWindow* client_window = mdi_frame->GetClientWindow();
bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info)
{
+ wxASSERT_MSG(window, wxT("NULL window ptrs are not allowed"));
+
// check if the pane has a valid window
if (!window)
return false;
if (pinfo.name.empty() || already_exists)
{
pinfo.name.Printf(wxT("%08lx%08x%08x%08lx"),
- ((unsigned long)pinfo.window) & 0xffffffff,
+ wxPtrToUInt(pinfo.window) & 0xffffffff,
(unsigned int)time(NULL),
#ifdef __WXWINCE__
(unsigned int)GetTickCount(),
button.button_id = wxAUI_BUTTON_CLOSE;
pinfo.buttons.Add(button);
}
+
+ if (pinfo.HasGripper())
+ {
+ if (pinfo.window->IsKindOf(CLASSINFO(wxAuiToolBar)))
+ {
+ // prevent duplicate gripper -- both wxAuiManager and wxAuiToolBar
+ // have a gripper control. The toolbar's built-in gripper
+ // meshes better with the look and feel of the control than ours,
+ // so turn wxAuiManager's gripper off, and the toolbar's on.
+
+ wxAuiToolBar* tb = static_cast<wxAuiToolBar*>(pinfo.window);
+ pinfo.SetFlag(wxAuiPaneInfo::optionGripper, false);
+ tb->SetGripperVisible(true);
+ }
+ }
+
if (pinfo.best_size == wxDefaultSize &&
pinfo.window)
// I believe this to be the correct action, until
// wxToolBar::GetBestSize() is fixed. Is this assumption
// correct?
- pinfo.best_size.y++;
+ // commented out by JACS 2007-9-08 after having added a pixel in wxMSW's wxToolBar::DoGetBestSize()
+ // pinfo.best_size.y++;
}
if (pinfo.min_size != wxDefaultSize)
}
}
+
+
return true;
}
bool wxAuiManager::InsertPane(wxWindow* window, const wxAuiPaneInfo& pane_info,
int insert_level)
{
+ wxASSERT_MSG(window, wxT("NULL window ptrs are not allowed"));
+
// shift the panes around, depending on the insert level
switch (insert_level)
{
// method will not destroy the window that is removed.
bool wxAuiManager::DetachPane(wxWindow* window)
{
+ wxASSERT_MSG(window, wxT("NULL window ptrs are not allowed"));
+
int i, count;
for (i = 0, count = m_panes.GetCount(); i < count; ++i)
{
return false;
}
-// ClosePane() destroys or hides the pane depending on its
-// flags
+// ClosePane() destroys or hides the pane depending on its flags
void wxAuiManager::ClosePane(wxAuiPaneInfo& pane_info)
{
// if we were maximized, restore
if (!p.IsOk())
{
// the pane window couldn't be found
- // in the existing layout
- return false;
+ // in the existing layout -- skip it
+ continue;
}
p.SafeSet(pane);
-
}
if (update)
{
wxAuiPaneInfo& pane = *(dock.panes.Item(pane_i));
- if (pane.state & wxAuiPaneInfo::actionPane)
+ if (pane.HasFlag(wxAuiPaneInfo::actionPane))
{
wxASSERT_MSG(action_pane==-1, wxT("Too many fixed action panes"));
action_pane = pane_i;
dock.fixed = false;
if (!pane.IsToolbar())
dock.toolbar = false;
- if (pane.state & wxAuiPaneInfo::actionPane)
+ if (pane.HasFlag(wxAuiPaneInfo::optionDockFixed))
+ dock.fixed = true;
+ if (pane.HasFlag(wxAuiPaneInfo::actionPane))
action_pane_marked = true;
}
// find any top docks in this layer
FindDocks(docks, wxAUI_DOCK_TOP, layer, -1, arr);
- RenumberDockRows(arr);
if (!arr.IsEmpty())
{
for (row = 0, row_count = arr.GetCount(); row < row_count; ++row)
// find any left docks in this layer
FindDocks(docks, wxAUI_DOCK_LEFT, layer, -1, arr);
- RenumberDockRows(arr);
if (!arr.IsEmpty())
{
for (row = 0, row_count = arr.GetCount(); row < row_count; ++row)
// find any right docks in this layer
FindDocks(docks, wxAUI_DOCK_RIGHT, layer, -1, arr);
- RenumberDockRows(arr);
if (!arr.IsEmpty())
{
for (row = arr.GetCount()-1; row >= 0; --row)
LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
}
- cont->Add(middle, 1, wxEXPAND);
-
+ if (middle->GetChildren().GetCount() > 0)
+ cont->Add(middle, 1, wxEXPAND);
+ else
+ delete middle;
+
// find any bottom docks in this layer
FindDocks(docks, wxAUI_DOCK_BOTTOM, layer, -1, arr);
- RenumberDockRows(arr);
if (!arr.IsEmpty())
{
for (row = arr.GetCount()-1; row >= 0; --row)
void wxAuiManager::Update()
{
+ m_hover_button = NULL;
+ m_action_part = NULL;
+
wxSizer* sizer;
int i, pane_count = m_panes.GetCount();
p.window->SetSize(1,1);
- // the following block is a workaround for bug #1531361
- // (see wxWidgets sourceforge page). On wxGTK (only), when
- // a frame is shown/hidden, a move event unfortunately
- // also gets fired. Because we may be dragging around
- // a pane, we need to cancel that action here to prevent
- // a spurious crash.
- if (m_action_window == p.frame)
- {
- if (wxWindow::GetCapture() == m_frame)
+ // the following block is a workaround for bug #1531361
+ // (see wxWidgets sourceforge page). On wxGTK (only), when
+ // a frame is shown/hidden, a move event unfortunately
+ // also gets fired. Because we may be dragging around
+ // a pane, we need to cancel that action here to prevent
+ // a spurious crash.
+ if (m_action_window == p.frame)
+ {
+ if (wxWindow::GetCapture() == m_frame)
m_frame->ReleaseMouse();
m_action = actionNone;
- m_action_window = NULL;
- }
+ m_action_window = NULL;
+ }
- // hide the frame
+ // hide the frame
if (p.frame->IsShown())
p.frame->Show(false);
{
// frame already exists, make sure it's position
// and size reflect the information in wxAuiPaneInfo
- if (p.frame->GetPosition() != p.floating_pos)
+ if ((p.frame->GetPosition() != p.floating_pos) || (p.frame->GetSize() != p.floating_size))
{
p.frame->SetSize(p.floating_pos.x, p.floating_pos.y,
p.floating_size.x, p.floating_size.y,
(part->dock->dock_direction != wxAUI_DOCK_CENTER &&
part->dock->dock_direction != wxAUI_DOCK_NONE)))
{
- drop.Float();
+ if (drop.IsFloatable())
+ drop.Float();
}
m_skipping = false;
return ProcessDockResult(target, drop);
}
- else
- {
- m_skipping = false;
- }
- if (!m_skipping)
- {
- m_last_rect = part->dock->rect;
- m_last_rect.Inflate( 15, 15 );
- }
+ m_skipping = false;
+
+ m_last_rect = part->dock->rect;
+ m_last_rect.Inflate( 15, 15 );
drop.Dock().
Direction(part->dock->dock_direction).
// nasty redrawn problems.
clip.Intersect(m_frame->GetRect());
- screendc.SetClippingRegion(clip);
+ screendc.SetDeviceClippingRegion(clip);
wxBitmap stipple = wxPaneCreateStippleBitmap();
wxBrush brush(stipple);
}
}
+void wxAuiManager::OnHintActivate(wxActivateEvent& WXUNUSED(event))
+{
+ // Do nothing so this event isn't handled in the base handlers.
+
+ // Letting the hint window activate without this handler can lead to
+ // weird behavior on Mac where the menu is switched out to the top
+ // window's menu in MDI applications when it shouldn't be. So since
+ // we don't want user interaction with the hint window anyway, we just
+ // prevent it from activating here.
+}
+
void wxAuiManager::StartPaneDrag(wxWindow* pane_window,
// no hint for toolbar floating windows
if (pane.IsToolbar() && m_action == actionDragFloatingPane)
{
- if (m_action == actionDragFloatingPane)
- {
- wxAuiDockInfoArray docks;
- wxAuiPaneInfoArray panes;
- wxAuiDockUIPartArray uiparts;
- wxAuiPaneInfo hint = pane;
+ wxAuiDockInfoArray docks;
+ wxAuiPaneInfoArray panes;
+ wxAuiDockUIPartArray uiparts;
+ wxAuiPaneInfo hint = pane;
- CopyDocksAndPanes(docks, panes, m_docks, m_panes);
+ CopyDocksAndPanes(docks, panes, m_docks, m_panes);
- // find out where the new pane would be
- if (!DoDrop(docks, panes, hint, client_pt))
- return;
- if (hint.IsFloating())
- return;
+ // find out where the new pane would be
+ if (!DoDrop(docks, panes, hint, client_pt))
+ return;
+ if (hint.IsFloating())
+ return;
- pane = hint;
- m_action = actionDragToolbarPane;
- m_action_window = pane.window;
+ pane = hint;
+ m_action = actionDragToolbarPane;
+ m_action_window = pane.window;
- Update();
- }
+ Update();
return;
}
// if a key modifier is pressed while dragging the frame,
// don't dock the window
- if (wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT))
+ if (!CanDockPanel(pane))
{
HideHint();
return;
wxPoint frame_pos = pane.frame->GetPosition();
wxPoint action_offset(pt.x-frame_pos.x, pt.y-frame_pos.y);
-
// if a key modifier is pressed while dragging the frame,
// don't dock the window
- if (!wxGetKeyState(WXK_CONTROL) && !wxGetKeyState(WXK_ALT))
+ if (CanDockPanel(pane))
{
// do the drop calculation
DoDrop(m_docks, m_panes, pane, client_pt, action_offset);
}
else
{
- ClosePane(pane);
+ // close the pane, but check that it
+ // still exists in our pane array first
+ // (the event handler above might have removed it)
+
+ wxAuiPaneInfo& check = GetPane(wnd);
+ if (check.IsOk())
+ {
+ ClosePane(pane);
+ }
}
}
void wxAuiManager::OnFloatingPaneActivated(wxWindow* wnd)
{
- if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
+ if ((GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE) && GetPane(wnd).IsOk())
{
- // try to find the pane
- wxASSERT_MSG(GetPane(wnd).IsOk(), wxT("Pane window not found"));
-
SetActivePane(m_panes, wnd);
Repaint();
}
{
// if the frame is about to be deleted, don't bother
if (!m_frame || wxPendingDelete.Member(m_frame))
- return;
-
+ return;
+
wxDC* dc = evt.GetDC();
#ifdef __WXMAC__
{
wxAuiDockUIPart& part = m_uiparts.Item(i);
- // don't draw hidden pane items
- if (part.sizer_item && !part.sizer_item->IsShown())
+ // don't draw hidden pane items or items that aren't windows
+ if (part.sizer_item && ((!part.sizer_item->IsWindow() && !part.sizer_item->IsSpacer() && !part.sizer_item->IsSizer()) || !part.sizer_item->IsShown()))
continue;
switch (part.type)
if (part->type == wxAuiDockUIPart::typeDockSizer ||
part->type == wxAuiDockUIPart::typePaneSizer)
{
- if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER)
- return;
+ // Removing this restriction so that a centre pane can be resized
+ //if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER)
+ // return;
// a dock may not be resized if it has a single
// pane which is not resizable
- if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER)
- return;
-
if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
{
// set the caption as active
Repaint();
}
+ if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER)
+ return;
+
m_action = actionClickCaption;
m_action_part = part;
m_action_start = wxPoint(event.m_x, event.m_y);
{
m_hover_button = NULL;
m_frame->ReleaseMouse();
- UpdateButtonOnScreen(m_action_part, event);
-
- // make sure we're still over the item that was originally clicked
- if (m_action_part == HitTest(event.GetX(), event.GetY()))
+
+ if (m_action_part)
{
- // fire button-click event
- wxAuiManagerEvent e(wxEVT_AUI_PANE_BUTTON);
- e.SetManager(this);
- e.SetPane(m_action_part->pane);
- e.SetButton(m_action_part->button->button_id);
- ProcessMgrEvent(e);
+ UpdateButtonOnScreen(m_action_part, event);
+
+ // make sure we're still over the item that was originally clicked
+ if (m_action_part == HitTest(event.GetX(), event.GetY()))
+ {
+ // fire button-click event
+ wxAuiManagerEvent e(wxEVT_AUI_PANE_BUTTON);
+ e.SetManager(this);
+ e.SetPane(m_action_part->pane);
+ e.SetButton(m_action_part->button->button_id);
+ ProcessMgrEvent(e);
+ }
}
}
else if (m_action == actionClickCaption)
if (m_action == actionResize)
{
- wxPoint pos = m_action_part->rect.GetPosition();
- if (m_action_part->orientation == wxHORIZONTAL)
- pos.y = wxMax(0, event.m_y - m_action_offset.y);
- else
- pos.x = wxMax(0, event.m_x - m_action_offset.x);
+ if (m_action_part)
+ {
+ wxPoint pos = m_action_part->rect.GetPosition();
+ if (m_action_part->orientation == wxHORIZONTAL)
+ pos.y = wxMax(0, event.m_y - m_action_offset.y);
+ else
+ pos.x = wxMax(0, event.m_x - m_action_offset.x);
- wxRect rect(m_frame->ClientToScreen(pos),
- m_action_part->rect.GetSize());
+ wxRect rect(m_frame->ClientToScreen(pos),
+ m_action_part->rect.GetSize());
- wxScreenDC dc;
- if (!m_action_hintrect.IsEmpty())
- DrawResizeHint(dc, m_action_hintrect);
- DrawResizeHint(dc, rect);
- m_action_hintrect = rect;
+ wxScreenDC dc;
+ if (!m_action_hintrect.IsEmpty())
+ DrawResizeHint(dc, m_action_hintrect);
+ DrawResizeHint(dc, rect);
+ m_action_hintrect = rect;
+ }
}
else if (m_action == actionClickCaption)
{
// caption has been clicked. we need to check if the mouse
// is now being dragged. if it is, we need to change the
// mouse action to 'drag'
- if (abs(event.m_x - m_action_start.x) > drag_x_threshold ||
- abs(event.m_y - m_action_start.y) > drag_y_threshold)
+ if (m_action_part &&
+ (abs(event.m_x - m_action_start.x) > drag_x_threshold ||
+ abs(event.m_y - m_action_start.y) > drag_y_threshold))
{
wxAuiPaneInfo* pane_info = m_action_part->pane;
wxAuiPaneInfo& pane = GetPane(m_action_window);
wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
- pane.state |= wxAuiPaneInfo::actionPane;
+ pane.SetFlag(wxAuiPaneInfo::actionPane, true);
wxPoint pt = event.GetPosition();
DoDrop(m_docks, m_panes, pane, pt, m_action_offset);
}
}
+void wxAuiManager::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
+{
+ // cancel the operation in progress, if any
+ if ( m_action != actionNone )
+ {
+ m_action = actionNone;
+ HideHint();
+ }
+}
+
void wxAuiManager::OnChildFocus(wxChildFocusEvent& event)
{
// when a child pane has it's focus set, we should change the
// active panes are allowed by the owner)
if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
{
- if (GetPane(event.GetWindow()).IsOk())
+ wxAuiPaneInfo& pane = GetPane(event.GetWindow());
+ if (pane.IsOk() && (pane.state & wxAuiPaneInfo::optionActive) == 0)
{
SetActivePane(m_panes, event.GetWindow());
m_frame->Refresh();
if (!e.GetVeto())
{
- ClosePane(pane);
+ // close the pane, but check that it
+ // still exists in our pane array first
+ // (the event handler above might have removed it)
+
+ wxAuiPaneInfo& check = GetPane(pane.window);
+ if (check.IsOk())
+ {
+ ClosePane(pane);
+ }
+
Update();
}
}