Kirix Support Forums

Closing a Pane Through a Child Window

Please post all general questions, comments, bug reports, and any other wxAUI feedback here.

Closing a Pane Through a Child Window

Postby stimpy on Wed Sep 06, 2006 8:25 pm

I've been toying with this for a day now and I'm curious what an accepted practice would be.

The scenario is this. I need to simulate pressing the X button of a pane. I need to do it whether it is floating or not. Currently, clicking the X as a floating pane calls OnClose. However, when the X is clicked while docked, the button press is emulated and handled through OnPaneButton. Since the two are completely different code paths, how does one click with X button without actually using the mouse?

A couple possibilities exist:
  • Pass a reference of the wxFrameManager into the child window, build a wxFrameManagerEvent event, and pass it to the parent. This also requires a wxFrameManagerEvent event handler inside wxFloatingPanel so Destroy can be called properly.
  • Create a different event type that can be sent without populating a wxPaneInfo member (similar to how DetachPane works with a wxWindow *). Add a wxClosePaneEvent (or whatever) to both wxFrameManager and wxFloatingPane and redesign ProcessMgrEvent to handle more events than just wxFrameManagerEvents. A message could then be sent to the parent like normal.
  • Pass a reference of wxFrameManager into the child window and call into a function like DetachPane, except it will be DestroyPane or ClosePane. This merely bypasses dealing with events.


I don't see a way to do it currently so I will be building something to handle it. If there is a way to do it, forgive me (and let me know how).

-Jon
stimpy
Registered User
 
Posts: 2
Joined: Wed Sep 06, 2006 8:06 pm

Postby Ben on Wed Sep 13, 2006 9:34 am

Hey there,

Great idea. Currently there isn't a way to do that programmatically. But I agree, that would be a cool feature. I imagine some kind of API call similar to wxWindow::Close(), which allows the programmer to close a pane, forcibly or not.

What do you think?

Best,
Ben
User avatar
Ben
Kirix Support Team
 
Posts: 525
Joined: Mon Dec 19, 2005 6:29 am

Postby stimpy on Wed Sep 13, 2006 9:49 pm

As a proof of concept (and to get me going), here is what I've currently altered on an otherwise unmodifed 0.9.2 sourcetree. It works, but it hasn't been fully thought out. Some ideas of this event system were taken from Joel's modified source.

Code: Select all
--- wxaui-0.9.2.org/include/manager.h   2006-04-19 09:19:36.000000000 -0600
+++ wxaui-0.9.2/include/manager.h   2006-09-07 11:40:51.312500000 -0600
@@ -86,7 +86,7 @@
class wxPaneInfo;
class wxDockInfo;
class wxDockArt;
-class wxFrameManagerEvent;
+class wxAUIEvent;

WX_DECLARE_OBJARRAY(wxDockInfo, wxDockInfoArray);
WX_DECLARE_OBJARRAY(wxDockUIPart, wxDockUIPartArray);
@@ -423,7 +423,7 @@
     void OnFloatingPaneResized(wxWindow* window, const wxSize& size);
     void Render(wxDC* dc);
     void Repaint(wxDC* dc = NULL);
-    void ProcessMgrEvent(wxFrameManagerEvent& event);
+    void DispatchAUIEvent(wxAUIEvent& event);
     void UpdateButtonOnScreen(wxDockUIPart* button_ui_part,
                               const wxMouseEvent& event);
     void GetPanePositionsAndSizes(wxDockInfo& dock,
@@ -444,7 +444,8 @@
     void OnLeftUp(wxMouseEvent& event);
     void OnMotion(wxMouseEvent& event);
     void OnLeaveWindow(wxMouseEvent& event);
-    void OnPaneButton(wxFrameManagerEvent& event);
+    void ProcessPaneClose(wxAUIEvent& event);
+    void ProcessPanePin(wxAUIEvent& event);
     void OnChildFocus(wxChildFocusEvent& event);
     void OnHintFadeTimer(wxTimerEvent& event);

@@ -487,40 +488,6 @@
     DECLARE_EVENT_TABLE()
};

-
-
-// event declarations/classes
-
-class WXDLLEXPORT wxFrameManagerEvent : public wxEvent
-{
-public:
-    wxFrameManagerEvent(wxEventType type) : wxEvent(0, type)
-    {
-        pane = NULL;
-        button = 0;
-    }
-
-    wxFrameManagerEvent(const wxFrameManagerEvent& c) : wxEvent(c)
-    {
-        pane = c.pane;
-        button = c.button;
-    }
-
-    wxEvent *Clone() const { return new wxFrameManagerEvent(*this); }
-
-    void SetPane(wxPaneInfo* p) { pane = p; }
-    void SetButton(int b) { button = b; }
-    wxPaneInfo* GetPane() { return pane; }
-    int GetButton() { return button; }
-
-public:
-    wxPaneInfo* pane;
-    int button;
-};
-
-
-
-
// dock art provider code - a dock provider provides all drawing
// functionality to the wxAui dock manager.  This allows the dock
// manager to have plugable look-and-feels
@@ -749,22 +716,64 @@


// wx event machinery
+// event declarations/classes
+
+class WXDLLEXPORT wxAUIEvent : public wxNotifyEvent
+{
+public:
+  wxAUIEvent(wxEventType eventType)
+    : wxNotifyEvent(eventType, 0), m_window(NULL)
+  { }
+
+  /** \brief Copy constructor.*/
+  wxAUIEvent(const wxAUIEvent & event)
+    : wxNotifyEvent(event)
+  { m_window = event.m_window; }

+  void SetWindow(wxWindow * window)
+  { m_window = window; }
+
+  wxWindow * GetWindow() const
+  { return m_window; }
+
+  virtual wxEvent * Clone() const
+  { return new wxAUIEvent(*this); }
+
+private:
+  wxWindow * m_window;
+};

// right now the only event that works is wxEVT_AUI_PANEBUTTON. A full
// spectrum of events will be implemented in the next incremental version

BEGIN_DECLARE_EVENT_TYPES()
-    DECLARE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON, 0)   
+    DECLARE_EVENT_TYPE(wxEVT_AUI_PANECLOSING, 0)
+    DECLARE_EVENT_TYPE(wxEVT_AUI_PANECLOSE, 0)
+    DECLARE_EVENT_TYPE(wxEVT_AUI_PANECLOSED, 0)
+    DECLARE_EVENT_TYPE(wxEVT_AUI_PANEPINNING, 0)
+    DECLARE_EVENT_TYPE(wxEVT_AUI_PANEPIN, 0)
+    DECLARE_EVENT_TYPE(wxEVT_AUI_PANEPINNED, 0)
END_DECLARE_EVENT_TYPES()

-typedef void (wxEvtHandler::*wxFrameManagerEventFunction)(wxFrameManagerEvent&);
-
-#define wxFrameManagerEventHandler(func) \
-    (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxFrameManagerEventFunction, &func)
-
-#define EVT_AUI_PANEBUTTON(func) \
-   wx__DECLARE_EVT0(wxEVT_AUI_PANEBUTTON, wxFrameManagerEventHandler(func))
+typedef void (wxEvtHandler::*wxAUIEventFunction)(wxAUIEvent&);

+#define wxAUIEventHandler(func) \
+    (wxObjectEventFunction)(wxEventFunction)(wxNotifyEventFunction) \
+    wxStaticCastEvent(wxAUIEventFunction, &func)
+
+#define EVT_AUI(evt, func) \
+   wx__DECLARE_EVT0(evt, wxAUIEventHandler(func))
+#define EVT_AUI_PANECLOSING(func) \
+    wx__DECLARE_EVT0(wxEVT_AUI_PANECLOSING, wxAUIEventHandler(func))
+#define EVT_AUI_PANECLOSE(func) \
+    wx__DECLARE_EVT0(wxEVT_AUI_PANECLOSE, wxAUIEventHandler(func))
+#define EVT_AUI_PANECLOSED(func) \
+    wx__DECLARE_EVT0(wxEVT_AUI_PANECLOSED, wxAUIEventHandler(func))
+#define EVT_AUI_PANEPINNING(func) \
+    wx__DECLARE_EVT0(wxEVT_AUI_PANEPINNING, wxAUIEventHandler(func))
+#define EVT_AUI_PANEPIN(func) \
+    wx__DECLARE_EVT0(wxEVT_AUI_PANEPIN, wxAUIEventHandler(func))
+#define EVT_AUI_PANEPINNED(func) \
+    wx__DECLARE_EVT0(wxEVT_AUI_PANEPINNED, wxAUIEventHandler(func))

