Soren Jorvang d14efe561b Import r67258 of the wxWidgets trunk, which I expect will before
long become wxWidgets 2.9.2, which in turn is expected to be the
last 2.9 release before the 3.0 stable release.

Since the full wxWidgets distribution is rather large, I have
imported only the parts that we use, on a subdirectory basis:

art
include/wx/*.*
include/wx/aui
include/wx/cocoa
include/wx/generic
include/wx/gtk
include/wx/meta
include/wx/msw
include/wx/osx
include/wx/persist
include/wx/private
include/wx/protocol
include/wx/unix
src/aui
src/common
src/generic
src/gtk
src/msw
src/osx
src/unix


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7380 8ced0084-cf51-0410-be5f-012b33b47a6e
2011-03-20 18:05:19 +00:00

375 lines
11 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: src/generic/infobar.cpp
// Purpose: generic wxInfoBar implementation
// Author: Vadim Zeitlin
// Created: 2009-07-28
// RCS-ID: $Id: infobar.cpp 63613 2010-03-03 07:17:18Z RD $
// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#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/artprov.h"
#include "wx/renderer.h"
#include "wx/scopeguard.h"
BEGIN_EVENT_TABLE(wxInfoBarGeneric, wxInfoBarBase)
EVT_BUTTON(wxID_ANY, wxInfoBarGeneric::OnButton)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// local helpers
// ----------------------------------------------------------------------------
namespace
{
#ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
wxBitmap
GetCloseButtonBitmap(wxWindow *win,
const wxSize& size,
const wxColour& colBg,
int flags = 0)
{
wxBitmap bmp(size);
wxMemoryDC dc(bmp);
dc.SetBackground(colBg);
dc.Clear();
wxRendererNative::Get().
DrawTitleBarBitmap(win, dc, size, wxTITLEBAR_BUTTON_CLOSE, flags);
return bmp;
}
#endif // wxHAS_DRAW_TITLE_BAR_BITMAP
} // anonymous namespace
// ============================================================================
// implementation
// ============================================================================
void wxInfoBarGeneric::Init()
{
m_icon = NULL;
m_text = NULL;
m_button = NULL;
m_showEffect =
m_hideEffect = wxSHOW_EFFECT_MAX;
// use default effect duration
m_effectDuration = 0;
}
bool wxInfoBarGeneric::Create(wxWindow *parent, wxWindowID winid)
{
// calling Hide() before Create() ensures that we're created initially
// hidden
Hide();
if ( !wxWindow::Create(parent, winid) )
return false;
// use special, easy to notice, colours
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
// message.
// the icon is not shown unless it's assigned a valid bitmap
m_icon = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
m_text = new wxStaticText(this, wxID_ANY, "");
#ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
const wxSize sizeBmp = wxArtProvider::GetSizeHint(wxART_BUTTON);
wxBitmap bmp = GetCloseButtonBitmap(this, sizeBmp, colBg);
#else // !wxHAS_DRAW_TITLE_BAR_BITMAP
wxBitmap bmp = wxArtProvider::GetBitmap(wxART_CLOSE, wxART_BUTTON);
#endif // wxHAS_DRAW_TITLE_BAR_BITMAP
m_button = new wxBitmapButton
(
this,
wxID_ANY,
bmp,
wxDefaultPosition,
wxDefaultSize,
wxBORDER_NONE
);
#ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
m_button->SetBitmapPressed(
GetCloseButtonBitmap(this, sizeBmp, colBg, wxCONTROL_PRESSED));
m_button->SetBitmapCurrent(
GetCloseButtonBitmap(this, sizeBmp, colBg, wxCONTROL_CURRENT));
#endif // wxHAS_DRAW_TITLE_BAR_BITMAP
m_button->SetBackgroundColour(colBg);
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_button, wxSizerFlags().Centre().Border());
SetSizer(sizer);
return true;
}
bool wxInfoBarGeneric::SetFont(const wxFont& font)
{
if ( !wxInfoBarBase::SetFont(font) )
return false;
// check that we're not called before Create()
if ( m_text )
m_text->SetFont(font);
return true;
}
wxInfoBarGeneric::BarPlacement wxInfoBarGeneric::GetBarPlacement() const
{
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;
}
wxShowEffect wxInfoBarGeneric::GetShowEffect() const
{
if ( m_showEffect != wxSHOW_EFFECT_MAX )
return m_showEffect;
switch ( GetBarPlacement() )
{
case BarPlacement_Top:
return wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
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;
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::UpdateParent()
{
wxWindow * const parent = GetParent();
parent->Layout();
}
void wxInfoBarGeneric::DoHide()
{
HideWithEffect(GetHideEffect(), GetEffectDuration());
UpdateParent();
}
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
// internal visibility flag to force Layout() to take us into account (an
// alternative solution to this hack would be to temporarily set
// wxRESERVE_SPACE_EVEN_IF_HIDDEN flag but it's not really batter)
// just change the internal flag indicating that the window is visible,
// without really showing it
wxWindowBase::Show();
// adjust the parent layout to account for us
UpdateParent();
// reset the flag back before really showing the window or it wouldn't be
// shown at all because it would believe itself already visible
wxWindowBase::Show(false);
// finally do really show the window.
ShowWithEffect(GetShowEffect(), GetEffectDuration());
}
void wxInfoBarGeneric::ShowMessage(const wxString& msg, int flags)
{
// first update the controls
const int icon = flags & wxICON_MASK;
if ( !icon || (icon == wxICON_NONE) )
{
m_icon->Hide();
}
else // do show an icon
{
m_icon->SetBitmap(wxArtProvider::GetBitmap(
wxArtProvider::GetMessageBoxIconId(flags),
wxART_BUTTON));
m_icon->Show();
}
// notice the use of EscapeMnemonics() to ensure that "&" come through
// correctly
m_text->SetLabel(wxControl::EscapeMnemonics(msg));
// then show this entire window if not done yet
if ( !IsShown() )
{
DoShow();
}
else // we're already shown
{
// just update the layout to correspond to the new message
Layout();
}
}
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();
}
#endif // wxUSE_INFOBAR