mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-03 09:09:47 +02:00
941 lines
23 KiB
C++
941 lines
23 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
ToolBar.cpp
|
|
|
|
Dominic Mazzoni
|
|
Shane T. Mueller
|
|
Leland Lucius
|
|
|
|
See ToolBar.h for details.
|
|
|
|
*******************************************************************//**
|
|
|
|
\file ToolBar.cpp
|
|
|
|
Implements ToolBar
|
|
|
|
*//*******************************************************************//**
|
|
|
|
\class ToolBar
|
|
\brief Works with ToolManager and ToolDock to provide a dockable window
|
|
in which buttons can be placed.
|
|
|
|
*//**********************************************************************/
|
|
|
|
#include "../Audacity.h"
|
|
|
|
// For compilers that support precompilation, includes "wx/wx.h".
|
|
#include <wx/wxprec.h>
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include <wx/defs.h>
|
|
#include <wx/gdicmn.h>
|
|
#include <wx/image.h>
|
|
#include <wx/intl.h>
|
|
#include <wx/settings.h>
|
|
#include <wx/sizer.h>
|
|
#include <wx/sysopt.h>
|
|
#include <wx/window.h>
|
|
#endif /* */
|
|
|
|
#include "ToolBar.h"
|
|
#include "ToolDock.h"
|
|
#include "../Experimental.h"
|
|
|
|
#include "../AllThemeResources.h"
|
|
#include "../AColor.h"
|
|
#include "../ImageManipulation.h"
|
|
#include "../Project.h"
|
|
#include "../Theme.h"
|
|
#include "../commands/Keyboard.h"
|
|
#include "../widgets/AButton.h"
|
|
#include "../widgets/Grabber.h"
|
|
#include "../Prefs.h"
|
|
|
|
////////////////////////////////////////////////////////////
|
|
/// ToolBarResizer
|
|
////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Width of the resize grab area
|
|
//
|
|
#define RWIDTH 4
|
|
|
|
class ToolBarResizer final : public wxWindow
|
|
{
|
|
public:
|
|
ToolBarResizer(ToolBar *mBar);
|
|
virtual ~ToolBarResizer();
|
|
|
|
// We don't need or want to accept focus.
|
|
// Note that AcceptsFocusFromKeyboard() is overriden rather than
|
|
// AcceptsFocus(), so that resize can be cancelled by ESC
|
|
bool AcceptsFocusFromKeyboard() const override {return false;}
|
|
|
|
private:
|
|
void OnErase(wxEraseEvent & event);
|
|
void OnPaint(wxPaintEvent & event);
|
|
void OnLeftDown(wxMouseEvent & event);
|
|
void OnLeftUp(wxMouseEvent & event);
|
|
void OnEnter(wxMouseEvent & event);
|
|
void OnLeave(wxMouseEvent & event);
|
|
void OnMotion(wxMouseEvent & event);
|
|
void ResizeBar(const wxSize &size);
|
|
void OnCaptureLost(wxMouseCaptureLostEvent & event);
|
|
void OnKeyDown(wxKeyEvent &event);
|
|
|
|
private:
|
|
ToolBar *mBar;
|
|
wxPoint mResizeStart;
|
|
wxSize mOrigSize;
|
|
wxWindow *mOrigFocus{};
|
|
|
|
DECLARE_EVENT_TABLE()
|
|
};
|
|
|
|
//
|
|
// Event table
|
|
//
|
|
BEGIN_EVENT_TABLE( ToolBarResizer, wxWindow )
|
|
EVT_ERASE_BACKGROUND( ToolBarResizer::OnErase )
|
|
EVT_PAINT( ToolBarResizer::OnPaint )
|
|
EVT_LEFT_DOWN( ToolBarResizer::OnLeftDown )
|
|
EVT_LEFT_UP( ToolBarResizer::OnLeftUp )
|
|
EVT_ENTER_WINDOW( ToolBarResizer::OnEnter )
|
|
EVT_LEAVE_WINDOW( ToolBarResizer::OnLeave )
|
|
EVT_MOTION( ToolBarResizer::OnMotion )
|
|
EVT_MOUSE_CAPTURE_LOST( ToolBarResizer::OnCaptureLost )
|
|
EVT_KEY_DOWN( ToolBarResizer::OnKeyDown )
|
|
END_EVENT_TABLE();
|
|
|
|
ToolBarResizer::ToolBarResizer(ToolBar *bar)
|
|
: wxWindow(bar, wxID_ANY, wxDefaultPosition, wxSize(RWIDTH, -1))
|
|
{
|
|
mBar = bar;
|
|
SetCursor( wxCURSOR_SIZEWE );
|
|
}
|
|
|
|
ToolBarResizer::~ToolBarResizer()
|
|
{
|
|
if(HasCapture())
|
|
ReleaseMouse();
|
|
}
|
|
|
|
//
|
|
// Handle background erasure
|
|
//
|
|
void ToolBarResizer::OnErase( wxEraseEvent & WXUNUSED(event) )
|
|
{
|
|
// Ignore it to prevent flashing
|
|
}
|
|
|
|
//
|
|
// This draws the background of a toolbar
|
|
//
|
|
void ToolBarResizer::OnPaint( wxPaintEvent & event )
|
|
{
|
|
wxPaintDC dc( (wxWindow *) event.GetEventObject() );
|
|
|
|
// Start with a clean background
|
|
//
|
|
// Under GTK, we specifically set the toolbar background to the background
|
|
// colour in the system theme.
|
|
#if defined( __WXGTK__ )
|
|
// dc.SetBackground( wxBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BACKGROUND ) ) );
|
|
#endif
|
|
dc.SetBackground( wxBrush( theTheme.Colour( clrMedium ) ) );
|
|
dc.Clear();
|
|
|
|
wxSize sz = GetSize();
|
|
|
|
AColor::Dark( &dc, false );
|
|
AColor::Line(dc, sz.x - 4, 0, sz.x - 4, sz.y );
|
|
AColor::Line(dc, sz.x - 1, 0, sz.x - 1, sz.y );
|
|
}
|
|
|
|
//
|
|
// Handle toolbar resizing
|
|
//
|
|
void ToolBarResizer::OnLeftDown( wxMouseEvent & event )
|
|
{
|
|
// Go ahead and set the event to propagate
|
|
event.Skip();
|
|
|
|
// Retrieve the mouse position
|
|
mResizeStart = ClientToScreen( event.GetPosition() );
|
|
|
|
mOrigSize = mBar->GetSize();
|
|
|
|
// We want all of the mouse events
|
|
if( !HasCapture() )
|
|
CaptureMouse();
|
|
}
|
|
|
|
void ToolBarResizer::OnLeftUp( wxMouseEvent & event )
|
|
{
|
|
// Go ahead and set the event to propagate
|
|
event.Skip();
|
|
|
|
if( HasCapture() )
|
|
{
|
|
ReleaseMouse();
|
|
if (mOrigFocus)
|
|
mOrigFocus->SetFocus();
|
|
mOrigFocus = nullptr;
|
|
}
|
|
}
|
|
|
|
void ToolBarResizer::OnEnter( wxMouseEvent & /*event*/ )
|
|
{
|
|
// Bug 1201: On Mac, unsetting and re-setting the tooltip may be needed
|
|
// to make it pop up when we want it.
|
|
const auto text = GetToolTipText();
|
|
UnsetToolTip();
|
|
SetToolTip(text);
|
|
if (!mOrigFocus)
|
|
mOrigFocus = FindFocus();
|
|
}
|
|
|
|
void ToolBarResizer::OnLeave( wxMouseEvent & /*event*/ )
|
|
{
|
|
if (!GetCapture())
|
|
mOrigFocus = nullptr;
|
|
}
|
|
|
|
void ToolBarResizer::OnMotion( wxMouseEvent & event )
|
|
{
|
|
// Go ahead and set the event to propagate
|
|
event.Skip();
|
|
|
|
// Retrieve the mouse position
|
|
wxPoint raw_pos = event.GetPosition();
|
|
wxPoint pos = ClientToScreen( raw_pos );
|
|
|
|
if( HasCapture() && event.Dragging() )
|
|
{
|
|
wxRect r = mBar->GetRect();
|
|
wxSize msz = mBar->GetMinSize();
|
|
wxSize psz = mBar->GetParent()->GetClientSize();
|
|
|
|
// Adjust the size by the difference between the
|
|
// last mouse and current mouse positions.
|
|
r.width += ( pos.x - mResizeStart.x );
|
|
|
|
// Constrain
|
|
if( r.width < msz.x )
|
|
{
|
|
// Don't allow resizing to go too small
|
|
r.width = msz.x;
|
|
}
|
|
else if( r.GetRight() > psz.x - 3 )
|
|
{
|
|
// Don't allow resizing to go too large
|
|
//
|
|
// The 3 magic pixels are because I'm too chicken to change the
|
|
// calculations in ToolDock::LayoutToolBars() even though I'm
|
|
// the one that set them up. :-)
|
|
r.SetRight( psz.x - 3 );
|
|
}
|
|
else
|
|
{
|
|
// Remember for next go round
|
|
mResizeStart = pos;
|
|
}
|
|
|
|
ResizeBar( r.GetSize() );
|
|
}
|
|
}
|
|
|
|
void ToolBarResizer::ResizeBar(const wxSize &size)
|
|
{
|
|
mBar->SetSize( size );
|
|
|
|
// Tell everyone we've changed sizes
|
|
mBar->Updated();
|
|
|
|
// Refresh our world
|
|
mBar->GetParent()->Refresh();
|
|
mBar->GetParent()->Update();
|
|
}
|
|
|
|
void ToolBarResizer::OnCaptureLost( wxMouseCaptureLostEvent & WXUNUSED(event) )
|
|
{
|
|
if( HasCapture() )
|
|
{
|
|
ReleaseMouse();
|
|
if (mOrigFocus)
|
|
mOrigFocus->SetFocus();
|
|
mOrigFocus = nullptr;
|
|
}
|
|
}
|
|
|
|
void ToolBarResizer::OnKeyDown(wxKeyEvent &event)
|
|
{
|
|
event.Skip();
|
|
if (HasCapture() && WXK_ESCAPE == event.GetKeyCode()) {
|
|
ResizeBar( mOrigSize );
|
|
ReleaseMouse();
|
|
if (mOrigFocus)
|
|
mOrigFocus->SetFocus();
|
|
mOrigFocus = nullptr;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
/// Methods for ToolBar
|
|
////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Define class to RTTI
|
|
//
|
|
IMPLEMENT_CLASS( ToolBar, wxPanelWrapper );
|
|
|
|
//
|
|
// Custom event
|
|
//
|
|
DEFINE_EVENT_TYPE(EVT_TOOLBAR_UPDATED)
|
|
|
|
//
|
|
// Event table
|
|
//
|
|
BEGIN_EVENT_TABLE( ToolBar, wxPanelWrapper )
|
|
EVT_PAINT( ToolBar::OnPaint )
|
|
EVT_ERASE_BACKGROUND( ToolBar::OnErase )
|
|
EVT_MOUSE_EVENTS( ToolBar::OnMouseEvents )
|
|
END_EVENT_TABLE()
|
|
|
|
//
|
|
// Constructor
|
|
//
|
|
ToolBar::ToolBar( int type,
|
|
const wxString &label,
|
|
const wxString §ion,
|
|
bool resizable )
|
|
: wxPanelWrapper()
|
|
{
|
|
// Save parameters
|
|
mType = type;
|
|
mLabel = label;
|
|
mSection = section;
|
|
mResizable = resizable;
|
|
|
|
// Initialize everything
|
|
mParent = NULL;
|
|
mHSizer = NULL;
|
|
mSpacer = NULL;
|
|
mVisible = false;
|
|
mPositioned = false;
|
|
|
|
mGrabber = NULL;
|
|
mResizer = NULL;
|
|
|
|
SetId(mType);
|
|
}
|
|
|
|
//
|
|
// Destructor
|
|
//
|
|
ToolBar::~ToolBar()
|
|
{
|
|
}
|
|
|
|
//
|
|
// Returns the toolbar title
|
|
//
|
|
wxString ToolBar::GetTitle()
|
|
{
|
|
/* i18n-hint: %s will be replaced by the name of the kind of toolbar.*/
|
|
return wxString::Format( _("Audacity %s Toolbar"), GetLabel().c_str() );
|
|
}
|
|
|
|
//
|
|
// Returns the toolbar label
|
|
//
|
|
wxString ToolBar::GetLabel()
|
|
{
|
|
return mLabel;
|
|
}
|
|
|
|
//
|
|
// Returns the toolbar preferences section
|
|
//
|
|
wxString ToolBar::GetSection()
|
|
{
|
|
return mSection;
|
|
}
|
|
|
|
//
|
|
// Returns the toolbar type
|
|
//
|
|
int ToolBar::GetType()
|
|
{
|
|
return mType;
|
|
}
|
|
|
|
//
|
|
// Set the toolbar label
|
|
//
|
|
void ToolBar::SetLabel(const wxString & label)
|
|
{
|
|
mLabel = label;
|
|
}
|
|
|
|
//
|
|
// Returns whether the toolbar is resizable or not
|
|
//
|
|
bool ToolBar::IsResizable() const
|
|
{
|
|
return mResizable;
|
|
}
|
|
|
|
//
|
|
// Returns the dock state of the toolbar
|
|
//
|
|
bool ToolBar::IsDocked() const
|
|
{
|
|
return const_cast<ToolBar*>(this)->GetDock() != nullptr;
|
|
}
|
|
|
|
//
|
|
// Returns the visibility of the toolbar
|
|
//
|
|
bool ToolBar::IsVisible() const
|
|
{
|
|
return mVisible;
|
|
}
|
|
|
|
void ToolBar::SetVisible( bool bVisible )
|
|
{
|
|
mVisible = bVisible;
|
|
}
|
|
|
|
//
|
|
// Show or hide the toolbar
|
|
//
|
|
bool ToolBar::Expose( bool show )
|
|
{
|
|
bool was = mVisible;
|
|
|
|
SetVisible( show );
|
|
|
|
if( IsDocked() )
|
|
{
|
|
Show( show );
|
|
}
|
|
else
|
|
{
|
|
wxWindow * pParent = GetParent();
|
|
if( !IsPositioned() && show ){
|
|
SetPositioned();
|
|
pParent->CentreOnParent();
|
|
pParent->Move( pParent->GetPosition() + wxSize( mType*10, mType*10 ));
|
|
}
|
|
pParent->Show( show );
|
|
}
|
|
|
|
return was;
|
|
}
|
|
|
|
//
|
|
// Initialize the toolbar
|
|
//
|
|
void ToolBar::Create( wxWindow *parent )
|
|
{
|
|
// Save parameters
|
|
mParent = parent;
|
|
|
|
// Create the window and label it
|
|
wxPanelWrapper::Create( mParent,
|
|
mType,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxNO_BORDER | wxTAB_TRAVERSAL,
|
|
GetTitle() );
|
|
wxPanelWrapper::SetLabel( GetLabel() );
|
|
|
|
// Go do the rest of the creation
|
|
ReCreateButtons();
|
|
|
|
// ToolManager depends on this appearing to be visible for proper dock construction
|
|
mVisible = true;
|
|
}
|
|
|
|
void ToolBar::ReCreateButtons()
|
|
{
|
|
wxSize sz3 = GetSize();
|
|
//wxLogDebug( "x:%i y:%i",sz3.x, sz3.y);
|
|
|
|
// SetSizer(NULL) detaches mHSizer and deletes it.
|
|
// Do not use Detach() here, as that attempts to detach mHSizer from itself!
|
|
SetSizer( NULL );
|
|
|
|
// Get rid of any children we may have
|
|
DestroyChildren();
|
|
mGrabber = NULL;
|
|
mResizer = NULL;
|
|
|
|
{
|
|
// Create the main sizer
|
|
auto ms = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
|
|
|
|
// Create the grabber and add it to the main sizer
|
|
mGrabber = safenew Grabber(this, mType);
|
|
ms->Add(mGrabber, 0, wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP | wxRIGHT, 1);
|
|
|
|
// Use a box sizer for laying out controls
|
|
ms->Add((mHSizer = safenew wxBoxSizer(wxHORIZONTAL)), 1, wxEXPAND);
|
|
|
|
// Go add all the rest of the gadgets
|
|
Populate();
|
|
|
|
// Add some space for the resize border
|
|
if (IsResizable())
|
|
{
|
|
// Create the resizer and add it to the main sizer
|
|
mResizer = safenew ToolBarResizer(this);
|
|
ms->Add(mResizer, 0, wxEXPAND | wxALIGN_TOP | wxLEFT, 1);
|
|
mResizer->SetToolTip(_("Click and drag to resize toolbar"));
|
|
}
|
|
|
|
// Set dock after possibly creating resizer.
|
|
// (Re)Establish dock state
|
|
SetDocked(GetDock(), false);
|
|
|
|
// Set the sizer
|
|
SetSizerAndFit(ms.release());
|
|
}
|
|
|
|
// Recalculate the height to be a multiple of toolbarSingle
|
|
const int tbs = toolbarSingle + toolbarGap;
|
|
wxSize sz = GetSize();
|
|
sz.y = ( ( ( sz.y + tbs -1) / tbs ) * tbs ) - 1;
|
|
|
|
// Set the true AND minimum sizes and do final layout
|
|
if(IsResizable())
|
|
{
|
|
// JKC we're going to allow all resizable toolbars to be resized
|
|
// to 1 unit high, typically 27 pixels.
|
|
wxSize sz2 = sz;
|
|
sz2.SetWidth(GetMinToolbarWidth());
|
|
sz2.y = tbs -1;
|
|
SetMinSize(sz2);
|
|
// Initial size at least as big as minimum.
|
|
if( sz3.y < sz2.y )
|
|
sz3.y = sz2.y;
|
|
if( sz3.x < sz2.x )
|
|
sz3.x = GetInitialWidth();
|
|
//sz.SetWidth();
|
|
SetSize(sz3);
|
|
}
|
|
else
|
|
{
|
|
SetInitialSize(sz);
|
|
}
|
|
Layout();
|
|
}
|
|
|
|
// The application preferences have changed, so update any elements that may
|
|
// depend on them.
|
|
void ToolBar::UpdatePrefs()
|
|
{
|
|
#if wxUSE_TOOLTIPS
|
|
// Change the tooltip of the grabber
|
|
if ( mGrabber )
|
|
{
|
|
mGrabber->SetToolTip( GetTitle() );
|
|
}
|
|
|
|
// Change the tooltip of the resizer
|
|
if ( mResizer )
|
|
{
|
|
mResizer->SetToolTip( _("Click and drag to resize toolbar") );
|
|
wxSizeEvent e;
|
|
GetParent()->GetEventHandler()->AddPendingEvent( e );
|
|
GetParent()->Refresh();
|
|
}
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Return the pointer to the ToolBock where this bar lives
|
|
//
|
|
ToolDock *ToolBar::GetDock()
|
|
{
|
|
return dynamic_cast<ToolDock*>(GetParent());
|
|
}
|
|
|
|
//
|
|
// Toggle the docked/floating state
|
|
//
|
|
void ToolBar::SetDocked( ToolDock *dock, bool pushed )
|
|
{
|
|
// Remember it
|
|
// mDock = dock;
|
|
|
|
// Change the tooltip of the grabber
|
|
#if wxUSE_TOOLTIPS
|
|
mGrabber->SetToolTip( GetTitle() );
|
|
#endif
|
|
|
|
// Set the grabber button state
|
|
mGrabber->PushButton( pushed );
|
|
|
|
if (mResizer)
|
|
{
|
|
mResizer->Show(dock != NULL);
|
|
Layout();
|
|
Fit();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Notify parent of changes
|
|
//
|
|
void ToolBar::Updated()
|
|
{
|
|
if( IsDocked() )
|
|
GetDock()->Updated();
|
|
//wxCommandEvent e( EVT_TOOLBAR_UPDATED, GetId() );
|
|
//GetParent()->GetEventHandler()->AddPendingEvent( e );
|
|
}
|
|
|
|
//
|
|
// Returns a pointer to the main sizer
|
|
//
|
|
wxBoxSizer *ToolBar::GetSizer()
|
|
{
|
|
return mHSizer;
|
|
}
|
|
|
|
//
|
|
// Add a window to the main sizer
|
|
//
|
|
void ToolBar::Add( wxWindow *window,
|
|
int proportion,
|
|
int flag,
|
|
int border,
|
|
wxObject* userData )
|
|
{
|
|
mHSizer->Add( window,
|
|
proportion,
|
|
flag,
|
|
border,
|
|
userData );
|
|
}
|
|
|
|
//
|
|
// Add a child sizer to the main sizer
|
|
//
|
|
void ToolBar::Add( wxSizer *sizer,
|
|
int proportion,
|
|
int flag,
|
|
int border,
|
|
wxObject* userData )
|
|
{
|
|
mHSizer->Add( sizer,
|
|
proportion,
|
|
flag,
|
|
border,
|
|
userData );
|
|
}
|
|
|
|
//
|
|
// Add some space to the main sizer
|
|
//
|
|
void ToolBar::Add( int width,
|
|
int height,
|
|
int proportion,
|
|
int flag,
|
|
int border,
|
|
wxObject* userData )
|
|
{
|
|
mHSizer->Add( width,
|
|
height,
|
|
proportion,
|
|
flag,
|
|
border,
|
|
userData );
|
|
}
|
|
|
|
//
|
|
// Adds a spacer to the main sizer
|
|
//
|
|
void ToolBar::AddSpacer( int size )
|
|
{
|
|
mHSizer->AddSpacer( size );
|
|
}
|
|
|
|
//
|
|
// Adds a strechable spacer to the main sizer
|
|
//
|
|
void ToolBar::AddStretchSpacer( int prop )
|
|
{
|
|
mHSizer->AddStretchSpacer( prop );
|
|
}
|
|
|
|
//
|
|
// Detach a window from the main sizer
|
|
//
|
|
void ToolBar::Detach( wxWindow *window )
|
|
{
|
|
mHSizer->Detach( window );
|
|
}
|
|
|
|
//
|
|
// Detach a child sizer from the main sizer
|
|
//
|
|
void ToolBar::Detach( wxSizer *sizer )
|
|
{
|
|
mHSizer->Detach( sizer );
|
|
}
|
|
|
|
void ToolBar::MakeMacRecoloredImage(teBmps eBmpOut, teBmps eBmpIn )
|
|
{
|
|
theTheme.ReplaceImage( eBmpOut, &theTheme.Image( eBmpIn ));
|
|
}
|
|
|
|
void ToolBar::MakeRecoloredImage( teBmps eBmpOut, teBmps eBmpIn )
|
|
{
|
|
// Don't recolour the buttons...
|
|
MakeMacRecoloredImage( eBmpOut, eBmpIn );
|
|
return;
|
|
wxImage * pSrc = &theTheme.Image( eBmpIn );
|
|
#if defined( __WXGTK__ )
|
|
wxColour newColour = wxSystemSettings::GetColour( wxSYS_COLOUR_BACKGROUND );
|
|
#else
|
|
wxColour newColour = wxSystemSettings::GetColour( wxSYS_COLOUR_3DFACE );
|
|
#endif
|
|
|
|
newColour = wxColour( 60,60,60 );
|
|
wxColour baseColour = wxColour( 204, 204, 204 );
|
|
|
|
auto pPattern = ChangeImageColour( pSrc, baseColour, newColour );
|
|
|
|
theTheme.ReplaceImage( eBmpOut, pPattern.get());
|
|
}
|
|
|
|
void ToolBar:: MakeButtonBackgroundsLarge()
|
|
{
|
|
|
|
bool bUseAqua = false;
|
|
|
|
#ifdef EXPERIMENTAL_THEME_PREFS
|
|
gPrefs->Read( wxT("/GUI/ShowMac"), &bUseAqua, false);
|
|
#endif
|
|
|
|
#ifdef USE_AQUA_THEME
|
|
bUseAqua = !bUseAqua;
|
|
#endif
|
|
|
|
if( bUseAqua ){
|
|
MakeMacRecoloredImage( bmpRecoloredUpLarge, bmpMacUpButton );
|
|
MakeMacRecoloredImage( bmpRecoloredDownLarge, bmpMacDownButton );
|
|
MakeMacRecoloredImage( bmpRecoloredHiliteLarge, bmpMacHiliteButton );
|
|
} else {
|
|
MakeRecoloredImage( bmpRecoloredUpLarge, bmpUpButtonLarge );
|
|
MakeRecoloredImage( bmpRecoloredDownLarge, bmpDownButtonLarge );
|
|
MakeRecoloredImage( bmpRecoloredHiliteLarge, bmpHiliteButtonLarge );
|
|
}
|
|
}
|
|
|
|
void ToolBar::MakeButtonBackgroundsSmall()
|
|
{
|
|
|
|
bool bUseAqua = false;
|
|
|
|
#ifdef EXPERIMENTAL_THEME_PREFS
|
|
gPrefs->Read( wxT("/GUI/ShowMac"), &bUseAqua, false);
|
|
#endif
|
|
|
|
#ifdef USE_AQUA_THEME
|
|
bUseAqua = !bUseAqua;
|
|
#endif
|
|
|
|
if( bUseAqua ){
|
|
MakeMacRecoloredImage( bmpRecoloredUpSmall, bmpMacUpButtonSmall );
|
|
MakeMacRecoloredImage( bmpRecoloredDownSmall, bmpMacDownButtonSmall );
|
|
MakeMacRecoloredImage( bmpRecoloredHiliteSmall, bmpMacHiliteButtonSmall );
|
|
} else {
|
|
MakeRecoloredImage( bmpRecoloredUpSmall, bmpUpButtonSmall );
|
|
MakeRecoloredImage( bmpRecoloredDownSmall, bmpDownButtonSmall );
|
|
MakeRecoloredImage( bmpRecoloredHiliteSmall, bmpHiliteButtonSmall );
|
|
}
|
|
}
|
|
|
|
/// Makes a button and its four different state bitmaps
|
|
/// @param parent Parent window for the button.
|
|
/// @param eUp Background for when button is Up.
|
|
/// @param eDown Background for when button is Down.
|
|
/// @param eHilite Background for when button is Hilit.
|
|
/// @param eStandardUp Foreground when enabled, up.
|
|
/// @param eStandardDown Foregrounde when enabled, down.
|
|
/// @param eDisabled Foreground when disabled.
|
|
/// @param id Windows Id.
|
|
/// @param placement Placement position
|
|
/// @param processdownevents true iff button handles down events.
|
|
/// @param size Size of the background.
|
|
AButton * ToolBar::MakeButton(wxWindow *parent,
|
|
teBmps eUp,
|
|
teBmps eDown,
|
|
teBmps eHilite,
|
|
teBmps eStandardUp,
|
|
teBmps eStandardDown,
|
|
teBmps eDisabled,
|
|
wxWindowID id,
|
|
wxPoint placement,
|
|
bool processdownevents,
|
|
wxSize size)
|
|
{
|
|
// wxMax to cater for case of image being bigger than the button.
|
|
int xoff = wxMax( 0, (size.GetWidth() - theTheme.Image(eStandardUp).GetWidth())/2);
|
|
int yoff = wxMax( 0, (size.GetHeight() - theTheme.Image(eStandardUp).GetHeight())/2);
|
|
|
|
typedef std::unique_ptr<wxImage> wxImagePtr;
|
|
wxImagePtr up2 (OverlayImage(eUp, eStandardUp, xoff, yoff));
|
|
wxImagePtr hilite2 (OverlayImage(eHilite, eStandardUp, xoff, yoff));
|
|
wxImagePtr down2 (OverlayImage(eDown, eStandardDown, xoff + 1, yoff + 1));
|
|
wxImagePtr disable2 (OverlayImage(eUp, eDisabled, xoff, yoff));
|
|
|
|
wxASSERT(parent); // to justify safenew
|
|
AButton * button =
|
|
safenew AButton(parent, id, placement, size, *up2, *hilite2, *down2,
|
|
*disable2, processdownevents);
|
|
|
|
return button;
|
|
}
|
|
|
|
//static
|
|
void ToolBar::MakeAlternateImages(AButton &button, int idx,
|
|
teBmps eUp,
|
|
teBmps eDown,
|
|
teBmps eHilite,
|
|
teBmps eStandardUp,
|
|
teBmps eStandardDown,
|
|
teBmps eDisabled,
|
|
wxSize size)
|
|
{
|
|
// wxMax to cater for case of image being bigger than the button.
|
|
int xoff = wxMax( 0, (size.GetWidth() - theTheme.Image(eStandardUp).GetWidth())/2);
|
|
int yoff = wxMax( 0, (size.GetHeight() - theTheme.Image(eStandardUp).GetHeight())/2);
|
|
|
|
typedef std::unique_ptr<wxImage> wxImagePtr;
|
|
wxImagePtr up (OverlayImage(eUp, eStandardUp, xoff, yoff));
|
|
wxImagePtr hilite (OverlayImage(eHilite, eStandardUp, xoff, yoff));
|
|
wxImagePtr down (OverlayImage(eDown, eStandardDown, xoff + 1, yoff + 1));
|
|
wxImagePtr disable (OverlayImage(eUp, eDisabled, xoff, yoff));
|
|
|
|
button.SetAlternateImages(idx, *up, *hilite, *down, *disable);
|
|
}
|
|
|
|
void ToolBar::SetButtonToolTip
|
|
(AButton &button, const std::vector<wxString> &commands)
|
|
{
|
|
wxString result;
|
|
const auto project = GetActiveProject();
|
|
const auto commandManager =
|
|
project ? project->GetCommandManager() : nullptr;
|
|
if (commandManager)
|
|
result =
|
|
commandManager->DescribeCommandsAndShortcuts(commands);
|
|
button.SetToolTip(result);
|
|
}
|
|
|
|
//
|
|
// This changes the state a button (from up to down or vice versa)
|
|
//
|
|
void ToolBar::SetButton( bool down, AButton * button )
|
|
{
|
|
if( down )
|
|
{
|
|
button->PushDown();
|
|
}
|
|
else
|
|
{
|
|
button->PopUp();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle background erasure
|
|
//
|
|
void ToolBar::OnErase( wxEraseEvent & WXUNUSED(event) )
|
|
{
|
|
// Ignore it to prevent flashing
|
|
}
|
|
|
|
//
|
|
// This draws the background of a toolbar
|
|
//
|
|
void ToolBar::OnPaint( wxPaintEvent & event )
|
|
{
|
|
wxPaintDC dc( (wxWindow *) event.GetEventObject() );
|
|
|
|
// Start with a clean background
|
|
//
|
|
// Under GTK, we specifically set the toolbar background to the background
|
|
// colour in the system theme.
|
|
#if defined( __WXGTK__ )
|
|
//dc.SetBackground( wxBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BACKGROUND ) ) );
|
|
#endif
|
|
dc.SetBackground( wxBrush( theTheme.Colour( clrMedium ) ) );
|
|
dc.Clear();
|
|
|
|
// EXPERIMENTAL_THEMING is set to not apply the gradient
|
|
// on wxMAC builds. on wxMAC we have the AQUA_THEME.
|
|
#ifdef USE_AQUA_THEME
|
|
Repaint( &dc );
|
|
#else
|
|
return;
|
|
#ifdef EXPERIMENTAL_THEMING
|
|
wxImage * mpBackGradient = &theTheme.Image( bmpRecoloredUpLarge );
|
|
|
|
if( mpBackGradient != NULL )
|
|
{
|
|
wxSize imSz( mpBackGradient->GetWidth(), mpBackGradient->GetHeight() );
|
|
wxSize sz = GetSize();
|
|
int y;
|
|
for(y=0;y<sz.y;y++)
|
|
{
|
|
int yPix = ((float)y * imSz.y - 1.0f)/(sz.y-1);
|
|
wxColour col(
|
|
mpBackGradient->GetRed( 0, yPix),
|
|
mpBackGradient->GetGreen( 0, yPix),
|
|
mpBackGradient->GetBlue( 0, yPix));
|
|
|
|
// Set background colour so that controls placed on this
|
|
// toolbar such as radio buttons will draw reasonably.
|
|
// It's a little tacky setting the background colour
|
|
// here, but we can't do it in the constructor as the gradient
|
|
// may not be available yet.
|
|
// Better than this would be to set the colour when the image
|
|
// is loaded.
|
|
// We use the colour at the half way point as a suitable 'average'.
|
|
if( y==(sz.y/2) )
|
|
{
|
|
SetBackgroundColour( col );
|
|
}
|
|
wxPen Pen( col );
|
|
dc.SetPen(Pen );
|
|
AColor::Line(dc, 0, y, sz.x, y );
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void ToolBar::OnMouseEvents(wxMouseEvent &event)
|
|
{
|
|
// Do this hack so scrubber can detect mouse drags anywhere
|
|
event.ResumePropagation(wxEVENT_PROPAGATE_MAX);
|
|
event.Skip();
|
|
}
|
|
|
|
int ToolBar::GetResizeGrabberWidth()
|
|
{
|
|
return RWIDTH;
|
|
}
|