#endif


Code: Select all
--- wxaui-0.9.2.org/src/manager.cpp   2006-04-19 09:19:36.000000000 -0600
+++ wxaui-0.9.2/src/manager.cpp   2006-09-07 12:30:40.687500000 -0600
@@ -27,7 +27,12 @@

wxPaneInfo wxNullPaneInfo;
wxDockInfo wxNullDockInfo;
-DEFINE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON)
+DEFINE_EVENT_TYPE(wxEVT_AUI_PANECLOSING)
+DEFINE_EVENT_TYPE(wxEVT_AUI_PANECLOSE)
+DEFINE_EVENT_TYPE(wxEVT_AUI_PANECLOSED)
+DEFINE_EVENT_TYPE(wxEVT_AUI_PANEPINNING)
+DEFINE_EVENT_TYPE(wxEVT_AUI_PANEPIN)
+DEFINE_EVENT_TYPE(wxEVT_AUI_PANEPINNED)

#ifdef __WXMAC__
     // a few defines to avoid nameclashes
@@ -618,6 +623,27 @@
     }

private:
+  void ProcessClose()
+  {
+    { // hey everybody, the pane is closing
+      wxAUIEvent closingEvent(wxEVT_AUI_PANECLOSING);
+      closingEvent.SetWindow(m_pane_window);
+      m_owner_mgr->DispatchAUIEvent(closingEvent);
+      if (!closingEvent.IsAllowed())
+      { return; }
+    }
+
+    // close the pane
+    m_owner_mgr->OnFloatingPaneClosed(m_pane_window);
+    Destroy();
+
+    { // hey everybody, the pane is closed
+      wxAUIEvent closedEvent(wxEVT_AUI_PANECLOSED);
+      closedEvent.SetWindow(m_pane_window);
+      m_owner_mgr->DispatchAUIEvent(closedEvent);
+      // allowed or not, exit
+    }
+  }

     void OnSize(wxSizeEvent& event)
     {
@@ -626,8 +652,7 @@
     
     void OnClose(wxCloseEvent& event)
     {
-        m_owner_mgr->OnFloatingPaneClosed(m_pane_window);
-        Destroy();
+      ProcessClose();
     }

     void OnMoveEvent(wxMoveEvent& event)
@@ -704,6 +729,11 @@
         }
     }

+    void OnPaneClose(wxAUIEvent& event)
+    {
+        ProcessClose();
+    }
+
     // utility function which determines the state of the mouse button
     // (independant of having a wxMouseEvent handy) - utimately a better
     // mechanism for this should be found (possibly by adding the
@@ -743,9 +773,10 @@
     EVT_SIZE(wxFloatingPane::OnSize)
     EVT_MOVE(wxFloatingPane::OnMoveEvent)
     EVT_MOVING(wxFloatingPane::OnMoveEvent)
-    EVT_CLOSE(wxFloatingPane::OnClose)
+    EVT_CLOSE(wxFloatingPane::OnClose) // [x] clicked
     EVT_IDLE(wxFloatingPane::OnIdle)
     EVT_ACTIVATE(wxFloatingPane::OnActivate)
+    EVT_AUI_PANECLOSE(wxFloatingPane::OnPaneClose) // [x] click emulated
END_EVENT_TABLE()


@@ -1046,7 +1077,8 @@


BEGIN_EVENT_TABLE(wxFrameManager, wxEvtHandler)
-    EVT_AUI_PANEBUTTON(wxFrameManager::OnPaneButton)
+    EVT_AUI_PANECLOSE(wxFrameManager::DispatchAUIEvent)
+    EVT_AUI_PANEPIN(wxFrameManager::DispatchAUIEvent)
     EVT_PAINT(wxFrameManager::OnPaint)
     EVT_ERASE_BACKGROUND(wxFrameManager::OnEraseBackground)
     EVT_SIZE(wxFrameManager::OnSize)
@@ -1218,16 +1250,24 @@
     return m_art;
}

-void wxFrameManager::ProcessMgrEvent(wxFrameManagerEvent& event)
-{
-    // first, give the owner frame a chance to override
-    if (m_frame)
-    {
-        if (m_frame->ProcessEvent(event))
-            return;
-    }
-
-    ProcessEvent(event);
+/** \brief AUIEvents must be dispatched to the appropriate listener, whether
+ * it be the wxFloatingPane, or the pane within wxFrameManager.*/
+void wxFrameManager::DispatchAUIEvent(wxAUIEvent& event)
+{
+  /**
+   * first, give the owner frame a chance to override
+   * this always goes to wxFloatingPane, if present?
+   */
+  if (m_frame)
+  {
+    if (m_frame->ProcessEvent(event))
+    { return; }
+  }
+
+  if (event.GetEventType() == wxEVT_AUI_PANECLOSE)
+  { ProcessPaneClose(event); }
+  else if (event.GetEventType() == wxEVT_AUI_PANEPIN)
+  { ProcessPanePin(event); }
}

// SetArtProvider() instructs wxFrameManager to use the
@@ -3916,11 +3956,13 @@
         // 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
-            wxFrameManagerEvent e(wxEVT_AUI_PANEBUTTON);
-            e.SetPane(m_action_part->pane);
-            e.SetButton(m_action_part->button->button_id);
-            ProcessMgrEvent(e);
+          if (m_action_part->button->button_id == wxPaneInfo::buttonClose)
+          {
+            // [x] click emulated
+            wxAUIEvent auiEvent(wxEVT_AUI_PANECLOSE);
+            auiEvent.SetWindow(m_action_part->pane->window);
+            DispatchAUIEvent(auiEvent);
+          }
         }
     }
      else if (m_action == actionClickCaption)
@@ -4142,23 +4184,64 @@
     }
}

-
-// OnPaneButton() is an event handler that is called
-// when a pane button has been pressed.
-void wxFrameManager::OnPaneButton(wxFrameManagerEvent& event)
+/** \brief Close a docked pane.*/
+void wxFrameManager::ProcessPaneClose(wxAUIEvent & event)
{
-    wxPaneInfo& pane = *(event.pane);
-   
-    if (event.button == wxPaneInfo::buttonClose)
-    {
-        pane.Hide();
-        Update();
-    }
-     else if (event.button == wxPaneInfo::buttonPin)
-    {
-        if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
-            pane.IsFloatable())
-                pane.Float();
-        Update();
-    }
+  { // hey everybody, the pane is closing
+    wxAUIEvent closingEvent(wxEVT_AUI_PANECLOSING);
+
+    closingEvent.SetWindow(event.GetWindow());
+    DispatchAUIEvent(closingEvent);
+    if (!closingEvent.IsAllowed())
+    { return; }
+  }
+
+  // close the pane
+  wxPaneInfo & pane(GetPane(event.GetWindow()));
+  if (!pane.IsOk())
+  { return; }
+
+  pane.Hide();
+  Update();
+
+  { // hey everybody, the pane is closed
+    wxAUIEvent closedEvent(wxEVT_AUI_PANECLOSED);
+
+    closedEvent.SetWindow(event.GetWindow());
+    DispatchAUIEvent(closedEvent);
+    // allowed or not, exit
+  }
+}
+
+/** \brief Float/unfloat a pane.
+ *
+ * \remark This is just copied from the previous OnPaneButton() and doesn't
+ * actually work.*/
+void wxFrameManager::ProcessPanePin(wxAUIEvent & event)
+{
+  { // hey everybody, the pane is pinning
+    wxAUIEvent pinningEvent(wxEVT_AUI_PANEPINNING);
+
+    pinningEvent.SetWindow(event.GetWindow());
+    DispatchAUIEvent(pinningEvent);
+    if (!pinningEvent.IsAllowed())
+    { return; }
+  }
+
+  // pin the pane
+  wxPaneInfo & pane(GetPane(event.GetWindow()));
+  if (!pane.IsOk())
+  { return; }
+
+  if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) && pane.IsFloatable())
+  { pane.Float(); }
+  Update();
+
+  { // hey everybody, the pane is pinned
+    wxAUIEvent pinnedEvent(wxEVT_AUI_PANEPINNED);
+
+    pinnedEvent.SetWindow(event.GetWindow());
+    DispatchAUIEvent(pinnedEvent);
+    // allowed or not, exit
+  }
}
stimpy
Registered User
 
Posts: 2
Joined: Wed Sep 06, 2006 8:06 pm

Return to wxAUI Questions, Thoughts & Feedback