X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cc0196c7944434aa873835b9a70ee0e23f3a38d3..177df6c5f6c24251cab056ce39e206ec3fd6b44b:/src/aui/framemanager.cpp diff --git a/src/aui/framemanager.cpp b/src/aui/framemanager.cpp index 99614d7638..3079df6dba 100644 --- a/src/aui/framemanager.cpp +++ b/src/aui/framemanager.cpp @@ -36,12 +36,9 @@ #include "wx/dcscreen.h" #include "wx/toolbar.h" #include "wx/mdi.h" + #include "wx/image.h" #endif -//#include "wx/dcbuffer.h" - -#include "wx/image.h" - WX_CHECK_BUILD_OPTIONS("wxAUI") #include "wx/arrimpl.cpp" @@ -55,6 +52,8 @@ WX_DEFINE_OBJARRAY(wxPaneInfoArray) wxPaneInfo wxNullPaneInfo; wxDockInfo wxNullDockInfo; DEFINE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON) +DEFINE_EVENT_TYPE(wxEVT_AUI_PANECLOSE) +DEFINE_EVENT_TYPE(wxEVT_AUI_RENDER) #ifdef __WXMAC__ // a few defines to avoid nameclashes @@ -63,6 +62,8 @@ DEFINE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON) #include "wx/mac/private.h" #endif +IMPLEMENT_DYNAMIC_CLASS(wxFrameManagerEvent, wxEvent) + // -- static utility functions -- @@ -84,39 +85,6 @@ static void DrawResizeHint(wxDC& dc, const wxRect& rect) dc.DrawRectangle(rect); } -#ifdef __WXMSW__ - -// on supported windows systems (Win2000 and greater), this function -// will make a frame window transparent by a certain amount -static void MakeWindowTransparent(wxWindow* wnd, int amount) -{ - // this API call is not in all SDKs, only the newer ones, so - // we will runtime bind this - typedef DWORD (WINAPI *PSETLAYEREDWINDOWATTR)(HWND, DWORD, BYTE, DWORD); - static PSETLAYEREDWINDOWATTR pSetLayeredWindowAttributes = NULL; - static HMODULE h = NULL; - HWND hwnd = (HWND)wnd->GetHWND(); - - if (!h) - h = LoadLibrary(_T("user32")); - - if (!pSetLayeredWindowAttributes) - { - pSetLayeredWindowAttributes = - (PSETLAYEREDWINDOWATTR)GetProcAddress(h,"SetLayeredWindowAttributes"); - } - - if (pSetLayeredWindowAttributes == NULL) - return; - - LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); - if (0 == (exstyle & 0x80000) /*WS_EX_LAYERED*/) - SetWindowLong(hwnd, GWL_EXSTYLE, exstyle | 0x80000 /*WS_EX_LAYERED*/); - - pSetLayeredWindowAttributes(hwnd, 0, (BYTE)amount, 2 /*LWA_ALPHA*/); -} - -#endif // CopyDocksAndPanes() - this utility function creates copies of @@ -361,6 +329,7 @@ static int PaneSortFunc(wxPaneInfo** p1, wxPaneInfo** p2) BEGIN_EVENT_TABLE(wxFrameManager, wxEvtHandler) EVT_AUI_PANEBUTTON(wxFrameManager::OnPaneButton) + EVT_AUI_RENDER(wxFrameManager::OnRender) EVT_PAINT(wxFrameManager::OnPaint) EVT_ERASE_BACKGROUND(wxFrameManager::OnEraseBackground) EVT_SIZE(wxFrameManager::OnSize) @@ -374,7 +343,7 @@ BEGIN_EVENT_TABLE(wxFrameManager, wxEvtHandler) END_EVENT_TABLE() -wxFrameManager::wxFrameManager(wxFrame* frame, unsigned int flags) +wxFrameManager::wxFrameManager(wxWindow* managed_wnd, unsigned int flags) { m_action = actionNone; m_last_mouse_move = wxPoint(); @@ -383,9 +352,9 @@ wxFrameManager::wxFrameManager(wxFrame* frame, unsigned int flags) m_hint_wnd = NULL; m_flags = flags; - if (frame) + if (managed_wnd) { - SetFrame(frame); + SetManagedWindow(managed_wnd); } } @@ -483,10 +452,25 @@ unsigned int wxFrameManager::GetFlags() const } -// SetFrame() is usually called once when the frame +// don't use these anymore as they are deprecated +// use Set/GetManagedFrame() instead +void wxFrameManager::SetFrame(wxFrame* frame) +{ + SetManagedWindow((wxWindow*)frame); +} + +wxFrame* wxFrameManager::GetFrame() const +{ + return (wxFrame*)m_frame; +} + + + + +// SetManagedWindow() is usually called once when the frame // manager class is being initialized. "frame" specifies // the frame which should be managed by the frame mananger -void wxFrameManager::SetFrame(wxFrame* frame) +void wxFrameManager::SetManagedWindow(wxWindow* frame) { wxASSERT_MSG(frame, wxT("specified frame must be non-NULL")); @@ -510,6 +494,40 @@ void wxFrameManager::SetFrame(wxFrame* frame) CenterPane().PaneBorder(false)); } #endif + + // Make a window to use for a translucent hint +#if defined(__WXMSW__) + m_hint_wnd = new wxFrame(m_frame, -1, wxEmptyString, wxDefaultPosition, wxSize(1,1), + wxFRAME_TOOL_WINDOW | + wxFRAME_FLOAT_ON_PARENT | + wxFRAME_NO_TASKBAR | + wxNO_BORDER); + + m_hint_wnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION)); + +#elif defined(__WXMAC__) + // Using a miniframe with float and tool styles keeps the parent + // frame activated and highlighted as such... + m_hint_wnd = new wxMiniFrame(m_frame, -1, wxEmptyString, wxDefaultPosition, wxSize(1,1), + wxFRAME_FLOAT_ON_PARENT + | wxFRAME_TOOL_WINDOW + | wxCAPTION ); + + // Can't set the bg colour of a Frame in wxMac + wxPanel* p = new wxPanel(m_hint_wnd); + + // The default wxSYS_COLOUR_ACTIVECAPTION colour is a light silver + // color that is really hard to see, especially transparent. + // Until a better system color is decided upon we'll just use + // blue. + p->SetBackgroundColour(*wxBLUE); +#endif + + if (m_hint_wnd && !m_hint_wnd->CanSetTranslucency()) + { + m_hint_wnd->Close(); + m_hint_wnd = NULL; + } } @@ -521,8 +539,8 @@ void wxFrameManager::UnInit() m_frame->RemoveEventHandler(this); } -// GetFrame() returns the frame pointer being managed by wxFrameManager -wxFrame* wxFrameManager::GetFrame() const +// GetManagedWindow() returns the window pointer being managed +wxWindow* wxFrameManager::GetManagedWindow() const { return m_frame; } @@ -582,7 +600,11 @@ bool wxFrameManager::AddPane(wxWindow* window, const wxPaneInfo& pane_info) pinfo.name.Printf(wxT("%08lx%08x%08x%08lx"), ((unsigned long)pinfo.window) & 0xffffffff, (unsigned int)time(NULL), +#ifdef __WXWINCE__ + (unsigned int)GetTickCount(), +#else (unsigned int)clock(), +#endif (unsigned long)m_panes.GetCount()); } @@ -647,6 +669,20 @@ bool wxFrameManager::AddPane(wxWindow* window, return AddPane(window, pinfo); } +bool wxFrameManager::AddPane(wxWindow* window, + const wxPaneInfo& pane_info, + const wxPoint& drop_pos) +{ + if (!AddPane(window, pane_info)) + return false; + + wxPaneInfo& pane = GetPane(window); + + DoDrop(m_docks, m_panes, pane, drop_pos, wxPoint(0,0)); + + return true; +} + bool wxFrameManager::InsertPane(wxWindow* window, const wxPaneInfo& pane_info, int insert_level) { @@ -728,6 +764,24 @@ bool wxFrameManager::DetachPane(wxWindow* window) p.frame->Destroy(); p.frame = NULL; } + + // make sure there are no references to this pane in our uiparts, + // just in case the caller doesn't call Update() immediately after + // the DetachPane() call. This prevets obscure crashes which would + // happen at window repaint if the caller forgets to call Update() + int pi, part_count; + for (pi = 0, part_count = (int)m_uiparts.GetCount(); pi < part_count; ++pi) + { + wxDockUIPart& part = m_uiparts.Item(pi); + if (part.pane == &p) + { + m_uiparts.RemoveAt(pi); + part_count--; + pi--; + continue; + } + } + m_panes.RemoveAt(i); return true; } @@ -1150,6 +1204,9 @@ void wxFrameManager::LayoutAddPane(wxSizer* cont, else { sizer_item = vert_pane_sizer->Add(pane.window, 1, wxEXPAND); + // Don't do this because it breaks the pane size in floating windows + // BIW: Right now commenting this out is causing problems with + // an mdi client window as the center pane. vert_pane_sizer->SetItemMinSize(pane.window, 1, 1); } @@ -1775,18 +1832,15 @@ void wxFrameManager::Update() // we need to create a frame for this // pane, which has recently been floated wxFloatingPane* frame = new wxFloatingPane(m_frame, - this, -1, - p.floating_pos, - p.floating_size); + this, + p); - // on MSW, if the owner desires transparent dragging, and + // on MSW and Mac, if the owner desires transparent dragging, and // the dragging is happening right now, then the floating // window should have this style by default -#ifdef __WXMSW__ if (m_action == actionDragFloatingPane && (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)) - MakeWindowTransparent(frame, 150); -#endif + frame->SetTranslucency(150); frame->SetPaneWindow(p); p.frame = frame; @@ -1803,7 +1857,8 @@ void wxFrameManager::Update() if (p.frame->GetPosition() != p.floating_pos) { p.frame->SetSize(p.floating_pos.x, p.floating_pos.y, - -1, -1, wxSIZE_USE_EXISTING); + wxDefaultCoord, wxDefaultCoord, + wxSIZE_USE_EXISTING); //p.frame->Move(p.floating_pos.x, p.floating_pos.y); } @@ -2026,7 +2081,7 @@ int wxFrameManager::GetDockPixelOffset(wxPaneInfo& test) // if a dock operation is allowed, the new dock position is copied into // the target info. If the operation was allowed, the function returns true. -static bool ProcessDockResult(wxPaneInfo& target, +bool wxFrameManager::ProcessDockResult(wxPaneInfo& target, const wxPaneInfo& new_pos) { bool allowed = false; @@ -2406,7 +2461,6 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks, void wxFrameManager::OnHintFadeTimer(wxTimerEvent& WXUNUSED(event)) { -#ifdef __WXMSW__ if (!m_hint_wnd || m_hint_fadeamt >= 50) { m_hint_fadetimer.Stop(); @@ -2414,28 +2468,12 @@ void wxFrameManager::OnHintFadeTimer(wxTimerEvent& WXUNUSED(event)) } m_hint_fadeamt += 5; - MakeWindowTransparent(m_hint_wnd, m_hint_fadeamt); -#endif + m_hint_wnd->SetTranslucency(m_hint_fadeamt); } void wxFrameManager::ShowHint(const wxRect& rect) { -#ifdef __WXMSW__ - - // First, determine if the operating system can handle transparency. - // Transparency is available on Win2000 and above - - static int os_type = -1; - static int ver_major = -1; - - if (os_type == -1) - os_type = ::wxGetOsVersion(&ver_major); - - // If the transparent flag is set, and the OS supports it, - // go ahead and use a transparent hint - - if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0 && - os_type == wxWINDOWS_NT && ver_major >= 5) + if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0 && m_hint_wnd) { if (m_last_hint == rect) return; @@ -2445,31 +2483,18 @@ void wxFrameManager::ShowHint(const wxRect& rect) if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE) initial_fade = 0; - if (m_hint_wnd == NULL) - { - wxPoint pt = rect.GetPosition(); - wxSize size = rect.GetSize(); - m_hint_wnd = new wxFrame(m_frame, -1, wxEmptyString, pt, size, - wxFRAME_TOOL_WINDOW | - wxFRAME_FLOAT_ON_PARENT | - wxFRAME_NO_TASKBAR | - wxNO_BORDER); - - MakeWindowTransparent(m_hint_wnd, initial_fade); - m_hint_wnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION)); + if (! m_hint_wnd->IsShown()) m_hint_wnd->Show(); - // if we are dragging a floating pane, set the focus - // back to that floating pane (otherwise it becomes unfocused) - if (m_action == actionDragFloatingPane && m_action_window) - m_action_window->SetFocus(); + // if we are dragging a floating pane, set the focus + // back to that floating pane (otherwise it becomes unfocused) + if (m_action == actionDragFloatingPane && m_action_window) + m_action_window->SetFocus(); - } - else - { - MakeWindowTransparent(m_hint_wnd, initial_fade); - m_hint_wnd->SetSize(rect); - } + m_hint_wnd->SetTranslucency(initial_fade); + m_hint_wnd->SetSize(rect); + m_hint_wnd->Raise(); + if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE) { @@ -2478,68 +2503,67 @@ void wxFrameManager::ShowHint(const wxRect& rect) m_hint_fadetimer.SetOwner(this, 101); m_hint_fadetimer.Start(5); } - - return; } -#endif - if (m_last_hint != rect) + else // Not using a translucent hint window... { - // remove the last hint rectangle - m_last_hint = rect; - m_frame->Refresh(); - m_frame->Update(); - } - - wxScreenDC screendc; - wxRegion clip(1, 1, 10000, 10000); + + if (m_last_hint != rect) + { + // remove the last hint rectangle + m_last_hint = rect; + m_frame->Refresh(); + m_frame->Update(); + } - // clip all floating windows, so we don't draw over them - int i, pane_count; - for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i) - { - wxPaneInfo& pane = m_panes.Item(i); + wxScreenDC screendc; + wxRegion clip(1, 1, 10000, 10000); - if (pane.IsFloating() && - pane.frame->IsShown()) + // clip all floating windows, so we don't draw over them + int i, pane_count; + for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i) { - wxRect rect = pane.frame->GetRect(); - #ifdef __WXGTK__ - // wxGTK returns the client size, not the whole frame size - rect.width += 15; - rect.height += 35; - rect.Inflate(5); - #endif + wxPaneInfo& pane = m_panes.Item(i); - clip.Subtract(rect); + if (pane.IsFloating() && + pane.frame->IsShown()) + { + wxRect rect = pane.frame->GetRect(); +#ifdef __WXGTK__ + // wxGTK returns the client size, not the whole frame size + rect.width += 15; + rect.height += 35; + rect.Inflate(5); +#endif + + clip.Subtract(rect); + } } - } - screendc.SetClippingRegion(clip); + screendc.SetClippingRegion(clip); - wxBitmap stipple = wxPaneCreateStippleBitmap(); - wxBrush brush(stipple); - screendc.SetBrush(brush); - screendc.SetPen(*wxTRANSPARENT_PEN); + wxBitmap stipple = wxPaneCreateStippleBitmap(); + wxBrush brush(stipple); + screendc.SetBrush(brush); + screendc.SetPen(*wxTRANSPARENT_PEN); - screendc.DrawRectangle(rect.x, rect.y, 5, rect.height); - screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5); - screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height); - screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5); + screendc.DrawRectangle(rect.x, rect.y, 5, rect.height); + screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5); + screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height); + screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5); + } } void wxFrameManager::HideHint() { - // hides a transparent window hint (currently wxMSW only) -#ifdef __WXMSW__ + // hides a transparent window hint, if there is one if (m_hint_wnd) { - MakeWindowTransparent(m_hint_wnd, 0); + m_hint_wnd->SetTranslucency(0); m_hint_fadetimer.Stop(); m_last_hint = wxRect(); return; } -#endif // hides a painted hint by redrawing the frame window if (!m_last_hint.IsEmpty()) @@ -2575,6 +2599,7 @@ void wxFrameManager::DrawHintRect(wxWindow* pane_window, wxDockUIPartArray uiparts; wxPaneInfo hint = GetPane(pane_window); hint.name = wxT("__HINT__"); + hint.Show(); if (!hint.IsOk()) return; @@ -2640,10 +2665,8 @@ void wxFrameManager::OnFloatingPaneMoveStart(wxWindow* wnd) wxPaneInfo& pane = GetPane(wnd); wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found")); -#ifdef __WXMSW__ if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG) - MakeWindowTransparent(pane.frame, 150); -#endif + pane.frame->SetTranslucency(150); } void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd) @@ -2729,26 +2752,20 @@ void wxFrameManager::OnFloatingPaneMoved(wxWindow* wnd) // if a key modifier is pressed while dragging the frame, // don't dock the window - if (wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT)) + if (!wxGetKeyState(WXK_CONTROL) && !wxGetKeyState(WXK_ALT)) { - HideHint(); - return; + // do the drop calculation + DoDrop(m_docks, m_panes, pane, client_pt, action_offset); } - - - // do the drop calculation - DoDrop(m_docks, m_panes, pane, client_pt, action_offset); - + // if the pane is still floating, update it's floating // position (that we store) if (pane.IsFloating()) { pane.floating_pos = pane.frame->GetPosition(); - #ifdef __WXMSW__ if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG) - MakeWindowTransparent(pane.frame, 255); - #endif + pane.frame->SetTranslucency(255); } Update(); @@ -2765,39 +2782,58 @@ void wxFrameManager::OnFloatingPaneResized(wxWindow* wnd, const wxSize& size) pane.floating_size = size; } -void wxFrameManager::OnFloatingPaneClosed(wxWindow* wnd) + +void wxFrameManager::OnFloatingPaneClosed(wxWindow* wnd, wxCloseEvent& evt) { // try to find the pane wxPaneInfo& pane = GetPane(wnd); wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found")); - // reparent the pane window back to us and - // prepare the frame window for destruction - pane.window->Show(false); - pane.window->Reparent(m_frame); - pane.frame = NULL; - pane.Hide(); + + // fire pane close event + wxFrameManagerEvent e(wxEVT_AUI_PANECLOSE); + e.SetPane(&pane); + e.SetCanVeto(evt.CanVeto()); + ProcessMgrEvent(e); + + if (e.GetVeto()) + { + evt.Veto(); + return; + } + else + { + // reparent the pane window back to us and + // prepare the frame window for destruction + pane.window->Show(false); + pane.window->Reparent(m_frame); + pane.frame = NULL; + pane.Hide(); + } } + + void wxFrameManager::OnFloatingPaneActivated(wxWindow* wnd) { if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE) { // try to find the pane - wxPaneInfo& pane = GetPane(wnd); - wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found")); + wxASSERT_MSG(GetPane(wnd).IsOk(), wxT("Pane window not found")); SetActivePane(m_panes, wnd); Repaint(); } } -// Render() draws all of the pane captions, sashes, +// OnRender() draws all of the pane captions, sashes, // backgrounds, captions, grippers, pane borders and buttons. // It renders the entire user interface. -void wxFrameManager::Render(wxDC* dc) +void wxFrameManager::OnRender(wxFrameManagerEvent& evt) { + wxDC* dc = evt.GetDC(); + #ifdef __WXMAC__ dc->Clear() ; #endif @@ -2837,6 +2873,20 @@ void wxFrameManager::Render(wxDC* dc) } } + +// Render() fire a render event, which is normally handled by +// wxFrameManager::OnRender(). This allows the render function to +// be overridden via the render event. This can be useful for paintin +// custom graphics in the main window. Default behavior can be +// invoked in the overridden function by calling OnRender() + +void wxFrameManager::Render(wxDC* dc) +{ + wxFrameManagerEvent e(wxEVT_AUI_RENDER); + e.SetDC(dc); + ProcessMgrEvent(e); +} + void wxFrameManager::Repaint(wxDC* dc) { #ifdef __WXMAC__ @@ -3475,16 +3525,26 @@ void wxFrameManager::OnChildFocus(wxChildFocusEvent& event) // OnPaneButton() is an event handler that is called // when a pane button has been pressed. -void wxFrameManager::OnPaneButton(wxFrameManagerEvent& event) +void wxFrameManager::OnPaneButton(wxFrameManagerEvent& evt) { - wxPaneInfo& pane = *(event.pane); + wxASSERT_MSG(evt.pane, wxT("Pane Info passed to wxFrameManager::OnPaneButton must be non-null")); - if (event.button == wxPaneInfo::buttonClose) + wxPaneInfo& pane = *(evt.pane); + + if (evt.button == wxPaneInfo::buttonClose) { - pane.Hide(); - Update(); + // fire pane close event + wxFrameManagerEvent e(wxEVT_AUI_PANECLOSE); + e.SetPane(evt.pane); + ProcessMgrEvent(e); + + if (!e.GetVeto()) + { + pane.Hide(); + Update(); + } } - else if (event.button == wxPaneInfo::buttonPin) + else if (evt.button == wxPaneInfo::buttonPin) { if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) && pane.IsFloatable())