Fix Big Time TimerToolBar, Stage III

Fixed issue where format selector could disappear.
Fixed upgrade from 2.3.3.
Remembers time format.
This commit is contained in:
James Crook 2020-02-14 12:02:21 +00:00
parent 1dffc4fe1f
commit 9985b8a9b8
16 changed files with 296 additions and 61 deletions

View File

@ -455,6 +455,21 @@ void PopulatePreferences()
gPrefs->Write(wxT("/GUI/Shortcuts/FullDefaults"),1);
}
// Upgrading pre 2.4.0 configs, the selection toolbar is now split.
if ((0<vMajor && vMajor < 2) ||
(vMajor == 2 && vMinor < 4))
{
gPrefs->Write(wxT("/GUI/Toolbars/Selection/W"),"");
gPrefs->Write(wxT("/GUI/Toolbars/TimeToolBar/X"),-1);
gPrefs->Write(wxT("/GUI/Toolbars/TimeToolBar/Y"),-1);
gPrefs->Write(wxT("/GUI/Toolbars/TimeToolBar/H"),55);
gPrefs->Write(wxT("/GUI/Toolbars/TimeToolBar/W"),251);
gPrefs->Write(wxT("/GUI/Toolbars/TimeToolBar/DockV2"),2);
gPrefs->Write(wxT("/GUI/Toolbars/TimeToolBar/Dock"),2);
gPrefs->Write(wxT("/GUI/Toolbars/TimeToolBar/Path"),"0,0");
gPrefs->Write(wxT("/GUI/Toolbars/TimeToolBar/Show"),1);
}
// write out the version numbers to the prefs file for future checking
gPrefs->Write(wxT("/Version/Major"), AUDACITY_VERSION);
gPrefs->Write(wxT("/Version/Minor"), AUDACITY_RELEASE);

View File

@ -306,6 +306,10 @@ bool ProjectFileIO::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
settings.SetSelectionFormat(
NumericConverter::LookupFormat( NumericConverter::TIME, value) );
else if (!wxStrcmp(attr, wxT("audiotimeformat")))
settings.SetAudioTimeFormat(
NumericConverter::LookupFormat( NumericConverter::TIME, value) );
else if (!wxStrcmp(attr, wxT("frequencyformat")))
settings.SetFrequencySelectionFormatName(
NumericConverter::LookupFormat( NumericConverter::FREQUENCY, value ) );

View File

