From: Vadim Zeitlin Date: Thu, 1 Sep 2005 01:26:49 +0000 (+0000) Subject: better handling of empty MDI parent frame visibility: show it only when there are... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/a57ac1c418349c0d918588e456e0c8dad00f8eb8 better handling of empty MDI parent frame visibility: show it only when there are no MDI children shown git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@35396 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/mac/carbon/mdi.h b/include/wx/mac/carbon/mdi.h index 863ff82e86..927194c27d 100644 --- a/include/wx/mac/carbon/mdi.h +++ b/include/wx/mac/carbon/mdi.h @@ -32,15 +32,16 @@ class WXDLLEXPORT wxMDIParentFrame: public wxFrame public: - wxMDIParentFrame(); - inline wxMDIParentFrame(wxWindow *parent, - wxWindowID id, - const wxString& title, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxDEFAULT_FRAME_STYLE | wxVSCROLL | wxHSCROLL, // Scrolling refers to client window - const wxString& name = wxFrameNameStr) + wxMDIParentFrame() { Init(); } + wxMDIParentFrame(wxWindow *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE | wxVSCROLL | wxHSCROLL, // Scrolling refers to client window + const wxString& name = wxFrameNameStr) { + Init(); Create(parent, id, title, pos, size, style, name); } @@ -84,19 +85,34 @@ public: virtual bool Show( bool show = true ); + // overridden base clas virtuals + virtual void AddChild(wxWindowBase *child); + virtual void RemoveChild(wxWindowBase *child); + protected: + // common part of all ctors + void Init(); + + // returns true if this frame has some contents and so should be visible, + // false if it's used solely as container for its children + bool ShouldBeVisible() const; - // TODO maybe have this member - wxMDIClientWindow *m_clientWindow; - wxMDIChildFrame * m_currentChild; - wxMenu* m_windowMenu; - // TRUE if MDI Frame is intercepting commands, not child + // TODO maybe have this member + wxMDIClientWindow *m_clientWindow; + wxMDIChildFrame *m_currentChild; + wxMenu *m_windowMenu; + + // true if MDI Frame is intercepting commands, not child bool m_parentFrameActive; + // true if the frame should be shown but is not because it is empty and + // useless otherwise than a container for its children + bool m_shouldBeShown; + private: friend class WXDLLEXPORT wxMDIChildFrame; -DECLARE_EVENT_TABLE() + DECLARE_EVENT_TABLE() }; class WXDLLEXPORT wxMDIChildFrame: public wxFrame diff --git a/src/mac/carbon/mdi.cpp b/src/mac/carbon/mdi.cpp index b79928d8f6..158f2df45c 100644 --- a/src/mac/carbon/mdi.cpp +++ b/src/mac/carbon/mdi.cpp @@ -57,27 +57,27 @@ static const int wxLAST_MDI_CHILD = 4600; // Status border dimensions static const int wxTHICK_LINE_BORDER = 3; +// ---------------------------------------------------------------------------- // Parent frame +// ---------------------------------------------------------------------------- -wxMDIParentFrame::wxMDIParentFrame() +void wxMDIParentFrame::Init() { m_clientWindow = NULL; m_currentChild = NULL; m_windowMenu = (wxMenu*) NULL; - m_parentFrameActive = TRUE; + m_parentFrameActive = true; + m_shouldBeShown = false; } bool wxMDIParentFrame::Create(wxWindow *parent, - wxWindowID id, - const wxString& title, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) + wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) { - m_clientWindow = NULL; - m_currentChild = NULL; - // this style can be used to prevent a window from having the standard MDI // "Window" menu if ( style & wxFRAME_NO_WINDOW_MENU ) @@ -98,11 +98,11 @@ bool wxMDIParentFrame::Create(wxWindow *parent, } wxFrame::Create( parent , id , title , pos , size , style , name ) ; - m_parentFrameActive = TRUE; + m_parentFrameActive = true; OnCreateClient(); - return TRUE; + return true; } wxMDIParentFrame::~wxMDIParentFrame() @@ -129,6 +129,58 @@ void wxMDIParentFrame::GetRectForTopLevelChildren(int *x, int *y, int *w, int *h wxDisplaySize(w,h); } +void wxMDIParentFrame::AddChild(wxWindowBase *child) +{ + if ( !m_currentChild ) + { + m_currentChild = wxDynamicCast(child, wxMDIChildFrame); + + if ( m_currentChild && IsShown() && ShouldBeVisible() ) + { + } + } + + wxFrame::AddChild(child); +} + +void wxMDIParentFrame::RemoveChild(wxWindowBase *child) +{ + if ( child == m_currentChild ) + { + // the current child isn't active any more, try to find another one + m_currentChild = NULL; + + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + wxMDIChildFrame * + childCur = wxDynamicCast(node->GetData(), wxMDIChildFrame); + if ( childCur != child ) + { + m_currentChild = childCur; + break; + } + } + } + + wxFrame::RemoveChild(child); + + // if there are no more children left we need to show the frame if we + // hadn't shown it before because there were active children and it was + // useless (note that we have to do it after fully removing the child, i.e. + // after calling the base class RemoveChild() as otherwise we risk to touch + // pointer to the child being deleted) + if ( !m_currentChild && m_shouldBeShown && !IsShown() ) + { + // we have to show it, but at least move it out of sight and make it of + // smallest possible size (unfortunately (0, 0) doesn't work so that it + // doesn't appear in expose + SetSize(-10000, -10000, 1, 1); + Show(); + } +} + void wxMDIParentFrame::MacActivate(long timestamp, bool activating) { wxLogTrace(TRACE_MDI, wxT("MDI PARENT=%p MacActivate(0x%08lx,%s)"),this,timestamp,activating?wxT("ACTIV"):wxT("deact")); @@ -229,29 +281,51 @@ void wxMDIParentFrame::ActivatePrevious() // TODO } +bool wxMDIParentFrame::ShouldBeVisible() const +{ + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + if ( !wxDynamicCast(node->GetData(), wxMDIChildFrame) +#if wxUSE_STATUSBAR + && node->GetData() != GetStatusBar() +#endif // wxUSE_STATUSBAR + && node->GetData() != GetClientWindow() ) + { + // if we have a non-MDI child, do remain visible so that it could + // be used + return true; + } + } + + return false; +} + bool wxMDIParentFrame::Show( bool show ) { + m_shouldBeShown = false; + // don't really show the MDI frame unless it has any children other than // MDI children as it is pretty useless in this case if ( show ) { - // TODO: check for other children - if ( !GetToolBar() ) + if ( !ShouldBeVisible() && m_currentChild ) { - // call the base class version to just update the flag but don't - // really make the window visible - return wxFrameBase::Show(); + // don't make the window visible now but remember that we should + // have had done it + m_shouldBeShown = true; + return false; } } - if ( !wxFrame::Show(show) ) - return false; - - return true; + return wxFrame::Show(show); } +// ---------------------------------------------------------------------------- // Child frame +// ---------------------------------------------------------------------------- wxMDIChildFrame::wxMDIChildFrame() { @@ -283,15 +357,11 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent, SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE)); wxModelessWindows.Append(this); - return FALSE; + return false; } wxMDIChildFrame::~wxMDIChildFrame() { - wxMDIParentFrame *mdiparent = wxDynamicCast(m_parent, wxMDIParentFrame); - wxASSERT(mdiparent); - if(mdiparent->m_currentChild == this) - mdiparent->m_currentChild = NULL; DestroyChildren(); } @@ -380,10 +450,10 @@ wxMDIClientWindow::~wxMDIClientWindow() bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style) { if ( !wxWindow::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style)) - return FALSE; + return false; wxModelessWindows.Append(this); - return TRUE; + return true; } // Get size *available for subwindows* i.e. excluding menu bar. @@ -397,5 +467,5 @@ void wxMDIClientWindow::OnScroll(wxScrollEvent& event) { } -#endif +#endif // wxUSE_MDI