// 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 $
// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#if wxUSE_INFOBAR
+#include "wx/infobar.h"
+
#ifndef WX_PRECOMP
#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
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;
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
// 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(wxInfoBarGeneric::OnButton),
- NULL,
- this
- );
+ m_button = wxBitmapButton::NewCloseButton(this, wxID_ANY);
+ m_button->SetToolTip(_("Hide this notification message."));
// 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;
return true;
}
-void wxInfoBarGeneric::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<wxInfoBarGeneric *>(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 wxInfoBarGeneric::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;
}
+}
- if ( sibling )
- parent->SetOwnBackgroundColour(sibling->GetBackgroundColour());
+wxShowEffect wxInfoBarGeneric::GetHideEffect() const
+{
+ if ( m_hideEffect != wxSHOW_EFFECT_MAX )
+ return m_hideEffect;
+
+ 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 wxInfoBarGeneric::RestoreParentBackground()
+void wxInfoBarGeneric::UpdateParent()
{
- GetParent()->SetOwnBackgroundColour(m_origParentBgCol);
+ wxWindow * const parent = GetParent();
+ parent->Layout();
}
void wxInfoBarGeneric::DoHide()
{
- ChangeParentBackground();
- wxON_BLOCK_EXIT_THIS0( wxInfoBarGeneric::RestoreParentBackground );
+ HideWithEffect(GetHideEffect(), GetEffectDuration());
- HideWithEffect(m_hideEffect, m_effectDuration);
UpdateParent();
}
// 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( wxInfoBarGeneric::RestoreParentBackground );
-
// adjust the parent layout to account for us
UpdateParent();
// finally do really show the window.
- ShowWithEffect(m_showEffect, m_effectDuration);
+ ShowWithEffect(GetShowEffect(), GetEffectDuration());
}
void wxInfoBarGeneric::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();
}
}
}
+void wxInfoBarGeneric::Dismiss()
+{
+ DoHide();
+}
+
void wxInfoBarGeneric::AddButton(wxWindowID btnid, const wxString& label)
{
wxSizer * const sizer = GetSizer();
wxCHECK_RET( sizer, "must be created first" );
- sizer->Insert(sizer->GetItemCount() - 1,
- new wxButton(this, btnid, label),
- wxSizerFlags().Centre().DoubleBorder());
+ // 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)
node != items.GetFirst();
node = node->GetPrevious() )
{
- node = node->GetPrevious();
const wxSizerItem * const item = node->GetData();
// if we reached the spacer separating the buttons from the text
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))