@ -1352,6 +1352,7 @@ void ProjectFileManager::OpenFile(const FilePath &fileNameArg, bool addtohistory
auto &selectionManager = ProjectSelectionManager::Get( project );
selectionManager.AS_SetSnapTo(settings.GetSnapTo());
selectionManager.AS_SetSelectionFormat(settings.GetSelectionFormat());
selectionManager.TT_SetAudioTimeFormat(settings.GetAudioTimeFormat());
selectionManager.SSBL_SetFrequencySelectionFormatName(
settings.GetFrequencySelectionFormatName());
selectionManager.SSBL_SetBandwidthSelectionFormatName(

View File

@ -45,6 +45,7 @@ Paul Licameli split from AudacityProject.cpp
#include "toolbars/MixerToolBar.h"
#include "toolbars/SelectionBar.h"
#include "toolbars/SpectralSelectionBar.h"
#include "toolbars/TimerToolBar.h"
#include "toolbars/ToolManager.h"
#include "widgets/AudacityMessageBox.h"
#include "widgets/FileHistory.h"
@ -569,6 +570,7 @@ AudacityProject *ProjectManager::New()
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
SpectralSelectionBar::Get( project ).SetListener( &projectSelectionManager );
#endif
TimerToolBar::Get( project ).SetListener( &projectSelectionManager );
#if wxUSE_DRAG_AND_DROP
// We can import now, so become a drag target

View File

@ -22,6 +22,7 @@ Paul Licameli split from ProjectManager.cpp
#include "WaveTrack.h"
#include "toolbars/SelectionBar.h"
#include "toolbars/SpectralSelectionBar.h"
#include "toolbars/TimerToolBar.h"
static AudacityProject::AttachedObjects::RegisteredFactory
sProjectSelectionManagerKey {
@ -149,6 +150,26 @@ void ProjectSelectionManager::AS_SetSelectionFormat(
SelectionBar::Get( project ).SetSelectionFormat(format);
}
const NumericFormatSymbol & ProjectSelectionManager::TT_GetAudioTimeFormat()
{
auto &project = mProject;
auto &settings = ProjectSettings::Get( project );
return settings.GetAudioTimeFormat();
}
void ProjectSelectionManager::TT_SetAudioTimeFormat(
const NumericFormatSymbol & format)
{
auto &project = mProject;
auto &settings = ProjectSettings::Get( project );
settings.SetAudioTimeFormat( format );
gPrefs->Write(wxT("/AudioTimeFormat"), format.Internal());
gPrefs->Flush();
TimerToolBar::Get( project ).SetAudioTimeFormat(format);
}
void ProjectSelectionManager::AS_ModifySelection(
double &start, double &end, bool done)
{

View File

@ -21,6 +21,7 @@ class ProjectSelectionManager final
: public ClientData::Base
, public SelectionBarListener
, public SpectralSelectionBarListener
, public TimerToolBarListener
{
public:
static ProjectSelectionManager &Get( AudacityProject &project );
@ -39,6 +40,8 @@ public:
void AS_SetSnapTo(int snap) override;
const NumericFormatSymbol & AS_GetSelectionFormat() override;
void AS_SetSelectionFormat(const NumericFormatSymbol & format) override;
const NumericFormatSymbol & TT_GetAudioTimeFormat() override;
void TT_SetAudioTimeFormat(const NumericFormatSymbol & format) override;
void AS_ModifySelection(double &start, double &end, bool done) override;
// SpectralSelectionBarListener callback methods

View File

@ -47,11 +47,15 @@ const ProjectSettings &ProjectSettings::Get( const AudacityProject &project )
return Get( const_cast< AudacityProject & >( project ) );
}
ProjectSettings::ProjectSettings( AudacityProject &project )
: mProject{ project }
, mSelectionFormat{ NumericTextCtrl::LookupFormat(
ProjectSettings::ProjectSettings(AudacityProject &project)
: mProject{ project }
, mSelectionFormat{ NumericTextCtrl::LookupFormat(
NumericConverter::TIME,
gPrefs->Read(wxT("/SelectionFormat"), wxT("")))
}
, mAudioTimeFormat{ NumericTextCtrl::LookupFormat(
NumericConverter::TIME,
gPrefs->Read(wxT("/SelectionFormat"), wxT("")) )
gPrefs->Read(wxT("/AudioTimeFormat"), wxT("hh:mm:ss")))
}
, mFrequencySelectionFormatName{ NumericTextCtrl::LookupFormat(
NumericConverter::FREQUENCY,
@ -149,6 +153,16 @@ const NumericFormatSymbol & ProjectSettings::GetSelectionFormat() const
return mSelectionFormat;
}
void ProjectSettings::SetAudioTimeFormat(const NumericFormatSymbol & format)
{
mAudioTimeFormat = format;
}
const NumericFormatSymbol & ProjectSettings::GetAudioTimeFormat() const
{
return mAudioTimeFormat;
}
void ProjectSettings::SetSnapTo(int snap)
{
mSnapTo = snap;

View File

@ -93,12 +93,14 @@ public:
mPlaySpeed.store( value, std::memory_order_relaxed ); }
// Selection Format
void SetSelectionFormat(const NumericFormatSymbol & format);
const NumericFormatSymbol & GetSelectionFormat() const;
// Spectral Selection Formats
// AudioTime format
void SetAudioTimeFormat(const NumericFormatSymbol & format);
const NumericFormatSymbol & GetAudioTimeFormat() const;
// Spectral Selection Formats
void SetFrequencySelectionFormatName(const NumericFormatSymbol & format);
const NumericFormatSymbol & GetFrequencySelectionFormatName() const;
@ -120,6 +122,7 @@ private:
NumericFormatSymbol mSelectionFormat;
NumericFormatSymbol mFrequencySelectionFormatName;
NumericFormatSymbol mBandwidthSelectionFormatName;
NumericFormatSymbol mAudioTimeFormat;
wxString mSoloPref;

View File

@ -31,4 +31,15 @@ class AUDACITY_DLL_API SelectionBarListener /* not final */ {
virtual void AS_ModifySelection(double &start, double &end, bool done) = 0;
};
class AUDACITY_DLL_API TimerToolBarListener /* not final */ {
public:
TimerToolBarListener(){};
virtual ~TimerToolBarListener(){};
virtual const NumericFormatSymbol & TT_GetAudioTimeFormat() = 0;
virtual void TT_SetAudioTimeFormat(const NumericFormatSymbol & format) = 0;
};
#endif

View File

@ -62,15 +62,19 @@ enum {
};
BEGIN_EVENT_TABLE(TimerToolBar, ToolBar)
EVT_SIZE(TimerToolBar::OnSize)
EVT_IDLE( TimerToolBar::OnIdle )
EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, TimerToolBar::OnCaptureKey)
EVT_SIZE(TimerToolBar::OnSize)
EVT_IDLE( TimerToolBar::OnIdle )
EVT_COMMAND(wxID_ANY, EVT_TIMETEXTCTRL_UPDATED, TimerToolBar::OnUpdate)
EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, TimerToolBar::OnCaptureKey)
END_EVENT_TABLE()
TimerToolBar::TimerToolBar( AudacityProject &project )
: ToolBar(project, TimeBarID, XO("TimeToolBar"), wxT("TimeToolBar"),true),
mListener(NULL), mAudioTime(NULL)
{
mMinWidth = 50;
mDigitHeight = 48;
mbPreserveHeight = false;
mRate = (double) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"),
AudioIO::GetOptimalSupportedSampleRate());
}
@ -97,42 +101,160 @@ void TimerToolBar::Create(wxWindow * parent)
}
NumericTextCtrl * TimerToolBar::AddTime(
const TranslatableString &Name, int id)
const TranslatableString &Name, int id, wxSizer * pSizer)
{
//auto formatName = mListener ? mListener->AS_GetSelectionFormat()
//: NumericFormatSymbol{};
auto formatName = NumericConverter::HoursMinsSecondsFormat();
auto formatName = mListener ? mListener->TT_GetAudioTimeFormat()
: NumericConverter::HoursMinsSecondsFormat();
auto pCtrl = safenew NumericTextCtrl(
this, id, NumericConverter::TIME, formatName, 0.0, mRate);
pCtrl->SetName(Name);
pCtrl->SetReadOnly(true);
pCtrl->SetDigitSize( mDigitHeight * 0.66,mDigitHeight );
pSizer->Add(pCtrl, 0, wxALIGN_CENTER , 0);
return pCtrl;
}
void TimerToolBar::Populate()
{
mAudioTime = AddTime(XO("Audio Position"), AudioTimeID);
wxSizer *mainSizer = GetSizer();
mAudioTime = AddTime(XO("Audio Position"), AudioTimeID, mainSizer);
Add(mAudioTime, 0, wxALIGN_CENTER);
Layout();
mainSizer->Layout();
RegenerateTooltips();
SetMinSize(GetSizer()->GetMinSize());
}
void TimerToolBar::SetListener(TimerToolBarListener *l)
{
mListener = l;
SetAudioTimeFormat(mListener->TT_GetAudioTimeFormat());
};
void TimerToolBar::UpdatePrefs()
{
wxCommandEvent e;
e.SetInt(mAudioTime->GetFormatIndex());
OnUpdate(e);
SetLabel(XO("Time"));
ToolBar::UpdatePrefs();
}
void TimerToolBar::SetAudioTimeFormat(const NumericFormatSymbol & format)
{
bool changed =
mAudioTime->SetFormatString(mAudioTime->GetBuiltinFormat(format));
// Test first whether changed, to avoid infinite recursion from OnUpdate
if ( changed ) {
wxCommandEvent e;
e.SetInt(mAudioTime->GetFormatIndex());
OnUpdate(e);
}
}
// Called when the format drop downs is changed.
void TimerToolBar::OnUpdate(wxCommandEvent &evt)
{
int index = evt.GetInt();
wxWindow *w = FindFocus();
bool bHasFocus = (w == mAudioTime);
mbPreserveHeight = true;
// If docked, font height is determined by toolbar height.
// If undocked, determined by last resize.
if (IsDocked())
mDigitHeight = GetSize().GetHeight()-6;
evt.Skip(false);
// Save format name before recreating the controls so they resize properly
{
auto format = mAudioTime->GetBuiltinName(index);
if (mListener)
mListener->TT_SetAudioTimeFormat(format);
}
wxSize sz = GetSize();
RegenerateTooltips();
// ReCreateButtons() will get rid of our sizers and controls
// so reset pointer first.
mAudioTime = NULL;
ReCreateButtons();
auto x = GetSizer()->GetMinSize().GetX();
SetMinSize(wxSize(x, sz.GetHeight()));
SetResizingLimits();
if( bHasFocus )
mAudioTime->SetFocus();
Updated();
mbPreserveHeight = false;
}
void TimerToolBar::SetDocked(ToolDock *dock, bool pushed)
{
ToolBar::SetDocked(dock, pushed);
if (!IsDocked()) {
wxSize sz = GetMinSize();
sz.y = 22;
SetMinSize(sz);
}
}
void TimerToolBar::SetToDefaultSize(){
wxSize sz;
sz.SetHeight( 80 );
sz.SetHeight( 48 );
sz.SetWidth( GetInitialWidth());
SetSize( sz );
}
void TimerToolBar::SetResizingLimits() {
if (!IsDocked()) {
wxWindow * pWnd = GetParent();
ToolFrame * pFrame = dynamic_cast<ToolFrame*>(pWnd);
Layout();
if (pFrame) {
pFrame->Layout();
// Set smallest conceivable min size
pFrame->SetMinSize(wxSize(80, 24));
// Fit frame around the toolbar
pFrame->Fit();
// The resize handle takes 25 pixels.
// And was not accounted for in the Fit().
wxSize sz = pFrame->GetSize();
sz.x += 45;
sz.y += 2;
pFrame->SetSize(sz);
// Now compute and lock in the min frame size
// using aspect ratio, so that dragging won't go
// smaller than this.
pFrame->LockInMinSize(this);
}
}
else
{
Fit();
Layout();
wxSize sz1 = GetSizer()->GetMinSize();
int minHeight = 21;
if (sz1.y > minHeight) {
sz1.x = 47+(sz1.x * minHeight) / sz1.y;
GetSizer()->SetMinSize(sz1);
SetMinSize(sz1);
}
}
}
// This 'OnSize' function is also called during moving the
// toolbar.
void TimerToolBar::OnSize(wxSizeEvent & ev)
{
ev.Skip();
@ -140,28 +262,28 @@ void TimerToolBar::OnSize(wxSizeEvent & ev)
if (!mAudioTime)
return;
// This 'OnSize' function is also called during moving the
// toolbar.
// If we are changing the time format, then we
// preserve the height. Otherwise we size the font to fit
// the space given.
if (!mbPreserveHeight) {
// 10 and 50 are magic numbers to allow some space around
// the numeric control. The horizontal space reserved
// is deliberately not quite enough. Size of font is set
// primarily by the height of the toolbar. The width
// calculations just stop the font width being
// ridiculously too large to fit.
// In practice a user will drag the size to get a good font
// size and adjust the width so that part of the control
// does not disappear.
float f = mAudioTime->GetAspectRatio();
int sh = ev.GetSize().GetHeight() - 10;
int sw = (ev.GetSize().GetWidth() - 50)/f;
sw = wxMin( sh, sw );
// The 22 and 77 are magic numbers setting min and max
// font sizes.
sw = wxMin( sw, 77 );
sw = wxMax( 20, sw );
sh = sw * 0.63;
mAudioTime->SetDigitSize( sh, sw );
int mx = ev.GetSize().GetWidth() - 25;
int my = ev.GetSize().GetHeight();
int h = my-2;
h = wxMax(21, h);
h = wxMin(h, 77);
//wxLogDebug("Try h=%i dimensions(%i,%i)", h,mx,my);
h++;
do {
h--;
mAudioTime->SetDigitSize(h*0.66, h);
} while ((h > 21) && mAudioTime->IsTooBig(mx, my));
mAudioTime->Layout();
//wxLogDebug(" accept height:%i", h);
mDigitHeight = h;
}
// Refresh and update immediately, so that we don't get
// to see grot from partly redrawn toolbar during
@ -172,7 +294,7 @@ void TimerToolBar::OnSize(wxSizeEvent & ev)
void TimerToolBar::SetTimes(double audio)
{
mAudioTime->SetValue(audio);
mAudioTime->SetValue(wxMax( 0.0, audio));
}
void TimerToolBar::OnFocus(wxFocusEvent &event)
@ -218,12 +340,6 @@ void TimerToolBar::OnIdle( wxIdleEvent &evt )
SetTimes( audioTime);
}
void TimerToolBar::OnSnapTo(wxCommandEvent & WXUNUSED(event))
{
mListener->AS_SetSnapTo(mSnapTo->GetSelection());
}
static RegisteredToolbarFactory factory{ TimeBarID,
[]( AudacityProject &project ){
return ToolBar::Holder{ safenew TimerToolBar{ project } }; }

View File

@ -34,30 +34,37 @@ public:
void Repaint(wxDC * WXUNUSED(dc)) override {};
void EnableDisableButtons() override {};
void UpdatePrefs() override;
void OnUpdate(wxCommandEvent &evt);
void SetTimes(double audio);
void SetListener(TimerToolBarListener *l);
void SetAudioTimeFormat(const NumericFormatSymbol & format);
void RegenerateTooltips() override {};
int GetInitialWidth() override {return 250;}
int GetMinToolbarWidth() override { return 150; }
int GetMinToolbarWidth() override { return mMinWidth; }
void SetToDefaultSize() override;
wxSize GetDockedSize() override {
return GetSmartDockedSize();
};
void SetDocked(ToolDock *dock, bool pushed) override;
void SetResizingLimits();
private:
NumericTextCtrl * AddTime( const TranslatableString &Name, int id);
NumericTextCtrl * AddTime( const TranslatableString &Name, int id,
wxSizer * pSizer);
void OnFocus(wxFocusEvent &event);
void OnCaptureKey(wxCommandEvent &event);
void OnSize(wxSizeEvent &evt);
void OnIdle( wxIdleEvent &evt );
void OnSnapTo(wxCommandEvent & event);
SelectionBarListener * mListener;
TimerToolBarListener * mListener;
double mRate;
double mAudio;
int mMinWidth;
int mDigitHeight;
bool mbPreserveHeight;
NumericTextCtrl *mAudioTime;
wxChoice *mSnapTo;

View File

@ -487,9 +487,6 @@ wxSize ToolBar::GetSmartDockedSize()
{
const int tbs = toolbarSingle + toolbarGap;
wxSize sz = GetSize();
wxSize sz2 = GetMinSize();
sz.x = wxMax( sz.x, sz2.x );
sz.y = wxMax( sz.y, sz2.y );
// 46 is the size where we switch from expanded to compact.
if( sz.y < 46 )
sz.y = tbs-1;
@ -540,7 +537,6 @@ void ToolBar::ReCreateButtons()
// Set dock after possibly creating resizer.
// (Re)Establish dock state
SetDocked(GetDock(), false);
// Set the sizer
SetSizerAndFit(ms.release());
}
@ -556,13 +552,17 @@ void ToolBar::ReCreateButtons()
// 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.SetWidth(wxMax( sz2.GetX(), GetMinToolbarWidth()));
if (!IsDocked()) {
sz2.x += 30;// for the stripy resize handle.
}
sz2.y = tbs -1;
SetMinSize(sz2);
// sz2 is now the minimum size.
// sz3 is the size we were.
// When recreating buttons, we want to preserve size.
// We're recreating buttons, and we want to preserve original size.
// But not if that makes the size too small.
// Size at least as big as minimum.
@ -570,7 +570,6 @@ void ToolBar::ReCreateButtons()
sz3.y = sz2.y;
if( sz3.x < sz2.x )
sz3.x = sz2.x;
SetSize(sz3);
}
else

View File

@ -158,6 +158,23 @@ void ToolFrame::OnGrabber( GrabberEvent & event )
mManager->ProcessEvent( event );
}
// The current size determines the min size for resizing...
// the 'lock in' is at that aspect ratio.
void ToolFrame::LockInMinSize(ToolBar * pBar)
{
mBar = pBar;
wxSize sz = mBar->GetSize();
SetClientSize( sz );
int yDesiredMin = 26;
int y = sz.GetHeight();
if (y > yDesiredMin) {
sz.SetWidth((sz.GetWidth() * yDesiredMin) / y);
sz.SetHeight( yDesiredMin );
}
mMinSize = sz -wxSize( 10, 0);
}
void ToolFrame::OnToolBarUpdate( wxCommandEvent & event )
{
// Resize floater window to exactly contain toolbar

View File

@ -164,6 +164,7 @@ public:
ToolBar *GetBar() { return mBar; }
void ClearBar() { mBar = nullptr; }
void LockInMinSize(ToolBar * pBar);
//
// Transition a toolbar from float to dragging

View File

@ -1329,6 +1329,7 @@ NumericTextCtrl::NumericTextCtrl(wxWindow *parent, wxWindowID id,
Layout();
Fit();
ValueToControls();
//PRL -- would this fix the following?
//ValueToControls();
@ -1351,6 +1352,7 @@ NumericTextCtrl::NumericTextCtrl(wxWindow *parent, wxWindowID id,
if (options.hasValue)
SetValue( options.value );
}
NumericTextCtrl::~NumericTextCtrl()
@ -1456,7 +1458,8 @@ void NumericTextCtrl::SetInvalidValue(double invalidValue)
SetValue(invalidValue);
}
bool NumericTextCtrl::Layout()
void NumericTextCtrl::ComputeSizing()
{
unsigned int i, j;
int x, pos;
@ -1525,6 +1528,19 @@ bool NumericTextCtrl::Layout()
mWidth = x + mBorderRight;
mHeight = mDigitBoxH + mBorderTop + mBorderBottom;
}
bool NumericTextCtrl::Layout()
{
ComputeSizing();
wxMemoryDC memDC;
wxCoord strW, strH;
memDC.SetFont(*mLabelFont);
memDC.GetTextExtent(mPrefix, &strW, &strH);
int i;
// Draw the background bitmap - it contains black boxes where
// all of the digits go and all of the other text

View File

@ -49,6 +49,7 @@ public:
enum Type {
TIME,
ATIME, // for Audio time control.
FREQUENCY,
BANDWIDTH,
};
@ -192,6 +193,7 @@ class NumericTextCtrl final : public wxControl, public NumericConverter
void SetName( const TranslatableString &name );
bool Layout() override;
void ComputeSizing();
void Fit() override;
void SetSampleRate(double sampleRate);
@ -218,7 +220,10 @@ class NumericTextCtrl final : public wxControl, public NumericConverter
int GetFocusedField() { return mLastField; }
int GetFocusedDigit() { return mFocusedDigit; }
// give a sane aspect ratio even if zero height.
float GetAspectRatio() { return mHeight ? (mWidth / mHeight):10; }
bool IsTooBig(int width, int height) {
ComputeSizing();
return (mWidth > width) || (mHeight > height);
}
private: