]> git.saurik.com Git - wxWidgets.git/blobdiff - src/aui/framemanager.cpp
Put the reentrance check inside #ifdef __DEBUG__
[wxWidgets.git] / src / aui / framemanager.cpp
index ec8eeded93ad72e0f168b614dde8972c5462737c..27e3bf941619124aeed9df3f5662bae8e1ce865b 100644 (file)
@@ -52,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
@@ -60,6 +62,8 @@ DEFINE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON)
     #include "wx/mac/private.h"
 #endif
 
+IMPLEMENT_DYNAMIC_CLASS(wxFrameManagerEvent, wxEvent)
+
 
 // -- static utility functions --
 
@@ -81,12 +85,12 @@ static void DrawResizeHint(wxDC& dc, const wxRect& rect)
     dc.DrawRectangle(rect);
 }
 
-#ifdef __WXMSW__
 
-// on supported windows systems (Win2000 and greater), this function
+// on supported windows systems (Win2000 and greater, Mac), this function
 // will make a frame window transparent by a certain amount
 static void MakeWindowTransparent(wxWindow* wnd, int amount)
 {
+#if defined(__WXMSW__)
     // 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);
@@ -117,9 +121,18 @@ static void MakeWindowTransparent(wxWindow* wnd, int amount)
         SetWindowLong(hwnd, GWL_EXSTYLE, exstyle | 0x80000 /*WS_EX_LAYERED*/);
 
     pSetLayeredWindowAttributes(hwnd, 0, (BYTE)amount, 2 /*LWA_ALPHA*/);
-}
 
+#elif defined(__WXMAC__)
+
+    WindowRef handle = GetControlOwner((OpaqueControlRef*)wnd->GetHandle());
+    SetWindowAlpha(handle, float(amount)/ 255.0);
+
+#else
+    wxUnusedVar(wnd);
+    wxUnusedVar(amount);
 #endif
+}
+
 
 
 // CopyDocksAndPanes() - this utility function creates copies of
@@ -364,6 +377,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)
@@ -377,7 +391,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();
@@ -386,9 +400,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);
     }
 }
 
@@ -486,10 +500,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"));
 
@@ -524,8 +553,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;
 }
@@ -1157,6 +1186,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);
     }
 
@@ -1782,18 +1814,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->SetPaneWindow(p);
                 p.frame = frame;
@@ -1810,7 +1839,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);
                 }
 
@@ -2033,7 +2063,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;
@@ -2413,7 +2443,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();
@@ -2422,13 +2451,11 @@ void wxFrameManager::OnHintFadeTimer(wxTimerEvent& WXUNUSED(event))
 
     m_hint_fadeamt += 5;
     MakeWindowTransparent(m_hint_wnd, m_hint_fadeamt);
-#endif
 }
 
 void wxFrameManager::ShowHint(const wxRect& rect)
 {
-#ifdef __WXMSW__
-
+#if defined(__WXMSW__) || defined(__WXMAC__)
     // First, determine if the operating system can handle transparency.
     // Transparency is available on Win2000 and above
 
@@ -2441,8 +2468,11 @@ void wxFrameManager::ShowHint(const wxRect& rect)
     // 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
+#ifdef __WXMSW__
+        && os_type == wxWINDOWS_NT && ver_major >= 5
+#endif
+        )
     {
         if (m_last_hint == rect)
             return;
@@ -2456,6 +2486,7 @@ void wxFrameManager::ShowHint(const wxRect& rect)
         {
             wxPoint pt = rect.GetPosition();
             wxSize size = rect.GetSize();
+#if defined(__WXMSW__)
             m_hint_wnd = new wxFrame(m_frame, -1, wxEmptyString, pt, size,
                                      wxFRAME_TOOL_WINDOW |
                                      wxFRAME_FLOAT_ON_PARENT |
@@ -2464,6 +2495,23 @@ void wxFrameManager::ShowHint(const wxRect& rect)
 
             MakeWindowTransparent(m_hint_wnd, initial_fade);
             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, pt, size,
+                                         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
             m_hint_wnd->Show();
 
             // if we are dragging a floating pane, set the focus
@@ -2472,10 +2520,11 @@ void wxFrameManager::ShowHint(const wxRect& rect)
                 m_action_window->SetFocus();
 
         }
-         else
+        else
         {
             MakeWindowTransparent(m_hint_wnd, initial_fade);
             m_hint_wnd->SetSize(rect);
+            m_hint_wnd->Raise();
         }
 
         if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
@@ -2489,7 +2538,7 @@ void wxFrameManager::ShowHint(const wxRect& rect)
         return;
     }
 #endif
-
+    
     if (m_last_hint != rect)
     {
         // remove the last hint rectangle
@@ -2537,8 +2586,7 @@ void wxFrameManager::ShowHint(const wxRect& rect)
 
 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);
@@ -2546,7 +2594,6 @@ void wxFrameManager::HideHint()
         m_last_hint = wxRect();
         return;
     }
-#endif
 
     // hides a painted hint by redrawing the frame window
     if (!m_last_hint.IsEmpty())
@@ -2582,6 +2629,7 @@ void wxFrameManager::DrawHintRect(wxWindow* pane_window,
     wxDockUIPartArray uiparts;
     wxPaneInfo hint = GetPane(pane_window);
     hint.name = wxT("__HINT__");
+    hint.Show();
 
     if (!hint.IsOk())
         return;
@@ -2647,10 +2695,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
 }
 
 void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd)
@@ -2752,10 +2798,8 @@ void wxFrameManager::OnFloatingPaneMoved(wxWindow* wnd)
     {
         pane.floating_pos = pane.frame->GetPosition();
 
-        #ifdef __WXMSW__
         if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
             MakeWindowTransparent(pane.frame, 255);
-        #endif
     }
 
     Update();
@@ -2772,39 +2816,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
@@ -2844,6 +2907,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__
@@ -3482,16 +3559,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())