mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-01 16:19:43 +02:00
2289 lines
64 KiB
C++
2289 lines
64 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
ShuttleGui.cpp
|
|
|
|
James Crook
|
|
|
|
Audacity is free software.
|
|
This file is licensed under the wxWidgets license, see License.txt
|
|
|
|
**********************************************************************//**
|
|
|
|
\file ShuttleGui.cpp
|
|
\brief Implements ShuttleGui, ShuttleGuiBase and InvisiblePanel.
|
|
|
|
*//***************************************************************//**
|
|
|
|
\class ShuttleGui
|
|
\brief
|
|
Derived from ShuttleGuiBase, an Audacity specific class for shuttling
|
|
data to and from GUI.
|
|
|
|
ShuttleGui extends the idea of the data Shuttle class to include creation
|
|
of dialog controls. As part of this it provides an interface to sizers
|
|
that leads to shorter more readable code.
|
|
|
|
It also allows the code that is used to create dialogs to be reused
|
|
to shuttle information in and out.
|
|
|
|
Most of the ShuttleGui functions are actually defined in
|
|
ShuttleGuiBase.
|
|
- wxWidgets widgets are dealt with by ShuttleGuiBase.
|
|
- Audacity specific widgets are dealt with by ShuttleGui
|
|
|
|
There is documentation on how to use this class in \ref ShuttleSystem
|
|
|
|
*//***************************************************************//**
|
|
|
|
\class ShuttleGuiBase
|
|
\brief Base class for shuttling data to and from a GUI.
|
|
|
|
see also ShuttleGui
|
|
|
|
Use the:
|
|
- \p Start / \p End methods for containers, like two-column-layout.
|
|
- \p Add methods if you are only interested in creating the controls.
|
|
- \p Tie methods if you also want to exchange data using ShuttleGui.
|
|
|
|
The code in this file is fairly repetitive. We are dealing with
|
|
- Many different types of Widget.
|
|
- Creation / Reading / Writing / Exporting / Importing
|
|
- int, float, string variants (for example of TextCtrl contents).
|
|
|
|
A technique used to reduce the size of the \p Tie functions is to
|
|
have one generic \p Tie function that uses WrappedType for its
|
|
data type. Type specific \p Tie functions themselves call the generic
|
|
variant.
|
|
|
|
A second technique used to reduce the size of \p Tie functions
|
|
only comes into play for two-step \p Tie functions. (A two step
|
|
\p Tie function is one that transfers data between the registry
|
|
and the GUI via an intermediate temporary variable). In the two
|
|
step style, a function ShuttleGuiBase::DoStep() determines which
|
|
transfers in the function are to be done, reducing repetitive
|
|
if-then-else's.
|
|
|
|
Although unusual, these two techniques make the code easier to
|
|
add to and much easier to check for correctness. The alternative
|
|
'more obvious' code that just repeats code as needed is
|
|
considerably longer.
|
|
|
|
You would rarely use ShuttleGuiBase directly, instead you'd use
|
|
ShuttleGui.
|
|
|
|
There is DOxygen documentation on how to use the ShuttleGui
|
|
class in \ref ShuttleSystem .
|
|
|
|
*//***************************************************************//**
|
|
|
|
\class InvisiblePanel
|
|
\brief An InvisiblePanel is a panel which does not repaint its
|
|
own background.
|
|
|
|
It is used (a) To group together widgets which need to be refreshed
|
|
together. A single refresh of the panel causes all the subwindows to
|
|
refresh. (b) as a base class for some flicker-free classes for which
|
|
the backgorund is never repainted.
|
|
|
|
JKC: InvisiblePanel will probably be replaced in time by a mechanism
|
|
for registering for changes.
|
|
|
|
*//******************************************************************/
|
|
|
|
|
|
#include "Audacity.h"
|
|
|
|
#include <wx/wx.h>
|
|
#include <wx/wxprec.h>
|
|
#include <wx/listctrl.h>
|
|
#include <wx/notebook.h>
|
|
#include <wx/treectrl.h>
|
|
#include <wx/spinctrl.h>
|
|
#include "Internat.h"
|
|
#include "Experimental.h"
|
|
#include "ShuttleGui.h"
|
|
#include "Shuttle.h"
|
|
#include "WrappedType.h"
|
|
|
|
ShuttleGuiBase::ShuttleGuiBase(wxWindow * pParent, teShuttleMode ShuttleMode )
|
|
{
|
|
wxASSERT( (pParent != NULL ) || ( ShuttleMode != eIsCreating));
|
|
|
|
mpParent = pParent;
|
|
mShuttleMode = ShuttleMode;
|
|
mpDlg = pParent;
|
|
Init();
|
|
}
|
|
|
|
ShuttleGuiBase::~ShuttleGuiBase()
|
|
{
|
|
}
|
|
|
|
void ShuttleGuiBase::Init()
|
|
{
|
|
mpShuttle = NULL;
|
|
mpSizer = NULL;
|
|
mpWind = NULL;
|
|
mpSubSizer = NULL;
|
|
|
|
mSettingName = wxT("");
|
|
mRadioCount = -1;
|
|
|
|
miBorder = 5;
|
|
miStyle = 0;
|
|
miProp=0;
|
|
miPropSetByUser=-1;
|
|
miSizerProp=0;
|
|
mSizerDepth=-1;
|
|
|
|
miIdSetByUser = -1;
|
|
miId = -1;
|
|
miIdNext = 3000;
|
|
|
|
miNoMatchSelector = 0;
|
|
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
|
|
mpSizer = mpParent->GetSizer();
|
|
|
|
#if 0
|
|
if( mpSizer == NULL )
|
|
{
|
|
wxWindow * pGrandParent = mpParent->GetParent();
|
|
if( pGrandParent )
|
|
{
|
|
mpSizer = pGrandParent->GetSizer();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if( !mpSizer )
|
|
{
|
|
mpSizer = new wxBoxSizer( wxVERTICAL );
|
|
mpParent->SetSizer( mpSizer );
|
|
}
|
|
PushSizer();
|
|
mpSizer->SetMinSize(250,100);
|
|
}
|
|
|
|
void ShuttleGuiBase::EnableCtrl( bool bEnable )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
mpLastWind->Enable( bEnable );
|
|
}
|
|
|
|
/// Used to modify an already placed Window.
|
|
void ShuttleGuiBase::SetSizeHints( int minX, int minY )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
mpLastWind->SetSizeHints( minX, minY );
|
|
}
|
|
|
|
|
|
/// Used to modify an already placed FlexGridSizer to make a column stretchy.
|
|
void ShuttleGuiBase::SetStretchyCol( int i )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
wxFlexGridSizer *pSizer = wxDynamicCast(mpSizer, wxFlexGridSizer);
|
|
wxASSERT( pSizer );
|
|
pSizer->AddGrowableCol( i, 1 );
|
|
}
|
|
|
|
/// Used to modify an already placed FlexGridSizer to make a row stretchy.
|
|
void ShuttleGuiBase::SetStretchyRow( int i )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
wxFlexGridSizer *pSizer = wxDynamicCast(mpSizer, wxFlexGridSizer);
|
|
wxASSERT( pSizer );
|
|
pSizer->AddGrowableRow( i, 1 );
|
|
}
|
|
|
|
|
|
//---- Add Functions.
|
|
|
|
/// Right aligned text string.
|
|
void ShuttleGuiBase::AddPrompt(const wxString &Prompt)
|
|
{
|
|
if( Prompt.IsEmpty() )
|
|
return;
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
miProp=1;
|
|
mpWind = new wxStaticText(mpParent, -1, Prompt, wxDefaultPosition, wxDefaultSize,
|
|
Style( wxALIGN_RIGHT ));
|
|
UpdateSizersCore( false, wxALL | wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL );
|
|
}
|
|
|
|
/// Left aligned text string.
|
|
void ShuttleGuiBase::AddUnits(const wxString &Prompt)
|
|
{
|
|
if( Prompt.IsEmpty() )
|
|
return;
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
miProp=1;
|
|
mpWind = new wxStaticText(mpParent, -1, Prompt, wxDefaultPosition, wxDefaultSize,
|
|
Style( wxALIGN_LEFT ));
|
|
UpdateSizersCore( false, wxALL | wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL );
|
|
}
|
|
|
|
/// Centred text string.
|
|
void ShuttleGuiBase::AddTitle(const wxString &Prompt)
|
|
{
|
|
if( Prompt.IsEmpty() )
|
|
return;
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
mpWind = new wxStaticText(mpParent, -1, Prompt, wxDefaultPosition, wxDefaultSize,
|
|
Style( wxALIGN_CENTRE ));
|
|
UpdateSizers();
|
|
}
|
|
|
|
/// Very generic 'Add' function. We can add anything we like.
|
|
/// Useful for unique controls
|
|
wxWindow * ShuttleGuiBase::AddWindow(wxWindow * pWindow, int Flags )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return pWindow;
|
|
mpWind = pWindow;
|
|
SetProportions( 0 );
|
|
UpdateSizersCore(false, Flags);
|
|
return pWindow;
|
|
}
|
|
|
|
wxCheckBox * ShuttleGuiBase::AddCheckBox( const wxString &Prompt, const wxString &Selected)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxCheckBox);
|
|
wxCheckBox * pCheckBox;
|
|
miProp=0;
|
|
mpWind = pCheckBox = new wxCheckBox(mpParent, miId, Prompt, wxDefaultPosition, wxDefaultSize,
|
|
Style( 0 ));
|
|
pCheckBox->SetValue(Selected == wxT("true"));
|
|
pCheckBox->SetName(wxStripMenuCodes(Prompt));
|
|
UpdateSizers();
|
|
return pCheckBox;
|
|
}
|
|
|
|
/// For a consistant two-column layout we want labels on the left and
|
|
/// controls on the right. CheckBoxes break that rule, so we fake it by
|
|
/// placing a static text label and then a tick box with an empty label.
|
|
wxCheckBox * ShuttleGuiBase::AddCheckBoxOnRight( const wxString &Prompt, const wxString &Selected)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxCheckBox);
|
|
wxCheckBox * pCheckBox;
|
|
miProp=0;
|
|
AddPrompt( Prompt );
|
|
mpWind = pCheckBox = new wxCheckBox(mpParent, miId, wxT(""), wxDefaultPosition, wxDefaultSize,
|
|
Style( 0 ));
|
|
pCheckBox->SetValue(Selected==wxT("true"));
|
|
pCheckBox->SetName(wxStripMenuCodes(Prompt));
|
|
UpdateSizers();
|
|
return pCheckBox;
|
|
}
|
|
|
|
wxButton * ShuttleGuiBase::AddButton(const wxString &Text, int PositionFlags)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxButton);
|
|
wxButton * pBtn;
|
|
mpWind = pBtn = new wxButton( mpParent, miId, Text, wxDefaultPosition, wxDefaultSize,
|
|
Style( 0 ) );
|
|
mpWind->SetName(wxStripMenuCodes(Text));
|
|
miProp=0;
|
|
UpdateSizersCore(false, PositionFlags | wxALL);
|
|
return pBtn;
|
|
}
|
|
|
|
wxBitmapButton * ShuttleGuiBase::AddBitmapButton(const wxBitmap &Bitmap, int PositionFlags)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxBitmapButton);
|
|
wxBitmapButton * pBtn;
|
|
mpWind = pBtn = new wxBitmapButton( mpParent, miId, Bitmap,
|
|
wxDefaultPosition, wxDefaultSize, Style( wxNO_BORDER ) );
|
|
pBtn->SetBackgroundColour(
|
|
wxColour( 246,246,243));
|
|
// wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
|
|
miProp=0;
|
|
UpdateSizersCore(false, PositionFlags | wxALL);
|
|
return pBtn;
|
|
}
|
|
|
|
wxChoice * ShuttleGuiBase::AddChoice( const wxString &Prompt, const wxString &Selected, const wxArrayString * pChoices )
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxChoice);
|
|
wxChoice * pChoice;
|
|
miProp=0;
|
|
|
|
AddPrompt( Prompt );
|
|
mpWind = pChoice = new wxChoice(
|
|
mpParent,
|
|
miId,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
*pChoices,
|
|
Style( 0 ) );
|
|
|
|
pChoice->SetSizeHints( 180,-1);// Use -1 for 'default size' - Platform specific.
|
|
pChoice->SetName(wxStripMenuCodes(Prompt));
|
|
pChoice->SetStringSelection( Selected );
|
|
|
|
UpdateSizers();
|
|
return pChoice;
|
|
}
|
|
|
|
void ShuttleGuiBase::AddFixedText(const wxString &Str, bool bCenter)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
mpWind = new wxStaticText(mpParent, miId, Str, wxDefaultPosition, wxDefaultSize,
|
|
Style( wxALIGN_LEFT ));
|
|
if( bCenter )
|
|
{
|
|
miProp=1;
|
|
UpdateSizersC();
|
|
}
|
|
else
|
|
UpdateSizers();
|
|
}
|
|
|
|
wxStaticText * ShuttleGuiBase::AddVariableText(const wxString &Str, bool bCenter, int PositionFlags)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxStaticText);
|
|
|
|
wxStaticText *pStatic;
|
|
mpWind = pStatic = new wxStaticText(mpParent, miId, Str, wxDefaultPosition, wxDefaultSize,
|
|
Style( wxALIGN_LEFT ));
|
|
if( bCenter )
|
|
{
|
|
miProp=1;
|
|
if( PositionFlags )
|
|
UpdateSizersCore( false, PositionFlags );
|
|
else
|
|
UpdateSizersC();
|
|
}
|
|
else
|
|
if( PositionFlags )
|
|
UpdateSizersCore( false, PositionFlags );
|
|
else
|
|
UpdateSizers();
|
|
return pStatic;
|
|
}
|
|
|
|
wxComboBox * ShuttleGuiBase::AddCombo( const wxString &Prompt, const wxString &Selected,const wxArrayString * pChoices )
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxComboBox);
|
|
wxComboBox * pCombo;
|
|
miProp=0;
|
|
|
|
int n = pChoices->GetCount();
|
|
if( n>50 ) n=50;
|
|
int i;
|
|
wxString Choices[50];
|
|
for(i=0;i<n;i++)
|
|
{
|
|
Choices[i] = (*pChoices)[i];
|
|
}
|
|
|
|
AddPrompt( Prompt );
|
|
|
|
mpWind = pCombo = new wxComboBox(mpParent, miId, Selected, wxDefaultPosition, wxDefaultSize,
|
|
n, Choices, Style( 0 ));
|
|
mpWind->SetName(wxStripMenuCodes(Prompt));
|
|
|
|
UpdateSizers();
|
|
return pCombo;
|
|
}
|
|
|
|
|
|
wxRadioButton * ShuttleGuiBase::AddRadioButton(const wxString &Prompt)
|
|
{
|
|
/// \todo This function and the next one, suitably adapted, could be
|
|
/// used by TieRadioButton.
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxRadioButton);
|
|
wxRadioButton * pRad;
|
|
mpWind = pRad = new wxRadioButton( mpParent, miId, Prompt,
|
|
wxDefaultPosition, wxDefaultSize, Style( wxRB_GROUP ) );
|
|
mpWind->SetName(wxStripMenuCodes(Prompt));
|
|
pRad->SetValue(true );
|
|
UpdateSizers();
|
|
return pRad;
|
|
}
|
|
|
|
wxRadioButton * ShuttleGuiBase::AddRadioButtonToGroup(const wxString &Prompt)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxRadioButton);
|
|
wxRadioButton * pRad;
|
|
mpWind = pRad = new wxRadioButton( mpParent, miId, Prompt,
|
|
wxDefaultPosition, wxDefaultSize, Style( 0 ) );
|
|
mpWind->SetName(wxStripMenuCodes(Prompt));
|
|
UpdateSizers();
|
|
return pRad;
|
|
}
|
|
|
|
wxSlider * ShuttleGuiBase::AddSlider(const wxString &Prompt, int pos, int Max, int Min)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxSlider);
|
|
AddPrompt( Prompt );
|
|
wxSlider * pSlider;
|
|
mpWind = pSlider = new wxSlider( mpParent, miId,
|
|
pos, Min, Max,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
Style( wxSL_HORIZONTAL | wxSL_LABELS | wxSL_AUTOTICKS )
|
|
);
|
|
mpWind->SetName(wxStripMenuCodes(Prompt));
|
|
miProp=1;
|
|
UpdateSizers();
|
|
return pSlider;
|
|
}
|
|
|
|
wxSpinCtrl * ShuttleGuiBase::AddSpinCtrl(const wxString &Prompt, int Value, int Max, int Min)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxSpinCtrl);
|
|
AddPrompt( Prompt );
|
|
wxSpinCtrl * pSpinCtrl;
|
|
mpWind = pSpinCtrl = new wxSpinCtrl( mpParent, miId,
|
|
wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
Style( wxSP_VERTICAL | wxSP_ARROW_KEYS ),
|
|
Min, Max, Value
|
|
);
|
|
mpWind->SetName(wxStripMenuCodes(Prompt));
|
|
miProp=1;
|
|
UpdateSizers();
|
|
return pSpinCtrl;
|
|
}
|
|
|
|
|
|
wxTextCtrl * ShuttleGuiBase::AddTextBox(const wxString &Caption, const wxString &Value, const int nChars)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxTextCtrl);
|
|
wxTextCtrl * pTextCtrl;
|
|
wxSize Size(wxDefaultSize);
|
|
if( nChars > 0 )
|
|
{
|
|
Size.SetWidth( nChars *5 );
|
|
}
|
|
AddPrompt( Caption );
|
|
miProp=0;
|
|
|
|
#ifdef RIGHT_ALIGNED_TEXTBOXES
|
|
long flags = wxTE_RIGHT;
|
|
#else
|
|
long flags = wxTE_LEFT;
|
|
#endif
|
|
|
|
mpWind = pTextCtrl = new wxTextCtrl(mpParent, miId, Value,
|
|
wxDefaultPosition, Size, Style( flags ));
|
|
mpWind->SetName(wxStripMenuCodes(Caption));
|
|
UpdateSizers();
|
|
return pTextCtrl;
|
|
}
|
|
|
|
wxTextCtrl * ShuttleGuiBase::AddNumericTextBox(const wxString &Caption, const wxString &Value, const int nChars)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxTextCtrl);
|
|
wxTextCtrl * pTextCtrl;
|
|
wxSize Size(wxDefaultSize);
|
|
if( nChars > 0 )
|
|
{
|
|
Size.SetWidth( nChars *5 );
|
|
}
|
|
AddPrompt( Caption );
|
|
miProp=0;
|
|
|
|
#ifdef RIGHT_ALIGNED_TEXTBOXES
|
|
long flags = wxTE_RIGHT;
|
|
#else
|
|
long flags = wxTE_LEFT;
|
|
#endif
|
|
|
|
wxTextValidator Validator(wxFILTER_NUMERIC);
|
|
mpWind = pTextCtrl = new wxTextCtrl(mpParent, miId, Value,
|
|
wxDefaultPosition, Size, Style( flags ),
|
|
Validator // It's OK to pass this. It will be cloned.
|
|
);
|
|
mpWind->SetName(wxStripMenuCodes(Caption));
|
|
UpdateSizers();
|
|
return pTextCtrl;
|
|
}
|
|
|
|
/// Multiline text box that grows.
|
|
wxTextCtrl * ShuttleGuiBase::AddTextWindow(const wxString &Value)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxTextCtrl);
|
|
wxTextCtrl * pTextCtrl;
|
|
SetProportions( 1 );
|
|
mpWind = pTextCtrl = new wxTextCtrl(mpParent, miId, Value,
|
|
wxDefaultPosition, wxDefaultSize, Style( wxTE_MULTILINE ));
|
|
UpdateSizers();
|
|
// Start off at start of window...
|
|
pTextCtrl->SetInsertionPoint( 0 );
|
|
pTextCtrl->ShowPosition( 0 );
|
|
return pTextCtrl;
|
|
}
|
|
|
|
/// Single line text box of fixed size.
|
|
void ShuttleGuiBase::AddConstTextBox(const wxString &Prompt, const wxString &Value)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wx);
|
|
miProp=0;
|
|
AddPrompt( Prompt );
|
|
UpdateSizers();
|
|
miProp=0;
|
|
mpWind = new wxStaticText(mpParent, miId, Value, wxDefaultPosition, wxDefaultSize,
|
|
Style( 0 ));
|
|
UpdateSizers();
|
|
}
|
|
|
|
wxListBox * ShuttleGuiBase::AddListBox(const wxArrayString * pChoices, long style)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxListBox);
|
|
wxListBox * pListBox;
|
|
SetProportions( 1 );
|
|
mpWind = pListBox = new wxListBox(mpParent, miId,
|
|
wxDefaultPosition, wxDefaultSize,*pChoices, style);
|
|
pListBox->SetMinSize( wxSize( 120,150 ));
|
|
UpdateSizers();
|
|
return pListBox;
|
|
}
|
|
|
|
|
|
wxListCtrl * ShuttleGuiBase::AddListControl()
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxListCtrl);
|
|
wxListCtrl * pListCtrl;
|
|
SetProportions( 1 );
|
|
mpWind = pListCtrl = new wxListCtrl(mpParent, miId,
|
|
wxDefaultPosition, wxDefaultSize, Style( wxLC_ICON ));
|
|
pListCtrl->SetMinSize( wxSize( 120,150 ));
|
|
UpdateSizers();
|
|
return pListCtrl;
|
|
}
|
|
|
|
wxGrid * ShuttleGuiBase::AddGrid()
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxGrid);
|
|
wxGrid * pGrid;
|
|
SetProportions( 1 );
|
|
mpWind = pGrid = new wxGrid(mpParent, miId, wxDefaultPosition,
|
|
wxDefaultSize, Style( wxWANTS_CHARS ));
|
|
pGrid->SetMinSize( wxSize( 120, 150 ));
|
|
UpdateSizers();
|
|
return pGrid;
|
|
}
|
|
|
|
wxListCtrl * ShuttleGuiBase::AddListControlReportMode()
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxListCtrl);
|
|
wxListCtrl * pListCtrl;
|
|
SetProportions( 1 );
|
|
mpWind = pListCtrl = new wxListCtrl(mpParent, miId,
|
|
wxDefaultPosition, wxSize(230,120),//wxDefaultSize,
|
|
Style( wxLC_REPORT | wxLC_HRULES | wxLC_VRULES | wxSUNKEN_BORDER ));
|
|
// pListCtrl->SetMinSize( wxSize( 120,150 ));
|
|
UpdateSizers();
|
|
return pListCtrl;
|
|
}
|
|
|
|
wxTreeCtrl * ShuttleGuiBase::AddTree()
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxTreeCtrl);
|
|
wxTreeCtrl * pTreeCtrl;
|
|
SetProportions( 1 );
|
|
mpWind = pTreeCtrl = new wxTreeCtrl(mpParent, miId, wxDefaultPosition, wxDefaultSize,
|
|
Style( wxTR_HAS_BUTTONS ));
|
|
pTreeCtrl->SetMinSize( wxSize( 120,650 ));
|
|
UpdateSizers();
|
|
return pTreeCtrl;
|
|
}
|
|
|
|
void ShuttleGuiBase::AddIcon(wxBitmap *pBmp)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wx);
|
|
return;
|
|
wxBitmapButton * pBtn;
|
|
mpWind = pBtn = new wxBitmapButton( mpParent, miId, *pBmp,
|
|
wxDefaultPosition, wxDefaultSize, Style( wxBU_AUTODRAW ) );
|
|
pBtn->SetWindowStyle( 0 );
|
|
UpdateSizersC();
|
|
}
|
|
|
|
ShuttleGuiBase & ShuttleGuiBase::Prop( int iProp )
|
|
{
|
|
miPropSetByUser = iProp;
|
|
return *this;
|
|
}
|
|
|
|
wxMenuBar * ShuttleGuiBase::AddMenuBar( )
|
|
{
|
|
mpMenuBar = new wxMenuBar( );
|
|
|
|
wxFrame * pFrame = (wxFrame*)mpParent;
|
|
pFrame->SetThemeEnabled( true );
|
|
mpMenuBar->SetThemeEnabled( true );
|
|
pFrame->SetMenuBar(mpMenuBar);
|
|
|
|
return mpMenuBar;
|
|
}
|
|
|
|
wxMenu * ShuttleGuiBase::AddMenu( const wxString & Title )
|
|
{
|
|
mpMenu = new wxMenu;
|
|
mpMenuBar->Append( mpMenu, Title );
|
|
return mpMenu;
|
|
}
|
|
|
|
|
|
|
|
/// Starts a static box around a number of controls.
|
|
/// @param Str The text of the title for the box.
|
|
/// @param iProp The resizing proportion value.
|
|
/// Use iProp == 0 for a minimum sized static box.
|
|
/// Use iProp == 1 for a box that grows if there is space to spare.
|
|
wxStaticBox * ShuttleGuiBase::StartStatic(const wxString &Str, int iProp)
|
|
{
|
|
UseUpId();
|
|
mBoxName = Str;
|
|
if( mShuttleMode != eIsCreating )
|
|
return NULL;
|
|
wxStaticBox * pBox = new wxStaticBox(mpParent, miId,
|
|
Str );
|
|
pBox->SetLabel( Str );
|
|
pBox->SetName( Str );
|
|
mpSubSizer = new wxStaticBoxSizer(
|
|
pBox,
|
|
wxVERTICAL );
|
|
miSizerProp = iProp;
|
|
UpdateSizers();
|
|
return pBox;
|
|
}
|
|
|
|
void ShuttleGuiBase::EndStatic()
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
PopSizer();
|
|
}
|
|
|
|
/// This allows subsequent controls and static boxes to be in
|
|
/// a scrolled panel. Very handy if you are running out of space
|
|
/// on a dialog.
|
|
///
|
|
/// The iStyle parameter is used in some very hacky code that
|
|
/// dynamically repopulates a dialog. It also controls the
|
|
/// background colour. Look at the code for details.
|
|
/// @param istyle deprecated parameter, but has been used for hacking.
|
|
wxScrolledWindow * ShuttleGuiBase::StartScroller(int iStyle)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxScrolledWindow);
|
|
|
|
wxScrolledWindow * pScroller;
|
|
mpWind = pScroller = new wxScrolledWindow( mpParent, miId, wxDefaultPosition, wxDefaultSize,
|
|
Style( wxSUNKEN_BORDER ) );
|
|
pScroller->SetScrollRate( 20,20 );
|
|
|
|
mpWind->SetBackgroundColour(
|
|
iStyle==0
|
|
? wxColour( 245,244,240) :
|
|
wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)
|
|
);
|
|
SetProportions( 1 );
|
|
if( iStyle==2 )
|
|
{
|
|
UpdateSizersAtStart();
|
|
}
|
|
else
|
|
{
|
|
UpdateSizers(); // adds window in to current sizer.
|
|
}
|
|
|
|
// create a sizer within the window...
|
|
mpParent = pScroller;
|
|
mpSizer = new wxBoxSizer( wxVERTICAL );
|
|
pScroller->SetSizer( mpSizer );
|
|
PushSizer();
|
|
return pScroller;
|
|
}
|
|
|
|
void ShuttleGuiBase::EndScroller()
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
wxSize ScrollSize = mpSizer->GetMinSize();
|
|
int yMin = ScrollSize.y+4;
|
|
int xMin = ScrollSize.x+4;
|
|
if( yMin > 400)
|
|
{
|
|
yMin = 400;
|
|
xMin+=50;// extra space for vertical scrollbar.
|
|
}
|
|
|
|
mpParent->SetMinSize( wxSize(xMin, yMin) );
|
|
|
|
PopSizer();
|
|
mpParent = mpParent->GetParent();
|
|
}
|
|
|
|
wxPanel * ShuttleGuiBase::StartPanel(int iStyle)
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxPanel);
|
|
wxPanel * pPanel;
|
|
mpWind = pPanel = new wxPanel( mpParent, miId, wxDefaultPosition, wxDefaultSize,
|
|
Style( wxNO_BORDER ));
|
|
|
|
if( iStyle != 0 )
|
|
{
|
|
mpWind->SetBackgroundColour(
|
|
iStyle==1
|
|
? wxColour( 190,200,230) :
|
|
wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)
|
|
);
|
|
}
|
|
SetProportions(0);
|
|
miBorder=2;
|
|
UpdateSizers(); // adds window in to current sizer.
|
|
|
|
// create a sizer within the window...
|
|
mpParent = pPanel;
|
|
mpSizer = new wxBoxSizer( wxVERTICAL );
|
|
pPanel->SetSizer( mpSizer );
|
|
PushSizer();
|
|
return pPanel;
|
|
}
|
|
|
|
void ShuttleGuiBase::EndPanel()
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
PopSizer();
|
|
mpParent = mpParent->GetParent();
|
|
}
|
|
|
|
wxNotebook * ShuttleGuiBase::StartNotebook()
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxNotebook);
|
|
wxNotebook * pNotebook;
|
|
mpWind = pNotebook = new wxNotebook(mpParent,
|
|
miId, wxDefaultPosition, wxDefaultSize, Style( 0 ));
|
|
SetProportions( 1 );
|
|
UpdateSizers();
|
|
mpParent = pNotebook;
|
|
return pNotebook;
|
|
}
|
|
|
|
void ShuttleGuiBase::EndNotebook()
|
|
{
|
|
//PopSizer();
|
|
mpParent = mpParent->GetParent();
|
|
}
|
|
|
|
|
|
wxNotebookPage * ShuttleGuiBase::StartNotebookPage( const wxString Name )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return NULL;
|
|
// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wx);
|
|
wxNotebook * pNotebook = (wxNotebook*)mpParent;
|
|
wxNotebookPage * pPage = new wxPanel(mpParent );
|
|
pPage->SetName(Name);
|
|
|
|
pNotebook->AddPage(
|
|
pPage,
|
|
Name);
|
|
PushSizer();
|
|
|
|
SetProportions( 1 );
|
|
mpParent = pPage;
|
|
mpSizer = new wxBoxSizer( wxVERTICAL );
|
|
mpSizer->SetMinSize(250,500);
|
|
pPage->SetSizer( mpSizer );
|
|
// UpdateSizers();
|
|
return pPage;
|
|
}
|
|
|
|
void ShuttleGuiBase::StartNotebookPage( const wxString Name, wxNotebookPage * pPage )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wx);
|
|
wxNotebook * pNotebook = (wxNotebook*)mpParent;
|
|
// wxNotebookPage * pPage = new wxPanel(mpParent );
|
|
pPage->Create( mpParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, wxT("panel"));
|
|
pPage->SetName(Name);
|
|
|
|
pNotebook->AddPage(
|
|
pPage,
|
|
Name);
|
|
PushSizer();
|
|
|
|
SetProportions( 1 );
|
|
mpParent = pPage;
|
|
mpSizer = new wxBoxSizer( wxVERTICAL );
|
|
mpSizer->SetMinSize(250,500);
|
|
pPage->SetSizer( mpSizer );
|
|
// UpdateSizers();
|
|
}
|
|
|
|
void ShuttleGuiBase::EndNotebookPage()
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
PopSizer();
|
|
mpParent = mpParent->GetParent();
|
|
}
|
|
|
|
// Doxygen description is at the start of the file
|
|
// this is a wxPanel with erase background disabled.
|
|
class InvisiblePanel : public wxPanel
|
|
{
|
|
public:
|
|
InvisiblePanel(
|
|
wxWindow* parent,
|
|
wxWindowID id = -1,
|
|
const wxPoint& pos = wxDefaultPosition,
|
|
const wxSize& size = wxDefaultSize,
|
|
long style = wxTAB_TRAVERSAL ) :
|
|
wxPanel( parent, id, pos, size, style )
|
|
{
|
|
};
|
|
~InvisiblePanel(){;};
|
|
void OnPaint( wxPaintEvent &event );
|
|
void OnErase(wxEraseEvent &/*evt*/){;};
|
|
DECLARE_EVENT_TABLE()
|
|
};
|
|
|
|
|
|
BEGIN_EVENT_TABLE(InvisiblePanel, wxPanel)
|
|
// EVT_PAINT(InvisiblePanel::OnPaint)
|
|
EVT_ERASE_BACKGROUND( InvisiblePanel::OnErase)
|
|
END_EVENT_TABLE()
|
|
|
|
void InvisiblePanel::OnPaint( wxPaintEvent &event )
|
|
{
|
|
// Don't repaint my background...
|
|
wxPaintDC dc(this);
|
|
// event.Skip();
|
|
;// swallow the paint event.
|
|
}
|
|
|
|
wxPanel * ShuttleGuiBase::StartInvisiblePanel()
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxPanel);
|
|
wxPanel * pPanel;
|
|
mpWind = pPanel = new wxPanel( mpParent, miId, wxDefaultPosition, wxDefaultSize,
|
|
wxNO_BORDER);
|
|
|
|
mpWind->SetBackgroundColour(
|
|
wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)
|
|
);
|
|
SetProportions( 1 );
|
|
miBorder=0;
|
|
UpdateSizers(); // adds window in to current sizer.
|
|
|
|
// create a sizer within the window...
|
|
mpParent = pPanel;
|
|
mpSizer = new wxBoxSizer( wxVERTICAL );
|
|
pPanel->SetSizer( mpSizer );
|
|
PushSizer();
|
|
return pPanel;
|
|
}
|
|
|
|
void ShuttleGuiBase::EndInvisiblePanel()
|
|
{
|
|
EndPanel();
|
|
}
|
|
|
|
|
|
/// Starts a Horizontal Layout.
|
|
/// - Use wxEXPAND and 0 to expand horizontally but not vertically.
|
|
/// - Use wxEXPAND and 1 to expand horizontally and vertically.
|
|
/// - Use wxCENTRE and 1 for no expansion.
|
|
/// @param PositionFlag Typically wxEXPAND or wxCENTRE.
|
|
/// @param iProp Proportionality for resizing.
|
|
void ShuttleGuiBase::StartHorizontalLay( int PositionFlags, int iProp)
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
miSizerProp=iProp;
|
|
mpSubSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
UpdateSizersCore( false, PositionFlags | wxALL );
|
|
}
|
|
|
|
void ShuttleGuiBase::EndHorizontalLay()
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
PopSizer();
|
|
}
|
|
|
|
void ShuttleGuiBase::StartVerticalLay(int iProp)
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
miSizerProp=iProp;
|
|
mpSubSizer = new wxBoxSizer( wxVERTICAL );
|
|
UpdateSizers();
|
|
}
|
|
|
|
void ShuttleGuiBase::EndVerticalLay()
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
PopSizer();
|
|
}
|
|
|
|
void ShuttleGuiBase::StartMultiColumn(int nCols, int PositionFlags)
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
mpSubSizer = new wxFlexGridSizer( nCols );
|
|
UpdateSizersCore( false, PositionFlags | wxALL );
|
|
}
|
|
|
|
void ShuttleGuiBase::EndMultiColumn()
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
PopSizer();
|
|
}
|
|
|
|
/// When we're exchanging with the configured shuttle rather than with the GUI
|
|
/// We use this function.
|
|
void ShuttleGuiBase::DoDataShuttle( const wxString &Name, WrappedType & WrappedRef )
|
|
{
|
|
wxASSERT( mpShuttle );
|
|
mpShuttle->TransferWrappedType( Name, WrappedRef );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------//
|
|
|
|
// We now have a group of tie functions which are generic in the type
|
|
// they bind to (i.e. WrappedType).
|
|
// The type specific versions are much shorter and are later
|
|
// in this file.
|
|
wxCheckBox * ShuttleGuiBase::TieCheckBox(const wxString &Prompt, WrappedType & WrappedRef)
|
|
{
|
|
// The Add function does a UseUpId(), so don't do it here in that case.
|
|
if( mShuttleMode == eIsCreating )
|
|
return AddCheckBox( Prompt, WrappedRef.ReadAsString());
|
|
|
|
UseUpId();
|
|
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
wxCheckBox * pCheckBox = wxDynamicCast(pWnd, wxCheckBox);
|
|
|
|
switch( mShuttleMode )
|
|
{
|
|
// IF setting internal storage from the controls.
|
|
case eIsGettingFromDialog:
|
|
{
|
|
wxASSERT( pCheckBox );
|
|
WrappedRef.WriteToAsBool( pCheckBox->GetValue() );
|
|
}
|
|
break;
|
|
case eIsSettingToDialog:
|
|
{
|
|
wxASSERT( pCheckBox );
|
|
pCheckBox->SetValue( WrappedRef.ReadAsBool() );
|
|
}
|
|
break;
|
|
// IF Saving settings to external storage...
|
|
// or IF Getting settings from external storage.
|
|
case eIsSavingViaShuttle:
|
|
case eIsGettingViaShuttle:
|
|
DoDataShuttle( Prompt, WrappedRef );
|
|
break;
|
|
default:
|
|
wxASSERT( false );
|
|
break;
|
|
}
|
|
return pCheckBox;
|
|
}
|
|
|
|
wxCheckBox * ShuttleGuiBase::TieCheckBoxOnRight(const wxString &Prompt, WrappedType & WrappedRef)
|
|
{
|
|
// The Add function does a UseUpId(), so don't do it here in that case.
|
|
if( mShuttleMode == eIsCreating )
|
|
return AddCheckBoxOnRight( Prompt, WrappedRef.ReadAsString());
|
|
|
|
UseUpId();
|
|
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
wxCheckBox * pCheckBox = wxDynamicCast(pWnd, wxCheckBox);
|
|
|
|
switch( mShuttleMode )
|
|
{
|
|
// IF setting internal storage from the controls.
|
|
case eIsGettingFromDialog:
|
|
{
|
|
wxASSERT( pCheckBox );
|
|
WrappedRef.WriteToAsBool( pCheckBox->GetValue() );
|
|
}
|
|
break;
|
|
case eIsSettingToDialog:
|
|
{
|
|
wxASSERT( pCheckBox );
|
|
pCheckBox->SetValue( WrappedRef.ReadAsBool() );
|
|
}
|
|
break;
|
|
// IF Saving settings to external storage...
|
|
// or IF Getting settings from external storage.
|
|
case eIsSavingViaShuttle:
|
|
case eIsGettingViaShuttle:
|
|
DoDataShuttle( Prompt, WrappedRef );
|
|
break;
|
|
default:
|
|
wxASSERT( false );
|
|
break;
|
|
}
|
|
return pCheckBox;
|
|
}
|
|
|
|
wxSpinCtrl * ShuttleGuiBase::TieSpinCtrl( const wxString &Prompt, WrappedType & WrappedRef, const int max, const int min )
|
|
{
|
|
// The Add function does a UseUpId(), so don't do it here in that case.
|
|
if( mShuttleMode == eIsCreating )
|
|
return AddSpinCtrl( Prompt, WrappedRef.ReadAsInt(), max, min );
|
|
|
|
UseUpId();
|
|
wxSpinCtrl * pSpinCtrl=NULL;
|
|
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
pSpinCtrl = wxDynamicCast(pWnd, wxSpinCtrl);
|
|
|
|
switch( mShuttleMode )
|
|
{
|
|
// IF setting internal storage from the controls.
|
|
case eIsGettingFromDialog:
|
|
{
|
|
wxASSERT( pSpinCtrl );
|
|
WrappedRef.WriteToAsInt( pSpinCtrl->GetValue() );
|
|
}
|
|
break;
|
|
case eIsSettingToDialog:
|
|
{
|
|
wxASSERT( pSpinCtrl );
|
|
pSpinCtrl->SetValue( WrappedRef.ReadAsInt() );
|
|
}
|
|
break;
|
|
// IF Saving settings to external storage...
|
|
// or IF Getting settings from external storage.
|
|
case eIsGettingViaShuttle:
|
|
case eIsSavingViaShuttle:
|
|
DoDataShuttle( Prompt, WrappedRef );
|
|
break;
|
|
default:
|
|
wxASSERT( false );
|
|
break;
|
|
}
|
|
return pSpinCtrl;
|
|
}
|
|
|
|
wxTextCtrl * ShuttleGuiBase::TieTextBox( const wxString &Prompt, WrappedType & WrappedRef, const int nChars)
|
|
{
|
|
// The Add function does a UseUpId(), so don't do it here in that case.
|
|
if( mShuttleMode == eIsCreating )
|
|
return AddTextBox( Prompt, WrappedRef.ReadAsString(), nChars );
|
|
|
|
UseUpId();
|
|
wxTextCtrl * pTextBox=NULL;
|
|
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
pTextBox = wxDynamicCast(pWnd, wxTextCtrl);
|
|
|
|
switch( mShuttleMode )
|
|
{
|
|
// IF setting internal storage from the controls.
|
|
case eIsGettingFromDialog:
|
|
{
|
|
wxASSERT( pTextBox );
|
|
WrappedRef.WriteToAsString( pTextBox->GetValue() );
|
|
}
|
|
break;
|
|
case eIsSettingToDialog:
|
|
{
|
|
wxASSERT( pTextBox );
|
|
pTextBox->SetValue( WrappedRef.ReadAsString() );
|
|
}
|
|
break;
|
|
// IF Saving settings to external storage...
|
|
// or IF Getting settings from external storage.
|
|
case eIsGettingViaShuttle:
|
|
case eIsSavingViaShuttle:
|
|
DoDataShuttle( Prompt, WrappedRef );
|
|
break;
|
|
default:
|
|
wxASSERT( false );
|
|
break;
|
|
}
|
|
return pTextBox;
|
|
}
|
|
|
|
wxTextCtrl * ShuttleGuiBase::TieNumericTextBox( const wxString &Prompt, WrappedType & WrappedRef, const int nChars)
|
|
{
|
|
// The Add function does a UseUpId(), so don't do it here in that case.
|
|
if( mShuttleMode == eIsCreating )
|
|
return AddNumericTextBox( Prompt, WrappedRef.ReadAsString(), nChars );
|
|
|
|
UseUpId();
|
|
wxTextCtrl * pTextBox=NULL;
|
|
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
pTextBox = wxDynamicCast(pWnd, wxTextCtrl);
|
|
|
|
switch( mShuttleMode )
|
|
{
|
|
// IF setting internal storage from the controls.
|
|
case eIsGettingFromDialog:
|
|
{
|
|
wxASSERT( pTextBox );
|
|
WrappedRef.WriteToAsString( pTextBox->GetValue() );
|
|
}
|
|
break;
|
|
case eIsSettingToDialog:
|
|
{
|
|
wxASSERT( pTextBox );
|
|
pTextBox->SetValue( WrappedRef.ReadAsString() );
|
|
}
|
|
break;
|
|
// IF Saving settings to external storage...
|
|
// or IF Getting settings from external storage.
|
|
case eIsGettingViaShuttle:
|
|
case eIsSavingViaShuttle:
|
|
DoDataShuttle( Prompt, WrappedRef );
|
|
break;
|
|
default:
|
|
wxASSERT( false );
|
|
break;
|
|
}
|
|
return pTextBox;
|
|
}
|
|
|
|
wxSlider * ShuttleGuiBase::TieSlider( const wxString &Prompt, WrappedType & WrappedRef, const int max, int min )
|
|
{
|
|
// The Add function does a UseUpId(), so don't do it here in that case.
|
|
if( mShuttleMode != eIsCreating )
|
|
UseUpId();
|
|
wxSlider * pSlider=NULL;
|
|
switch( mShuttleMode )
|
|
{
|
|
case eIsCreating:
|
|
{
|
|
pSlider = AddSlider( Prompt, WrappedRef.ReadAsInt(), max, min );
|
|
}
|
|
break;
|
|
// IF setting internal storage from the controls.
|
|
case eIsGettingFromDialog:
|
|
{
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
pSlider = wxDynamicCast(pWnd, wxSlider);
|
|
wxASSERT( pSlider );
|
|
WrappedRef.WriteToAsInt( pSlider->GetValue() );
|
|
}
|
|
break;
|
|
case eIsSettingToDialog:
|
|
{
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
pSlider = wxDynamicCast(pWnd, wxSlider);
|
|
wxASSERT( pSlider );
|
|
pSlider->SetValue( WrappedRef.ReadAsInt() );
|
|
}
|
|
break;
|
|
// IF Saving settings to external storage...
|
|
// or IF Getting settings from external storage.
|
|
case eIsSavingViaShuttle:
|
|
case eIsGettingViaShuttle:
|
|
DoDataShuttle( Prompt, WrappedRef );
|
|
break;
|
|
default:
|
|
wxASSERT( false );
|
|
break;
|
|
}
|
|
return pSlider;
|
|
}
|
|
|
|
|
|
wxChoice * ShuttleGuiBase::TieChoice(
|
|
const wxString &Prompt,
|
|
WrappedType &WrappedRef,
|
|
const wxArrayString * pChoices )
|
|
{
|
|
// The Add function does a UseUpId(), so don't do it here in that case.
|
|
if( mShuttleMode != eIsCreating )
|
|
UseUpId();
|
|
wxChoice * pChoice=NULL;
|
|
switch( mShuttleMode )
|
|
{
|
|
case eIsCreating:
|
|
{
|
|
if( WrappedRef.IsString() )
|
|
pChoice = AddChoice( Prompt, WrappedRef.ReadAsString(), pChoices );
|
|
else
|
|
{
|
|
wxString Temp;
|
|
if( pChoices && ( WrappedRef.ReadAsInt() < (int)pChoices->GetCount() ) )
|
|
{
|
|
Temp = (*pChoices)[WrappedRef.ReadAsInt()];
|
|
}
|
|
pChoice = AddChoice( Prompt, Temp, pChoices );
|
|
}
|
|
}
|
|
break;
|
|
// IF setting internal storage from the controls.
|
|
case eIsGettingFromDialog:
|
|
{
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
pChoice = wxDynamicCast(pWnd, wxChoice);
|
|
wxASSERT( pChoice );
|
|
if( WrappedRef.IsString())
|
|
WrappedRef.WriteToAsString( pChoice->GetStringSelection());
|
|
else
|
|
WrappedRef.WriteToAsInt( pChoice->GetSelection() );
|
|
}
|
|
break;
|
|
case eIsSettingToDialog:
|
|
{
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
pChoice = wxDynamicCast(pWnd, wxChoice);
|
|
wxASSERT( pChoice );
|
|
if( WrappedRef.IsString() )
|
|
pChoice->SetStringSelection( WrappedRef.ReadAsString() );
|
|
else
|
|
pChoice->SetSelection( WrappedRef.ReadAsInt() );
|
|
}
|
|
break;
|
|
// IF Saving settings to external storage...
|
|
// or IF Getting settings from external storage.
|
|
case eIsSavingViaShuttle:
|
|
case eIsGettingViaShuttle:
|
|
DoDataShuttle( Prompt, WrappedRef );
|
|
break;
|
|
default:
|
|
wxASSERT( false );
|
|
break;
|
|
}
|
|
return pChoice;
|
|
}
|
|
|
|
wxRadioButton * ShuttleGuiBase::TieRadioButton(const wxString &Prompt, WrappedType & WrappedRef)
|
|
{
|
|
wxASSERT( mRadioCount >= 0); // Did you remember to use StartRadioButtonGroup() ?
|
|
mRadioCount++;
|
|
UseUpId();
|
|
wxRadioButton * pRadioButton = NULL;
|
|
|
|
switch( mShuttleMode )
|
|
{
|
|
case eIsCreating:
|
|
{
|
|
mpWind = pRadioButton = new wxRadioButton( mpParent, miId, Prompt,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
(mRadioCount==1)?wxRB_GROUP:0);
|
|
pRadioButton->SetValue(WrappedRef.ValuesMatch( mRadioValue ));
|
|
pRadioButton->SetName(wxStripMenuCodes(Prompt));
|
|
UpdateSizers();
|
|
}
|
|
break;
|
|
case eIsGettingFromDialog:
|
|
{
|
|
wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
|
|
pRadioButton = wxDynamicCast(pWnd, wxRadioButton);
|
|
wxASSERT( pRadioButton );
|
|
if( pRadioButton->GetValue() )
|
|
{
|
|
mRadioValue.WriteToAsWrappedType( WrappedRef );
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
wxASSERT( false );
|
|
break;
|
|
}
|
|
return pRadioButton;
|
|
}
|
|
|
|
/// Call this before any TieRadioButton calls.
|
|
/// This is the generic version and requires mRadioValue already initialised.
|
|
/// Versions for specific types must do that initialisation.
|
|
void ShuttleGuiBase::StartRadioButtonGroup( const wxString & SettingName )
|
|
{
|
|
wxASSERT( mRadioValue.eWrappedType != eWrappedNotSet );
|
|
mSettingName = SettingName;
|
|
mRadioCount = 0;
|
|
if( mShuttleMode == eIsCreating )
|
|
DoDataShuttle( SettingName, mRadioValue );
|
|
}
|
|
|
|
/// Call this after any TieRadioButton calls.
|
|
/// It's generic too. We don't need type-specific ones.
|
|
void ShuttleGuiBase::EndRadioButtonGroup()
|
|
{
|
|
if( mShuttleMode == eIsGettingFromDialog )
|
|
DoDataShuttle( mSettingName, mRadioValue );
|
|
mRadioValue.Init();// Clear it out...
|
|
mSettingName = wxT("");
|
|
mRadioCount = -1; // So we detect a problem.
|
|
}
|
|
|
|
//-----------------------------------------------------------------------//
|
|
//-- Now we are into type specific Tie() functions.
|
|
//-- These are all 'one-step' tie functions.
|
|
|
|
wxCheckBox * ShuttleGuiBase::TieCheckBox(const wxString &Prompt, bool &Var)
|
|
{
|
|
WrappedType WrappedRef( Var );
|
|
return TieCheckBox( Prompt, WrappedRef );
|
|
}
|
|
|
|
// See comment in AddCheckBoxOnRight() for why we have this variant.
|
|
wxCheckBox * ShuttleGuiBase::TieCheckBoxOnRight(const wxString &Prompt, bool &Var)
|
|
{
|
|
// Only odes anything different if it's creating.
|
|
WrappedType WrappedRef( Var );
|
|
if( mShuttleMode == eIsCreating )
|
|
return AddCheckBoxOnRight( Prompt, WrappedRef.ReadAsString() );
|
|
return TieCheckBox( Prompt, WrappedRef );
|
|
}
|
|
|
|
wxSpinCtrl * ShuttleGuiBase::TieSpinCtrl( const wxString &Prompt, int &Value, const int max, const int min )
|
|
{
|
|
WrappedType WrappedRef(Value);
|
|
return TieSpinCtrl( Prompt, WrappedRef, max, min );
|
|
}
|
|
|
|
wxTextCtrl * ShuttleGuiBase::TieTextBox( const wxString &Prompt, wxString &Selected, const int nChars)
|
|
{
|
|
WrappedType WrappedRef(Selected);
|
|
return TieTextBox( Prompt, WrappedRef, nChars );
|
|
}
|
|
|
|
wxTextCtrl * ShuttleGuiBase::TieTextBox( const wxString &Prompt, int &Selected, const int nChars)
|
|
{
|
|
WrappedType WrappedRef( Selected );
|
|
return TieTextBox( Prompt, WrappedRef, nChars );
|
|
}
|
|
|
|
wxTextCtrl * ShuttleGuiBase::TieTextBox( const wxString &Prompt, double &Value, const int nChars)
|
|
{
|
|
WrappedType WrappedRef( Value );
|
|
return TieTextBox( Prompt, WrappedRef, nChars );
|
|
}
|
|
|
|
wxTextCtrl * ShuttleGuiBase::TieNumericTextBox( const wxString &Prompt, wxString &Selected, const int nChars)
|
|
{
|
|
WrappedType WrappedRef(Selected);
|
|
return TieNumericTextBox( Prompt, WrappedRef, nChars );
|
|
}
|
|
|
|
wxTextCtrl * ShuttleGuiBase::TieNumericTextBox( const wxString &Prompt, int &Selected, const int nChars)
|
|
{
|
|
WrappedType WrappedRef( Selected );
|
|
return TieNumericTextBox( Prompt, WrappedRef, nChars );
|
|
}
|
|
|
|
wxTextCtrl * ShuttleGuiBase::TieNumericTextBox( const wxString &Prompt, double &Value, const int nChars)
|
|
{
|
|
WrappedType WrappedRef( Value );
|
|
return TieNumericTextBox( Prompt, WrappedRef, nChars );
|
|
}
|
|
|
|
wxSlider * ShuttleGuiBase::TieSlider( const wxString &Prompt, int &pos, const int max, const int min )
|
|
{
|
|
WrappedType WrappedRef( pos );
|
|
return TieSlider( Prompt, WrappedRef, max, min );
|
|
}
|
|
|
|
wxSlider * ShuttleGuiBase::TieSlider( const wxString &Prompt, float &pos, const float fMin, const float fMax)
|
|
{
|
|
const float RoundFix=0.0000001f;
|
|
int iVal=(pos-fMin+RoundFix)*100.0/(fMax-fMin);
|
|
wxSlider * pWnd = TieSlider( Prompt, iVal, 100 );
|
|
pos = iVal*(fMax-fMin)*0.01+fMin;
|
|
return pWnd;
|
|
}
|
|
|
|
wxSlider * ShuttleGuiBase::TieVSlider( const wxString &Prompt, float &pos, const float fMin, const float fMax)
|
|
{
|
|
int iVal=(pos-fMin)*100.0/(fMax-fMin);
|
|
// if( mShuttleMode == eIsCreating )
|
|
// {
|
|
// return AddVSlider( Prompt, iVal, 100 );
|
|
// }
|
|
wxSlider * pWnd = TieSlider( Prompt, iVal, 100 );
|
|
pos = iVal*(fMax-fMin)*0.01+fMin;
|
|
return pWnd;
|
|
}
|
|
|
|
wxChoice * ShuttleGuiBase::TieChoice(
|
|
const wxString &Prompt,
|
|
wxString &Selected,
|
|
const wxArrayString * pChoices )
|
|
{
|
|
WrappedType WrappedRef( Selected );
|
|
return TieChoice( Prompt, WrappedRef, pChoices );
|
|
}
|
|
|
|
wxChoice * ShuttleGuiBase::TieChoice(
|
|
const wxString &Prompt,
|
|
int &Selected,
|
|
const wxArrayString * pChoices )
|
|
{
|
|
WrappedType WrappedRef( Selected );
|
|
return TieChoice( Prompt, WrappedRef, pChoices );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------//
|
|
|
|
// ShuttleGui utility functions to look things up in a list.
|
|
// If not present, we use the configured default index value.
|
|
|
|
//-----------------------------------------------------------------------//
|
|
|
|
/// String-to-Index
|
|
int ShuttleGuiBase::TranslateToIndex( const wxString &Value, const wxArrayString &Choices )
|
|
{
|
|
int n = Choices.Index( Value );
|
|
if( n== wxNOT_FOUND )
|
|
n=miNoMatchSelector;
|
|
miNoMatchSelector = 0;
|
|
return n;
|
|
}
|
|
|
|
/// Index-to-String
|
|
wxString ShuttleGuiBase::TranslateFromIndex( const int nIn, const wxArrayString &Choices )
|
|
{
|
|
int n = nIn;
|
|
if( n== wxNOT_FOUND )
|
|
n=miNoMatchSelector;
|
|
miNoMatchSelector = 0;
|
|
if( n < (int)Choices.GetCount() )
|
|
{
|
|
return Choices[n];
|
|
}
|
|
return wxT("");
|
|
}
|
|
|
|
/// Int-to-Index (choices can be items like e.g 0x400120 )
|
|
int ShuttleGuiBase::TranslateToIndex( const int Value, const wxArrayInt &Choices )
|
|
{
|
|
int n = Choices.Index( Value );
|
|
if( n== wxNOT_FOUND )
|
|
n=miNoMatchSelector;
|
|
miNoMatchSelector = 0;
|
|
return n;
|
|
}
|
|
|
|
/// Index-to-int (choices can be items like e.g 0x400120 )
|
|
int ShuttleGuiBase::TranslateFromIndex( const int nIn, const wxArrayInt &Choices )
|
|
{
|
|
int n = nIn;
|
|
if( n== wxNOT_FOUND )
|
|
n=miNoMatchSelector;
|
|
miNoMatchSelector = 0;
|
|
if( n < (int)Choices.GetCount() )
|
|
{
|
|
return Choices[n];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------//
|
|
|
|
|
|
// ShuttleGui code uses the model that you read into program variables
|
|
// and write out from program variables.
|
|
|
|
// In programs like Audacity which don't use internal program variables
|
|
// you have to do both steps in one go, using variants of the standard
|
|
// 'Tie' functions which call the underlying Tie functions twice.
|
|
|
|
//----------------------------------------------------------------------//
|
|
|
|
|
|
/**
|
|
Code-Condenser function.
|
|
|
|
We have functions which need to do:
|
|
|
|
\code
|
|
// Either: Values are coming in:
|
|
DoDataShuttle( SettingName, WrappedRef );
|
|
TieMyControl( Prompt, WrappedRef );
|
|
|
|
// Or: Values are going out:
|
|
TieMyControl( Prompt, WrappedRef );
|
|
DoDataShuttle( SettingName, WrappedRef );
|
|
\endcode
|
|
|
|
So we make a list of all the possible steps,
|
|
and have DoStep choose which ones are actually done,
|
|
like this:
|
|
|
|
\code
|
|
if( DoStep(1) ) DoFirstThing();
|
|
if( DoStep(2) ) DoSecondThing();
|
|
if( DoStep(3) ) DoThirdThing();
|
|
\endcode
|
|
|
|
The repeated choice logic can then be taken out of those
|
|
functions.
|
|
|
|
JKC: This paves the way for doing data validation too,
|
|
though when we add that we wil need to renumber the
|
|
steps.
|
|
*/
|
|
bool ShuttleGuiBase::DoStep( int iStep )
|
|
{
|
|
// Get value and create
|
|
if( mShuttleMode == eIsCreating )
|
|
{
|
|
return (iStep==1) || (iStep==2);
|
|
}
|
|
// Like creating, get the value and set.
|
|
if( mShuttleMode == eIsSettingToDialog )
|
|
{
|
|
return (iStep==1) || (iStep==2);
|
|
}
|
|
if( mShuttleMode == eIsGettingFromDialog )
|
|
{
|
|
return (iStep==2) || (iStep==3);
|
|
}
|
|
wxASSERT( false );
|
|
return false;
|
|
}
|
|
|
|
|
|
/// Variant of the standard TieCheckBox which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
wxCheckBox * ShuttleGuiBase::TieCheckBox(
|
|
const wxString &Prompt,
|
|
const wxString &SettingName,
|
|
const bool bDefault)
|
|
{
|
|
wxCheckBox * pCheck=NULL;
|
|
|
|
bool bValue=bDefault;
|
|
WrappedType WrappedRef( bValue );
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef );
|
|
if( DoStep(2) ) pCheck = TieCheckBox( Prompt, WrappedRef );
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef );
|
|
|
|
return pCheck;
|
|
}
|
|
|
|
/// Variant of the standard TieCheckBox which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
wxCheckBox * ShuttleGuiBase::TieCheckBoxOnRight(
|
|
const wxString &Prompt,
|
|
const wxString &SettingName,
|
|
const bool bDefault)
|
|
{
|
|
wxCheckBox * pCheck=NULL;
|
|
|
|
bool bValue=bDefault;
|
|
WrappedType WrappedRef( bValue );
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef );
|
|
if( DoStep(2) ) pCheck = TieCheckBoxOnRight( Prompt, WrappedRef );
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef );
|
|
|
|
return pCheck;
|
|
}
|
|
|
|
/// Variant of the standard TieSlider which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
wxSlider * ShuttleGuiBase::TieSlider(
|
|
const wxString &Prompt,
|
|
const wxString &SettingName,
|
|
const int iDefault,
|
|
const int max,
|
|
const int min)
|
|
{
|
|
wxSlider * pSlider=NULL;
|
|
|
|
int iValue=iDefault;
|
|
WrappedType WrappedRef( iValue );
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef );
|
|
if( DoStep(2) ) pSlider = TieSlider( Prompt, WrappedRef, max, min );
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef );
|
|
|
|
return pSlider;
|
|
}
|
|
|
|
/// Variant of the standard TieSpinCtrl which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
wxSpinCtrl * ShuttleGuiBase::TieSpinCtrl(
|
|
const wxString &Prompt,
|
|
const wxString &SettingName,
|
|
const int Value,
|
|
const int max,
|
|
const int min)
|
|
{
|
|
wxSpinCtrl * pSpinCtrl=NULL;
|
|
|
|
int iValue = Value;
|
|
WrappedType WrappedRef( iValue );
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef );
|
|
if( DoStep(2) ) pSpinCtrl = TieSpinCtrl( Prompt, WrappedRef, max, min );
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef );
|
|
|
|
return pSpinCtrl;
|
|
}
|
|
|
|
/// Variant of the standard TieTextBox which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
wxTextCtrl * ShuttleGuiBase::TieTextBox(
|
|
const wxString & Prompt,
|
|
const wxString & SettingName,
|
|
const wxString & Default,
|
|
const int nChars)
|
|
{
|
|
wxTextCtrl * pText=(wxTextCtrl*)NULL;
|
|
|
|
wxString Temp = Default;
|
|
WrappedType WrappedRef( Temp );
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef );
|
|
if( DoStep(2) ) pText = TieTextBox( Prompt, WrappedRef, nChars );
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef );
|
|
return pText;
|
|
}
|
|
|
|
/// Variant of the standard TieTextBox which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
wxTextCtrl * ShuttleGuiBase::TieNumericTextBox(
|
|
const wxString & Prompt,
|
|
const wxString & SettingName,
|
|
const wxString & Default,
|
|
const int nChars)
|
|
{
|
|
wxTextCtrl * pText=(wxTextCtrl*)NULL;
|
|
|
|
wxString Temp = Default;
|
|
WrappedType WrappedRef( Temp );
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef );
|
|
if( DoStep(2) ) pText = TieNumericTextBox( Prompt, WrappedRef, nChars );
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef );
|
|
return pText;
|
|
}
|
|
/// Variant of the standard TieTextBox which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
/// This one does it for double values...
|
|
wxTextCtrl * ShuttleGuiBase::TieTextBox(
|
|
const wxString & Prompt,
|
|
const wxString & SettingName,
|
|
const double & Default,
|
|
const int nChars)
|
|
{
|
|
wxTextCtrl * pText=(wxTextCtrl*)NULL;
|
|
|
|
double Temp = Default;
|
|
WrappedType WrappedRef( Temp );
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef );
|
|
if( DoStep(2) ) pText = TieTextBox( Prompt, WrappedRef, nChars );
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef );
|
|
return pText;
|
|
}
|
|
|
|
/// Variant of the standard TieTextBox which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
/// This one does it for double values...
|
|
wxTextCtrl * ShuttleGuiBase::TieNumericTextBox(
|
|
const wxString & Prompt,
|
|
const wxString & SettingName,
|
|
const double & Default,
|
|
const int nChars)
|
|
{
|
|
wxTextCtrl * pText=(wxTextCtrl*)NULL;
|
|
|
|
double Temp = Default;
|
|
WrappedType WrappedRef( Temp );
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef );
|
|
if( DoStep(2) ) pText = TieNumericTextBox( Prompt, WrappedRef, nChars );
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef );
|
|
return pText;
|
|
}
|
|
|
|
/// Variant of the standard TieChoice which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
/// @param Prompt The prompt shown beside the control.
|
|
/// @param SettingName The setting name as stored in gPrefs
|
|
/// @param Default The default value for this control (translated)
|
|
/// @param Choices An array of choices that appear on screen.
|
|
/// @param TranslatedChoices The corresponding values (as a string array)
|
|
wxChoice * ShuttleGuiBase::TieChoice(
|
|
const wxString &Prompt,
|
|
const wxString &SettingName,
|
|
const wxString &Default,
|
|
const wxArrayString & Choices,
|
|
const wxArrayString & TranslatedChoices)
|
|
{
|
|
wxChoice * pChoice=(wxChoice*)NULL;
|
|
|
|
int TempIndex=0;
|
|
// int TempIndex = TranslateToIndex( Default, TranslatedChoices );
|
|
wxString TempStr = Default;
|
|
WrappedType WrappedRef( TempStr );
|
|
// Get from prefs does 1 and 2.
|
|
// Put to prefs does 2 and 3.
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef ); // Get Index from Prefs.
|
|
if( DoStep(1) ) TempIndex = TranslateToIndex( TempStr, TranslatedChoices ); // To an index
|
|
if( DoStep(2) ) pChoice = TieChoice( Prompt, TempIndex, &Choices ); // Get/Put index from GUI.
|
|
if( DoStep(3) ) TempStr = TranslateFromIndex( TempIndex, TranslatedChoices ); // To a string
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef ); // Put into Prefs.
|
|
return pChoice;
|
|
}
|
|
|
|
/// Variant of the standard TieChoice which does the two step exchange
|
|
/// between gui and stack variable and stack variable and shuttle.
|
|
/// Difference to previous one is that the Translated choices and default
|
|
/// are integers, not Strings.
|
|
/// @param Prompt The prompt shown beside the control.
|
|
/// @param SettingName The setting name as stored in gPrefs
|
|
/// @param Default The default value for this control (translated)
|
|
/// @param Choices An array of choices that appear on screen.
|
|
/// @param TranslatedChoices The correcponding values (as an integer array)
|
|
wxChoice * ShuttleGuiBase::TieChoice(
|
|
const wxString &Prompt,
|
|
const wxString &SettingName,
|
|
const int Default,
|
|
const wxArrayString & Choices,
|
|
const wxArrayInt & TranslatedChoices)
|
|
{
|
|
wxChoice * pChoice=(wxChoice*)NULL;
|
|
|
|
int TempIndex=0;
|
|
int TranslatedInt = Default;
|
|
WrappedType WrappedRef( TranslatedInt );
|
|
// Get from prefs does 1 and 2.
|
|
// Put to prefs does 2 and 3.
|
|
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef ); // Get Int from Prefs.
|
|
if( DoStep(1) ) TempIndex = TranslateToIndex( TranslatedInt, TranslatedChoices ); // Int to an index.
|
|
if( DoStep(2) ) pChoice = TieChoice( Prompt, TempIndex, &Choices ); // Get/Put index from GUI.
|
|
if( DoStep(3) ) TranslatedInt = TranslateFromIndex( TempIndex, TranslatedChoices ); // Index to int
|
|
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef ); // Put into Prefs.
|
|
return pChoice;
|
|
}
|
|
|
|
/// Integer specific version of StartRadioButtonGroup.
|
|
/// All 'TieRadioButton()' enclosed must be ints.
|
|
void ShuttleGuiBase::StartRadioButtonGroup( const wxString & SettingName, const int iDefaultValue )
|
|
{
|
|
// Configure the generic type mechanism to use OUR integer.
|
|
mRadioValueInt = iDefaultValue;
|
|
mRadioValue.SetTo( mRadioValueInt );
|
|
// Now actually start the radio button group.
|
|
StartRadioButtonGroup( SettingName );
|
|
}
|
|
|
|
/// String specific version of StartRadioButtonGroup.
|
|
/// All 'TieRadioButton()' enclosed must be strings.
|
|
void ShuttleGuiBase::StartRadioButtonGroup( const wxString & SettingName, const wxString & DefaultValue )
|
|
{
|
|
// Configure the generic type mechanism to use OUR string.
|
|
mRadioValueString = DefaultValue;
|
|
mRadioValue.SetTo( mRadioValueString );
|
|
// Now actually start the radio button group.
|
|
StartRadioButtonGroup( SettingName );
|
|
}
|
|
|
|
|
|
/// This function must be within a StartRadioButtonGroup - EndRadioButtonGroup pair.
|
|
wxRadioButton * ShuttleGuiBase::TieRadioButton(
|
|
const wxString &Prompt,
|
|
const int iValue)
|
|
{
|
|
int iTemp = iValue;
|
|
WrappedType WrappedRef( iTemp );
|
|
return TieRadioButton( Prompt, WrappedRef );
|
|
}
|
|
|
|
/// This function must be within a StartRadioButtonGroup - EndRadioButtonGroup pair.
|
|
wxRadioButton * ShuttleGuiBase::TieRadioButton(
|
|
const wxString &Prompt,
|
|
const wxString &Value)
|
|
{
|
|
// In what follows, WrappedRef is used in read only mode, but we
|
|
// don't have a 'read-only' version, so we copy to deal with the constness.
|
|
wxString Temp = Value;
|
|
WrappedType WrappedRef( Temp );
|
|
return TieRadioButton( Prompt, WrappedRef );
|
|
}
|
|
|
|
//------------------------------------------------------------------//
|
|
|
|
// We're now into ShuttleGuiBase sizer and misc functions.
|
|
|
|
/// The Ids increment as we add new controls.
|
|
/// However, the user can force the id manually, for example
|
|
/// if they need a specific Id for a button, and then let it
|
|
/// resume normal numbering later.
|
|
/// UseUpId() sets miId to the next Id, either using the
|
|
/// user specicfied one, or resuming the sequence.
|
|
void ShuttleGuiBase::UseUpId()
|
|
{
|
|
if( miIdSetByUser > 0)
|
|
{
|
|
miId = miIdSetByUser;
|
|
miIdSetByUser = -1;
|
|
return;
|
|
}
|
|
miId = miIdNext++;
|
|
}
|
|
|
|
void ShuttleGuiBase::SetProportions( int Default )
|
|
{
|
|
if( miPropSetByUser >=0 )
|
|
{
|
|
miProp = miPropSetByUser;
|
|
miPropSetByUser =-1;
|
|
return;
|
|
}
|
|
miProp = Default;
|
|
}
|
|
|
|
|
|
void ShuttleGuiBase::UpdateSizersCore(bool bPrepend, int Flags)
|
|
{
|
|
if( mpWind && mpParent )
|
|
{
|
|
if( mpSizer){
|
|
if( bPrepend )
|
|
{
|
|
mpSizer->Prepend(mpWind, miProp, Flags,miBorder);
|
|
}
|
|
else
|
|
{
|
|
mpSizer->Add(mpWind, miProp, Flags,miBorder);
|
|
}
|
|
}
|
|
}
|
|
|
|
if( mpSubSizer && mpSizer )
|
|
{
|
|
// When adding sizers into sizers, don't add a border.
|
|
// unless it's a static box sizer.
|
|
if( wxDynamicCast( mpSubSizer, wxStaticBoxSizer ))
|
|
{
|
|
mpSizer->Add( mpSubSizer,miSizerProp, Flags , miBorder);
|
|
}
|
|
else
|
|
{
|
|
mpSizer->Add( mpSubSizer,miSizerProp, Flags ,0);//miBorder);
|
|
}
|
|
mpSizer = mpSubSizer;
|
|
mpSubSizer = NULL;
|
|
PushSizer();
|
|
}
|
|
mpLastWind = mpWind;
|
|
mpWind = NULL;
|
|
miProp = 0;
|
|
miSizerProp =0;
|
|
}
|
|
|
|
// Sizer is added into parent sizer, and will expand/shrink.
|
|
void ShuttleGuiBase::UpdateSizers()
|
|
{ UpdateSizersCore( false, wxEXPAND | wxALL );}
|
|
|
|
// Sizer is added into parent sizer, centred
|
|
void ShuttleGuiBase::UpdateSizersC()
|
|
{ UpdateSizersCore( false, wxALIGN_CENTRE | wxALL );}
|
|
|
|
// Sizer is added into parent sizer, and will expand/shrink.
|
|
// added to start of sizer list.
|
|
void ShuttleGuiBase::UpdateSizersAtStart()
|
|
{ UpdateSizersCore( true, wxEXPAND | wxALL );}
|
|
|
|
void ShuttleGuiBase::PopSizer()
|
|
{
|
|
mSizerDepth--;
|
|
wxASSERT( mSizerDepth >=0 );
|
|
mpSizer = pSizerStack[ mSizerDepth ];
|
|
}
|
|
|
|
void ShuttleGuiBase::PushSizer()
|
|
{
|
|
mSizerDepth++;
|
|
wxASSERT( mSizerDepth < nMaxNestedSizers );
|
|
pSizerStack[ mSizerDepth ] = mpSizer;
|
|
}
|
|
|
|
long ShuttleGuiBase::Style( long style )
|
|
{
|
|
if( miStyle )
|
|
style = miStyle;
|
|
miStyle = 0;
|
|
return style;
|
|
}
|
|
|
|
// A rarely used helper function that sets a pointer
|
|
// ONLY if the value it is to be set to is non NULL.
|
|
void SetIfCreated( wxChoice * &Var, wxChoice * Val )
|
|
{
|
|
if( Val != NULL )
|
|
Var = Val;
|
|
};
|
|
void SetIfCreated( wxTextCtrl * &Var, wxTextCtrl * Val )
|
|
{
|
|
if( Val != NULL )
|
|
Var = Val;
|
|
};
|
|
void SetIfCreated( wxStaticText *&Var, wxStaticText * Val )
|
|
{
|
|
if( Val != NULL )
|
|
Var = Val;
|
|
};
|
|
|
|
#ifdef EXPERIMENTAL_TRACK_PANEL
|
|
// Additional includes down here, to make it easier to split this into
|
|
// two files at some later date.
|
|
#include "../extnpanel-src/GuiWaveTrack.h"
|
|
#endif
|
|
#include "./widgets/Ruler.h"
|
|
#include "./widgets/AttachableScrollBar.h"
|
|
#include "ShuttlePrefs.h"
|
|
|
|
ShuttleGui::ShuttleGui(wxWindow * pParent, teShuttleMode ShuttleMode) :
|
|
ShuttleGuiBase( pParent, ShuttleMode )
|
|
{
|
|
if( ShuttleMode == eIsCreatingFromPrefs )
|
|
{
|
|
mShuttleMode = eIsCreating;
|
|
Init(); // Wasn't fully done in base constructor because it is only done when eIsCreating is set.
|
|
}
|
|
else if( ShuttleMode == eIsSavingToPrefs )
|
|
{
|
|
mShuttleMode = eIsGettingFromDialog;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
mpShuttle = new ShuttlePrefs;
|
|
// In this case the client is the GUI, so if creating we do want to
|
|
// store in the client.
|
|
mpShuttle->mbStoreInClient = (mShuttleMode == eIsCreating );
|
|
};
|
|
|
|
ShuttleGui::~ShuttleGui()
|
|
{
|
|
if( mpShuttle )
|
|
delete mpShuttle;
|
|
}
|
|
|
|
// Now we have Audacity specific shuttle functions.
|
|
ShuttleGui & ShuttleGui::Id(int id )
|
|
{
|
|
miIdSetByUser = id;
|
|
return *this;
|
|
}
|
|
|
|
GuiWaveTrack * ShuttleGui::AddGuiWaveTrack( const wxString & Name)
|
|
{
|
|
#ifdef EXPERIMENTAL_TRACK_PANEL
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return (GuiWaveTrack*)NULL;
|
|
// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), GuiWaveTrack);
|
|
GuiWaveTrack * pGuiWaveTrack;
|
|
miProp=1;
|
|
mpWind = pGuiWaveTrack = new GuiWaveTrack(mpParent, miId, Name);
|
|
mpWind->SetMinSize(wxSize(100,50));
|
|
UpdateSizers();
|
|
return pGuiWaveTrack;
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
AdornedRulerPanel * ShuttleGui::AddAdornedRuler( ViewInfo *pViewInfo )
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return (AdornedRulerPanel*)NULL;
|
|
// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), AdornedRulerPanel);
|
|
AdornedRulerPanel * pAdornedRuler;
|
|
miProp=0;
|
|
mpWind = pAdornedRuler = new AdornedRulerPanel(
|
|
mpParent,
|
|
miId,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
pViewInfo
|
|
);
|
|
|
|
mpWind->SetMinSize(wxSize(100,28));
|
|
UpdateSizers();
|
|
return pAdornedRuler;
|
|
}
|
|
|
|
|
|
RulerPanel * ShuttleGui::AddRulerVertical(float low, float hi, const wxString & Units )
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return (RulerPanel*)NULL;
|
|
// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), RulerPanel);
|
|
RulerPanel * pRulerPanel;
|
|
miProp=0;
|
|
mpWind = pRulerPanel = new RulerPanel(
|
|
mpParent,
|
|
miId,
|
|
wxDefaultPosition,
|
|
wxDefaultSize
|
|
);
|
|
Ruler & Ruler = pRulerPanel->ruler;
|
|
Ruler.SetOrientation(wxVERTICAL);
|
|
Ruler.SetBounds(0, 0, 100, 100); // Ruler can't handle small sizes
|
|
Ruler.SetRange(low, hi);
|
|
Ruler.SetFormat(Ruler::RealFormat);
|
|
Ruler.SetUnits(Units);
|
|
Ruler.SetLabelEdges(true);
|
|
|
|
mpWind->SetMinSize(wxSize(38,50));
|
|
UpdateSizers();
|
|
return pRulerPanel;
|
|
}
|
|
|
|
AttachableScrollBar * ShuttleGui::AddAttachableScrollBar( long style )
|
|
{
|
|
UseUpId();
|
|
if( mShuttleMode != eIsCreating )
|
|
return (AttachableScrollBar*)NULL;
|
|
// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), AttachableScrollBar);
|
|
AttachableScrollBar * pAttachableScrollBar;
|
|
miProp=0;
|
|
mpWind = pAttachableScrollBar = new AttachableScrollBar(
|
|
mpParent,
|
|
miId,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
style
|
|
);
|
|
mpWind->SetMinSize(wxSize(10,20));
|
|
UpdateSizers();
|
|
return pAttachableScrollBar;
|
|
}
|
|
|
|
wxSizer *CreateStdButtonSizer(wxWindow *parent, long buttons, wxButton *extra)
|
|
{
|
|
wxButton *b = new wxButton( parent, 0, wxEmptyString );
|
|
int margin;
|
|
|
|
#if defined(__WXMAC__)
|
|
margin = 12;
|
|
#elif defined(__WXGTK20__)
|
|
margin = 12;
|
|
#elif defined(__WXMSW__)
|
|
margin = b->ConvertDialogToPixels( wxSize( 2, 0 ) ).x;
|
|
#else
|
|
margin = b->ConvertDialogToPixels( wxSize( 4, 0 ) ).x;
|
|
#endif
|
|
|
|
delete b;
|
|
|
|
wxStdDialogButtonSizer *bs = new wxStdDialogButtonSizer();
|
|
|
|
if( buttons & eOkButton )
|
|
{
|
|
b = new wxButton( parent, wxID_OK );
|
|
b->SetDefault();
|
|
bs->AddButton( b );
|
|
}
|
|
|
|
if( buttons & eCancelButton )
|
|
{
|
|
bs->AddButton( new wxButton( parent, wxID_CANCEL ) );
|
|
}
|
|
|
|
if( buttons & eYesButton )
|
|
{
|
|
b = new wxButton( parent, wxID_YES );
|
|
b->SetDefault();
|
|
bs->AddButton( b );
|
|
}
|
|
|
|
if( buttons & eNoButton )
|
|
{
|
|
bs->AddButton( new wxButton( parent, wxID_NO ) );
|
|
}
|
|
|
|
if( buttons & eHelpButton )
|
|
{
|
|
bs->AddButton( new wxButton( parent, wxID_HELP ) );
|
|
}
|
|
|
|
if( buttons & ePreviewButton )
|
|
{
|
|
b = new wxButton( parent, ePreviewID, _("Pre&view") );
|
|
bs->Add( b, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin );
|
|
bs->Add( 40, 0 );
|
|
}
|
|
|
|
if( buttons & eDebugButton )
|
|
{
|
|
b = new wxButton( parent, eDebugID, _("&Debug") );
|
|
bs->Add( b, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin );
|
|
bs->Add( 40, 0 );
|
|
}
|
|
|
|
if( extra )
|
|
{
|
|
bs->Add( extra, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin );
|
|
bs->Add( 40, 0 );
|
|
}
|
|
|
|
bs->AddStretchSpacer();
|
|
bs->Realize();
|
|
wxSizer * s;
|
|
s = new wxBoxSizer( wxVERTICAL );
|
|
s->Add( bs, 1, wxEXPAND | wxALL, 7 );
|
|
s->Add( 0, 3 ); // a little extra space
|
|
|
|
return s;
|
|
}
|
|
|
|
void ShuttleGui::AddStandardButtons(long buttons, wxButton *extra)
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
|
|
StartVerticalLay( false );
|
|
|
|
miSizerProp = false;
|
|
mpSubSizer = CreateStdButtonSizer( mpParent, buttons, extra );
|
|
UpdateSizers();
|
|
PopSizer();
|
|
|
|
EndVerticalLay();
|
|
}
|
|
|
|
void ShuttleGui::AddSpace( int width, int height )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
|
|
mpSizer->Add( width, height, 0);
|
|
}
|
|
|
|
void ShuttleGui::SetSizeHints( wxWindow *window, const wxArrayString & items )
|
|
{
|
|
int maxw = 0;
|
|
|
|
for( size_t i = 0; i < items.GetCount(); i++ )
|
|
{
|
|
int x;
|
|
int y;
|
|
|
|
window->GetTextExtent(items[i], &x, &y );
|
|
if( x > maxw )
|
|
{
|
|
maxw = x;
|
|
}
|
|
}
|
|
|
|
// Would be nice to know the sizes of the button and borders, but this is
|
|
// the best we can do for now.
|
|
#if defined(__WXMAC__)
|
|
maxw += 50;
|
|
#elif defined(__WXMSW__)
|
|
maxw += 50;
|
|
#elif defined(__WXGTK__)
|
|
maxw += 50;
|
|
#else
|
|
maxw += 50;
|
|
#endif
|
|
|
|
window->SetSizeHints( maxw, -1 );
|
|
}
|
|
|
|
void ShuttleGui::SetSizeHints( wxWindow *window, const wxArrayInt & items )
|
|
{
|
|
wxArrayString strs;
|
|
|
|
for( size_t i = 0; i < items.GetCount(); i++ )
|
|
{
|
|
strs.Add( wxString::Format( wxT("%d"), items[i] ) );
|
|
}
|
|
|
|
SetSizeHints( window, strs );
|
|
}
|
|
|
|
void ShuttleGui::SetSizeHints( const wxArrayString & items )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
|
|
SetSizeHints( mpLastWind, items );
|
|
}
|
|
|
|
void ShuttleGui::SetSizeHints( const wxArrayInt & items )
|
|
{
|
|
if( mShuttleMode != eIsCreating )
|
|
return;
|
|
|
|
SetSizeHints( mpLastWind, items );
|
|
}
|
|
|
|
void ShuttleGui::SetSizeHints( int minX, int minY )
|
|
{
|
|
ShuttleGuiBase::SetSizeHints( minX, minY );
|
|
}
|