X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/df8c364bf488d99d6b0c305898a5289fe20a393b..07aaf32633ecf18ec3edfbb41793a112914792d0:/src/generic/infobar.cpp?ds=sidebyside diff --git a/src/generic/infobar.cpp b/src/generic/infobar.cpp index 549f20617d..31f0d0ed7f 100644 --- a/src/generic/infobar.cpp +++ b/src/generic/infobar.cpp @@ -3,7 +3,7 @@ // Purpose: generic wxInfoBar implementation // Author: Vadim Zeitlin // Created: 2009-07-28 -// RCS-ID: $Id: wxhead.cpp,v 1.10 2009-06-29 10:23:04 zeitlin Exp $ +// RCS-ID: $Id$ // Copyright: (c) 2009 Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -25,37 +25,43 @@ #if wxUSE_INFOBAR +#include "wx/infobar.h" + #ifndef WX_PRECOMP - #include "wx/artprov.h" #include "wx/bmpbuttn.h" + #include "wx/button.h" + #include "wx/dcmemory.h" #include "wx/settings.h" #include "wx/statbmp.h" #include "wx/stattext.h" + #include "wx/sizer.h" #endif // WX_PRECOMP -#include "wx/infobar.h" - +#include "wx/artprov.h" #include "wx/scopeguard.h" -#include "wx/sizer.h" + +BEGIN_EVENT_TABLE(wxInfoBarGeneric, wxInfoBarBase) + EVT_BUTTON(wxID_ANY, wxInfoBarGeneric::OnButton) +END_EVENT_TABLE() // ============================================================================ // implementation // ============================================================================ -void wxInfoBar::Init() +void wxInfoBarGeneric::Init() { m_icon = NULL; m_text = NULL; m_button = NULL; - m_showEffect = wxSHOW_EFFECT_SLIDE_TO_BOTTOM; - m_hideEffect = wxSHOW_EFFECT_SLIDE_TO_TOP; + m_showEffect = + m_hideEffect = wxSHOW_EFFECT_MAX; // use default effect duration m_effectDuration = 0; } -bool wxInfoBar::Create(wxWindow *parent, wxWindowID winid) +bool wxInfoBarGeneric::Create(wxWindow *parent, wxWindowID winid) { // calling Hide() before Create() ensures that we're created initially // hidden @@ -64,7 +70,8 @@ bool wxInfoBar::Create(wxWindow *parent, wxWindowID winid) return false; // use special, easy to notice, colours - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK)); + const wxColour colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK); + SetBackgroundColour(colBg); SetOwnForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT)); // create the controls: icon, text and the button to dismiss the @@ -73,42 +80,27 @@ bool wxInfoBar::Create(wxWindow *parent, wxWindowID winid) // the icon is not shown unless it's assigned a valid bitmap m_icon = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap); - // by default, the text uses a larger, more noticeable, font m_text = new wxStaticText(this, wxID_ANY, ""); - m_text->SetFont(m_text->GetFont().Bold().Larger()); - - m_button = new wxBitmapButton - ( - this, - wxID_ANY, - wxArtProvider::GetBitmap(wxART_CROSS_MARK), - wxDefaultPosition, - wxDefaultSize, - wxBORDER_NONE - ); - m_button->SetToolTip(_("Hide this notification message.")); - Connect - ( - wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxInfoBar::OnButton), - NULL, - this - ); + m_button = wxBitmapButton::NewCloseButton(this, wxID_ANY); + m_button->SetToolTip(_("Hide this notification message.")); - // Center the text inside the sizer. + // center the text inside the sizer with an icon to the left of it and a + // button at the very right + // + // NB: AddButton() relies on the button being the last control in the sizer + // and being preceded by a spacer wxSizer * const sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(m_icon, wxSizerFlags().Centre().Border()); + sizer->Add(m_text, wxSizerFlags().Centre()); sizer->AddStretchSpacer(); - sizer->Add(m_icon, wxSizerFlags().Centre().DoubleBorder()); - sizer->Add(m_text, wxSizerFlags().Centre().DoubleBorder()); - sizer->AddStretchSpacer(); - sizer->Add(m_button, wxSizerFlags().Centre().DoubleBorder()); + sizer->Add(m_button, wxSizerFlags().Centre().Border()); SetSizer(sizer); return true; } -bool wxInfoBar::SetFont(const wxFont& font) +bool wxInfoBarGeneric::SetFont(const wxFont& font) { if ( !wxInfoBarBase::SetFont(font) ) return false; @@ -120,65 +112,82 @@ bool wxInfoBar::SetFont(const wxFont& font) return true; } -void wxInfoBar::UpdateParent() +wxInfoBarGeneric::BarPlacement wxInfoBarGeneric::GetBarPlacement() const { - wxWindow * const parent = wxGetTopLevelParent(GetParent()); - parent->Layout(); + wxSizer * const sizer = GetContainingSizer(); + if ( !sizer ) + return BarPlacement_Unknown; + + // FIXME-VC6: can't compare "const wxInfoBarGeneric *" and "wxWindow *", + // so need this workaround + wxWindow * const self = const_cast(this); + const wxSizerItemList& siblings = sizer->GetChildren(); + if ( siblings.GetFirst()->GetData()->GetWindow() == self ) + return BarPlacement_Top; + else if ( siblings.GetLast()->GetData()->GetWindow() == self ) + return BarPlacement_Bottom; + else + return BarPlacement_Unknown; } -void wxInfoBar::ChangeParentBackground() +wxShowEffect wxInfoBarGeneric::GetShowEffect() const { - wxWindow * const parent = GetParent(); - m_origParentBgCol = parent->GetBackgroundColour(); - - wxSizer * const sizer = GetContainingSizer(); - if ( !sizer ) - return; + if ( m_showEffect != wxSHOW_EFFECT_MAX ) + return m_showEffect; - wxWindow *sibling = NULL; - for ( wxSizerItemList::compatibility_iterator - node = sizer->GetChildren().GetFirst(); - node; - node = node->GetNext() ) + switch ( GetBarPlacement() ) { - if ( node->GetData()->GetWindow() == this ) - { - // find the next window following us - for ( node = node->GetNext(); - node; - node = node->GetNext() ) - { - wxSizerItem * const item = node->GetData(); - if ( item->IsWindow() ) - { - sibling = item->GetWindow(); - break; - } - } + case BarPlacement_Top: + return wxSHOW_EFFECT_SLIDE_TO_BOTTOM; - break; - } + case BarPlacement_Bottom: + return wxSHOW_EFFECT_SLIDE_TO_TOP; + + default: + wxFAIL_MSG( "unknown info bar placement" ); + // fall through + + case BarPlacement_Unknown: + return wxSHOW_EFFECT_NONE; } +} + +wxShowEffect wxInfoBarGeneric::GetHideEffect() const +{ + if ( m_hideEffect != wxSHOW_EFFECT_MAX ) + return m_hideEffect; - if ( sibling ) - parent->SetOwnBackgroundColour(sibling->GetBackgroundColour()); + switch ( GetBarPlacement() ) + { + case BarPlacement_Top: + return wxSHOW_EFFECT_SLIDE_TO_TOP; + + case BarPlacement_Bottom: + return wxSHOW_EFFECT_SLIDE_TO_BOTTOM; + + default: + wxFAIL_MSG( "unknown info bar placement" ); + // fall through + + case BarPlacement_Unknown: + return wxSHOW_EFFECT_NONE; + } } -void wxInfoBar::RestoreParentBackground() +void wxInfoBarGeneric::UpdateParent() { - GetParent()->SetOwnBackgroundColour(m_origParentBgCol); + wxWindow * const parent = GetParent(); + parent->Layout(); } -void wxInfoBar::DoHide() +void wxInfoBarGeneric::DoHide() { - ChangeParentBackground(); - wxON_BLOCK_EXIT_THIS0( wxInfoBar::RestoreParentBackground ); + HideWithEffect(GetHideEffect(), GetEffectDuration()); - HideWithEffect(m_hideEffect, m_effectDuration); UpdateParent(); } -void wxInfoBar::DoShow() +void wxInfoBarGeneric::DoShow() { // re-layout the parent first so that the window expands into an already // unoccupied by the other controls area: for this we need to change our @@ -190,12 +199,6 @@ void wxInfoBar::DoShow() // without really showing it wxWindowBase::Show(); - // an extra hack: we want the temporarily uncovered area in which we're - // going to expand to look like part of this sibling for a better effect so - // temporarily change the background of our parent to the same colour - ChangeParentBackground(); - wxON_BLOCK_EXIT_THIS0( wxInfoBar::RestoreParentBackground ); - // adjust the parent layout to account for us UpdateParent(); @@ -205,10 +208,10 @@ void wxInfoBar::DoShow() // finally do really show the window. - ShowWithEffect(m_showEffect, m_effectDuration); + ShowWithEffect(GetShowEffect(), GetEffectDuration()); } -void wxInfoBar::ShowMessage(const wxString& msg, int flags) +void wxInfoBarGeneric::ShowMessage(const wxString& msg, int flags) { // first update the controls const int icon = flags & wxICON_MASK; @@ -218,7 +221,9 @@ void wxInfoBar::ShowMessage(const wxString& msg, int flags) } else // do show an icon { - m_icon->SetBitmap(wxArtProvider::GetMessageBoxIcon(icon)); + m_icon->SetBitmap(wxArtProvider::GetBitmap( + wxArtProvider::GetMessageBoxIconId(flags), + wxART_BUTTON)); m_icon->Show(); } @@ -239,7 +244,76 @@ void wxInfoBar::ShowMessage(const wxString& msg, int flags) } } -void wxInfoBar::OnButton(wxCommandEvent& WXUNUSED(event)) +void wxInfoBarGeneric::Dismiss() +{ + DoHide(); +} + +void wxInfoBarGeneric::AddButton(wxWindowID btnid, const wxString& label) +{ + wxSizer * const sizer = GetSizer(); + wxCHECK_RET( sizer, "must be created first" ); + + // user-added buttons replace the standard close button so remove it if we + // hadn't done it yet + if ( sizer->Detach(m_button) ) + { + m_button->Hide(); + } + + wxButton * const button = new wxButton(this, btnid, label); + +#ifdef __WXMAC__ + // smaller buttons look better in the (narrow) info bar under OS X + button->SetWindowVariant(wxWINDOW_VARIANT_SMALL); +#endif // __WXMAC__ + + sizer->Add(button, wxSizerFlags().Centre().DoubleBorder()); +} + +void wxInfoBarGeneric::RemoveButton(wxWindowID btnid) +{ + wxSizer * const sizer = GetSizer(); + wxCHECK_RET( sizer, "must be created first" ); + + // iterate over the sizer items in reverse order to find the last added + // button with this id (ids of all buttons should be unique anyhow but if + // they are repeated removing the last added one probably makes more sense) + const wxSizerItemList& items = sizer->GetChildren(); + for ( wxSizerItemList::compatibility_iterator node = items.GetLast(); + node != items.GetFirst(); + node = node->GetPrevious() ) + { + const wxSizerItem * const item = node->GetData(); + + // if we reached the spacer separating the buttons from the text + // preceding them without finding our button, it must mean it's not + // there at all + if ( item->IsSpacer() ) + { + wxFAIL_MSG( wxString::Format("button with id %d not found", btnid) ); + return; + } + + // check if we found our button + if ( item->GetWindow()->GetId() == btnid ) + { + delete item->GetWindow(); + break; + } + } + + // check if there are any custom buttons left + if ( sizer->GetChildren().GetLast()->GetData()->IsSpacer() ) + { + // if the last item is the spacer, none are left so restore the + // standard close button + sizer->Add(m_button, wxSizerFlags().Centre().DoubleBorder()); + m_button->Show(); + } +} + +void wxInfoBarGeneric::OnButton(wxCommandEvent& WXUNUSED(event)) { DoHide(); }