mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-11 09:31:13 +02:00
Bug 2318 - Linux: Time Toolbar is needlessly resized too large when accommodating longer time format
This commit is contained in:
parent
1fa86ee868
commit
a5db7bbb2b
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Audacity: A Digital Audio Editor
|
Audacity: A Digital Audio Editor
|
||||||
|
|
||||||
TimerToolBar.cpp
|
TimeToolBar.cpp
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -11,14 +11,7 @@
|
|||||||
|
|
||||||
*//*******************************************************************/
|
*//*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include "../Audacity.h"
|
#include "../Audacity.h"
|
||||||
#include "../Experimental.h"
|
|
||||||
|
|
||||||
#include "SelectionBar.h"
|
|
||||||
|
|
||||||
#include "SelectionBarListener.h"
|
|
||||||
#include "ToolManager.h"
|
|
||||||
|
|
||||||
// For compilers that support precompilation, includes "wx/wx.h".
|
// For compilers that support precompilation, includes "wx/wx.h".
|
||||||
#include <wx/wxprec.h>
|
#include <wx/wxprec.h>
|
||||||
@ -26,393 +19,331 @@
|
|||||||
#include <wx/setup.h> // for wxUSE_* macros
|
#include <wx/setup.h> // for wxUSE_* macros
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include <wx/choice.h>
|
|
||||||
#include <wx/intl.h>
|
#include <wx/intl.h>
|
||||||
#include <wx/settings.h>
|
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/valtext.h>
|
|
||||||
#include <wx/stattext.h>
|
|
||||||
#endif
|
#endif
|
||||||
#include <wx/statline.h>
|
|
||||||
|
|
||||||
#include "SelectionBarListener.h"
|
|
||||||
#include "SelectionBar.h"
|
|
||||||
#include "TimerToolBar.h"
|
#include "TimerToolBar.h"
|
||||||
|
#include "ToolManager.h"
|
||||||
|
#include "SelectionBarListener.h"
|
||||||
|
|
||||||
//#include "../widgets/AButton.h"
|
|
||||||
#include "../AudioIO.h"
|
#include "../AudioIO.h"
|
||||||
#include "../AColor.h"
|
|
||||||
#include "../KeyboardCapture.h"
|
|
||||||
#include "../Prefs.h"
|
|
||||||
#include "../Project.h"
|
|
||||||
#include "../ProjectAudioIO.h"
|
#include "../ProjectAudioIO.h"
|
||||||
#include "../ProjectSettings.h"
|
|
||||||
#include "../Snap.h"
|
|
||||||
#include "../ViewInfo.h"
|
#include "../ViewInfo.h"
|
||||||
#include "../widgets/NumericTextCtrl.h"
|
|
||||||
#include "../AllThemeResources.h"
|
|
||||||
|
|
||||||
#if wxUSE_ACCESSIBILITY
|
|
||||||
#include "../widgets/WindowAccessible.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(TimerToolBar, ToolBar);
|
IMPLEMENT_CLASS(TimerToolBar, ToolBar);
|
||||||
|
|
||||||
enum {
|
|
||||||
TimerToolBarFirstID = 2700,
|
|
||||||
AudioTimeID,
|
|
||||||
};
|
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(TimerToolBar, ToolBar)
|
BEGIN_EVENT_TABLE(TimerToolBar, ToolBar)
|
||||||
EVT_SIZE(TimerToolBar::OnSize)
|
|
||||||
EVT_IDLE( TimerToolBar::OnIdle )
|
|
||||||
EVT_COMMAND(wxID_ANY, EVT_TIMETEXTCTRL_UPDATED, TimerToolBar::OnUpdate)
|
EVT_COMMAND(wxID_ANY, EVT_TIMETEXTCTRL_UPDATED, TimerToolBar::OnUpdate)
|
||||||
EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, TimerToolBar::OnCaptureKey)
|
EVT_SIZE(TimerToolBar::OnSize)
|
||||||
|
EVT_IDLE(TimerToolBar::OnIdle)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
TimerToolBar::TimerToolBar( AudacityProject &project )
|
TimerToolBar::TimerToolBar(AudacityProject &project)
|
||||||
: ToolBar(project, TimeBarID, XO("Time"), wxT("Time"),true),
|
: ToolBar(project, TimeBarID, XO("Time"), wxT("Time"), true),
|
||||||
mListener(NULL), mAudioTime(NULL)
|
mListener(NULL),
|
||||||
|
mAudioTime(NULL)
|
||||||
{
|
{
|
||||||
mMinWidth = 50;
|
|
||||||
mDigitHeight = 48;
|
|
||||||
mbReady = false;
|
|
||||||
mbPreserveHeight = false;
|
|
||||||
mbPreserveWidth = false;
|
|
||||||
mRate = (double) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"),
|
|
||||||
AudioIO::GetOptimalSupportedSampleRate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TimerToolBar::~TimerToolBar()
|
TimerToolBar::~TimerToolBar()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TimerToolBar &TimerToolBar::Get( AudacityProject &project )
|
TimerToolBar &TimerToolBar::Get(AudacityProject &project)
|
||||||
{
|
{
|
||||||
auto &toolManager = ToolManager::Get( project );
|
auto &toolManager = ToolManager::Get(project);
|
||||||
return *static_cast<TimerToolBar*>( toolManager.GetToolBar(TimeBarID) );
|
return *static_cast<TimerToolBar*>(toolManager.GetToolBar(TimeBarID));
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimerToolBar &TimerToolBar::Get( const AudacityProject &project )
|
const TimerToolBar &TimerToolBar::Get(const AudacityProject &project)
|
||||||
{
|
{
|
||||||
return Get( const_cast<AudacityProject&>( project )) ;
|
return Get(const_cast<AudacityProject&>(project)) ;
|
||||||
}
|
|
||||||
|
|
||||||
void TimerToolBar::Create(wxWindow * parent)
|
|
||||||
{
|
|
||||||
mbIsCreating = true;
|
|
||||||
ToolBar::Create(parent);
|
|
||||||
UpdatePrefs();
|
|
||||||
mbIsCreating = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NumericTextCtrl * TimerToolBar::AddTime(
|
|
||||||
const TranslatableString &Name, int id, wxSizer * pSizer)
|
|
||||||
{
|
|
||||||
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()
|
void TimerToolBar::Populate()
|
||||||
{
|
{
|
||||||
|
// Get the default sample rate
|
||||||
|
auto rate = gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"),
|
||||||
|
AudioIO::GetOptimalSupportedSampleRate());
|
||||||
|
|
||||||
wxSizer *mainSizer = GetSizer();
|
// Get the default time format
|
||||||
|
auto format = NumericConverter::HoursMinsSecondsFormat();
|
||||||
|
|
||||||
mAudioTime = AddTime(XO("Audio Position"), AudioTimeID, mainSizer);
|
// Create the read-only time control
|
||||||
|
mAudioTime = safenew NumericTextCtrl(this, wxID_ANY, NumericConverter::TIME, format, 0.0, rate);
|
||||||
mainSizer->Layout();
|
mAudioTime->SetName(XO("Audio Position"));
|
||||||
RegenerateTooltips();
|
mAudioTime->SetReadOnly(true);
|
||||||
SetMinSize(GetSizer()->GetMinSize());
|
|
||||||
|
// Add it to the toolbar
|
||||||
|
Add(mAudioTime, 0, wxALIGN_CENTER, 0);
|
||||||
|
|
||||||
|
// Calculate the width to height ratio
|
||||||
|
wxSize digitSize = mAudioTime->GetDigitSize();
|
||||||
|
mDigitRatio = (float)digitSize.x / digitSize.y;
|
||||||
|
|
||||||
|
// Establish initial resizing limits
|
||||||
|
// SetResizingLimits();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerToolBar::UpdatePrefs()
|
||||||
|
{
|
||||||
|
// Since the language may have changed, we need to force an update to accommodate
|
||||||
|
// different length text
|
||||||
|
wxCommandEvent e;
|
||||||
|
e.SetInt(mAudioTime->GetFormatIndex());
|
||||||
|
OnUpdate(e);
|
||||||
|
|
||||||
|
// Language may have changed so reset label
|
||||||
|
SetLabel(XO("Time"));
|
||||||
|
|
||||||
|
// Give the toolbar a chance
|
||||||
|
ToolBar::UpdatePrefs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerToolBar::SetToDefaultSize()
|
||||||
|
{
|
||||||
|
// Reset
|
||||||
|
SetMaxSize(wxDefaultSize);
|
||||||
|
SetMinSize(wxDefaultSize);
|
||||||
|
|
||||||
|
// Set the default time format
|
||||||
|
SetAudioTimeFormat(NumericConverter::HoursMinsSecondsFormat());
|
||||||
|
|
||||||
|
// Set the default size
|
||||||
|
SetSize(GetInitialWidth(), 48);
|
||||||
|
|
||||||
|
// Inform others the toobar has changed
|
||||||
|
Updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxSize TimerToolBar::GetDockedSize()
|
||||||
|
{
|
||||||
|
wxSize sz = GetSize();
|
||||||
|
|
||||||
|
// Anything less than a single height bar becomes single height
|
||||||
|
if (sz.y <= toolbarSingle) {
|
||||||
|
sz.y = toolbarSingle;
|
||||||
|
}
|
||||||
|
// Otherwise it will be a double height bar
|
||||||
|
else {
|
||||||
|
sz.y = 2 * toolbarSingle + toolbarGap;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerToolBar::SetDocked(ToolDock *dock, bool pushed)
|
||||||
|
{
|
||||||
|
// It's important to call this FIRST since it unhides the resizer control.
|
||||||
|
// Not doing so causes the calculated best size to be off by the width
|
||||||
|
// of the resizer.
|
||||||
|
ToolBar::SetDocked(dock, pushed);
|
||||||
|
|
||||||
|
// Recalculate the min and max limits
|
||||||
|
SetResizingLimits();
|
||||||
|
|
||||||
|
// When moving from floater to dock, fit to toolbar since the resizer will
|
||||||
|
// be mispositioned
|
||||||
|
if (dock) {
|
||||||
|
// Fit() while retaining height
|
||||||
|
SetSize(GetBestSize().x, GetSize().y);
|
||||||
|
|
||||||
|
// Inform others the toolbar has changed
|
||||||
|
Updated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerToolBar::SetListener(TimerToolBarListener *l)
|
void TimerToolBar::SetListener(TimerToolBarListener *l)
|
||||||
{
|
{
|
||||||
mbPreserveWidth = true;
|
// Remember the listener
|
||||||
mListener = l;
|
mListener = l;
|
||||||
|
|
||||||
|
// Get (and set) the saved time format
|
||||||
SetAudioTimeFormat(mListener->TT_GetAudioTimeFormat());
|
SetAudioTimeFormat(mListener->TT_GetAudioTimeFormat());
|
||||||
mbPreserveWidth = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void TimerToolBar::UpdatePrefs()
|
|
||||||
{
|
|
||||||
mbPreserveWidth = true;
|
|
||||||
wxCommandEvent e;
|
|
||||||
e.SetInt(mAudioTime->GetFormatIndex());
|
|
||||||
OnUpdate(e);
|
|
||||||
mbPreserveWidth = false;
|
|
||||||
|
|
||||||
SetLabel(XO("Time"));
|
|
||||||
ToolBar::UpdatePrefs();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerToolBar::SetAudioTimeFormat(const NumericFormatSymbol & format)
|
void TimerToolBar::SetAudioTimeFormat(const NumericFormatSymbol & format)
|
||||||
{
|
{
|
||||||
bool changed =
|
// Set the format if it's different from previous
|
||||||
mAudioTime->SetFormatString(mAudioTime->GetBuiltinFormat(format));
|
if (mAudioTime->SetFormatString(mAudioTime->GetBuiltinFormat(format))) {
|
||||||
|
// Simulate an update since the format has changed.
|
||||||
// Test first whether changed, to avoid infinite recursion from OnUpdate
|
|
||||||
if ( changed || !mbReady ) {
|
|
||||||
if (!mbReady) {
|
|
||||||
//wxLogDebug("Ready!");
|
|
||||||
mbReady = true;
|
|
||||||
}
|
|
||||||
wxCommandEvent e;
|
wxCommandEvent e;
|
||||||
e.SetInt(mAudioTime->GetFormatIndex());
|
e.SetInt(mAudioTime->GetFormatIndex());
|
||||||
OnUpdate(e);
|
OnUpdate(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The intention of this is to get the resize handle in the
|
||||||
|
// correct position, after we've let go in dragging.
|
||||||
|
void TimerToolBar::ResizingDone()
|
||||||
|
{
|
||||||
|
// Fit() while retaining height
|
||||||
|
SetSize(GetBestSize().x, GetSize().y);
|
||||||
|
|
||||||
|
// Inform others the toobar has changed
|
||||||
|
Updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerToolBar::SetResizingLimits()
|
||||||
|
{
|
||||||
|
// Reset limits
|
||||||
|
SetMinSize(wxDefaultSize);
|
||||||
|
SetMaxSize(wxDefaultSize);
|
||||||
|
|
||||||
|
// If docked we use the current bar height since it's always a single or double height
|
||||||
|
// toolbar. For floaters, single height toolbar is the minimum height.
|
||||||
|
int minH = IsDocked() ? GetSize().y : toolbarSingle;
|
||||||
|
|
||||||
|
// Get the content size given the smallest digit height we allow
|
||||||
|
wxSize minSize = ComputeSizing(17);
|
||||||
|
|
||||||
|
// Account for any borders added by the window manager
|
||||||
|
minSize.x += (mAudioTime->GetSize().x - mAudioTime->GetClientSize().x);
|
||||||
|
|
||||||
|
// Calculate the space used by other controls and sizer borders with this toolbar
|
||||||
|
wxSize outer = (GetSize() - GetSizer()->GetSize());
|
||||||
|
|
||||||
|
// And account for them in the width
|
||||||
|
minSize.x += outer.x;
|
||||||
|
|
||||||
|
// Override the height
|
||||||
|
minSize.y = minH;
|
||||||
|
|
||||||
|
// Get the maximum digit height we can use. This is restricted to the toolbar's
|
||||||
|
// current height minus any control borders
|
||||||
|
int digH = minH - (mAudioTime->GetSize().y - mAudioTime->GetClientSize().y);
|
||||||
|
|
||||||
|
// Get the content size using the digit height, if docked. Otherwise use the
|
||||||
|
// maximum digit height we allow.
|
||||||
|
wxSize maxSize = ComputeSizing(IsDocked() ? digH : 100);
|
||||||
|
|
||||||
|
// Account for the other controls and sizer borders within this toolbar
|
||||||
|
maxSize.x += outer.x;
|
||||||
|
|
||||||
|
// Account for any borders added by the window manager and +1 to keep toolbar
|
||||||
|
// from dropping to next smaller size when grabbing the resizer.
|
||||||
|
maxSize.x += (mAudioTime->GetSize().x - mAudioTime->GetClientSize().x) + 1;
|
||||||
|
|
||||||
|
// Override the height
|
||||||
|
maxSize.y = IsDocked() ? minH : wxDefaultCoord;
|
||||||
|
|
||||||
|
// And finally set them both
|
||||||
|
SetMinSize(minSize);
|
||||||
|
SetMaxSize(maxSize);
|
||||||
|
}
|
||||||
|
|
||||||
// Called when the format drop downs is changed.
|
// Called when the format drop downs is changed.
|
||||||
// This causes recreation of the toolbar contents.
|
// This causes recreation of the toolbar contents.
|
||||||
void TimerToolBar::OnUpdate(wxCommandEvent &evt)
|
void TimerToolBar::OnUpdate(wxCommandEvent &evt)
|
||||||
{
|
{
|
||||||
//wxLogDebug("OnUpdate");
|
|
||||||
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;
|
|
||||||
mDigitHeight = wxMin(mDigitHeight, 25);
|
|
||||||
}
|
|
||||||
|
|
||||||
evt.Skip(false);
|
evt.Skip(false);
|
||||||
|
|
||||||
|
// Reset to allow resizing to work
|
||||||
|
SetMinSize(wxDefaultSize);
|
||||||
|
SetMaxSize(wxDefaultSize);
|
||||||
|
|
||||||
// Save format name before recreating the controls so they resize properly
|
// Save format name before recreating the controls so they resize properly
|
||||||
{
|
if (mListener) {
|
||||||
auto format = mAudioTime->GetBuiltinName(index);
|
mListener->TT_SetAudioTimeFormat(mAudioTime->GetBuiltinName(evt.GetInt()));
|
||||||
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()));
|
|
||||||
|
|
||||||
|
// Go set the new size limits
|
||||||
SetResizingLimits();
|
SetResizingLimits();
|
||||||
|
|
||||||
if( bHasFocus )
|
// Fit() while retaining height
|
||||||
mAudioTime->SetFocus();
|
SetSize(GetBestSize().x, GetSize().y);
|
||||||
|
|
||||||
|
// Inform others the toobar has changed
|
||||||
Updated();
|
Updated();
|
||||||
mbPreserveHeight = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerToolBar::SetDocked(ToolDock *dock, bool pushed)
|
void TimerToolBar::OnSize(wxSizeEvent &evt)
|
||||||
{
|
{
|
||||||
//wxLogDebug("SetDocked");
|
evt.Skip();
|
||||||
ToolBar::SetDocked(dock, pushed);
|
|
||||||
if (!mbReady)
|
// Can fire before we're ready
|
||||||
|
if (!mAudioTime) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Do not use IsDocked() here. It's not valid!
|
|
||||||
if ( dock == nullptr) {
|
|
||||||
// The min height when undocked is always 22
|
|
||||||
wxSize sz = GetMinSize();
|
|
||||||
sz.y = 22;
|
|
||||||
SetMinSize(sz);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//SetResizingLimits();
|
|
||||||
ResizingDone();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// Make sure everything is where it's supposed to be
|
||||||
|
Layout();
|
||||||
|
|
||||||
void TimerToolBar::SetToDefaultSize(){
|
// Get the sizer's size and remove any borders the time control might have.
|
||||||
wxSize sz;
|
wxSize sizerBR = GetSizer()->GetSize() - (mAudioTime->GetSize() - mAudioTime->GetClientSize());
|
||||||
sz.SetHeight( 48 );
|
|
||||||
sz.SetWidth( GetInitialWidth());
|
|
||||||
SetSize( sz );
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerToolBar::SetResizingLimits() {
|
// Get the content size of the time control. This can be different than the
|
||||||
|
// control itself due to borders and sizer enduced changes.
|
||||||
|
wxSize timeBR = mAudioTime->GetDimensions();
|
||||||
|
|
||||||
//wxLogDebug("Set Resizing Limits");
|
// Get the current digit box height
|
||||||
if (!IsDocked()) {
|
int h = mAudioTime->GetDigitSize().y;
|
||||||
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 39 pixels.
|
// Increase current size to find the best fit within the new size
|
||||||
// And was not accounted for in the Fit().
|
if (sizerBR.x > timeBR.x && sizerBR.y > timeBR.y) {
|
||||||
wxSize sz = pFrame->GetSize();
|
do {
|
||||||
sz.x += 39;
|
h++;
|
||||||
sz.y += 2;
|
timeBR = ComputeSizing(h);
|
||||||
pFrame->SetSize(sz);
|
} while (h < 150 && sizerBR.x > timeBR.x && sizerBR.y > timeBR.y);
|
||||||
// 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(); // Toolbar size to fit around minimum sizer.
|
|
||||||
Layout();
|
|
||||||
//GetSizer()->RecalcSizes();
|
|
||||||
wxSize sz1 = GetSizer()->GetMinSize();
|
|
||||||
int minHeight = 21;
|
|
||||||
if (sz1.y > minHeight) {
|
|
||||||
sz1.x = (sz1.x * minHeight) / sz1.y;
|
|
||||||
GetSizer()->SetMinSize(sz1);
|
|
||||||
SetMinSize(sz1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are given the size of the toolbar.
|
|
||||||
// Compute digit Height and layout the Numeric Control.
|
|
||||||
void TimerToolBar::ResizeTime( const wxSize & sz) {
|
|
||||||
|
|
||||||
int mx = sz.GetWidth() - 25;
|
|
||||||
int my = sz.GetHeight();
|
|
||||||
//wxLogDebug("ResizeTime %i,%i",mx,my);
|
|
||||||
|
|
||||||
// Digit height is 2 less than y
|
|
||||||
// OR fits to width, if width is a bit low.
|
|
||||||
int h = my-2;
|
|
||||||
h = wxMax(17, h);
|
|
||||||
h = wxMin(h, 77);
|
|
||||||
|
|
||||||
//wxLogDebug("Try h=%i dimensions(%i,%i)", h,mx,my);
|
|
||||||
h++;
|
|
||||||
do {
|
|
||||||
h--;
|
h--;
|
||||||
mAudioTime->SetDigitSize(h*0.66, h);
|
}
|
||||||
} while ((h > 17) && mAudioTime->IsTooBig(mx, my));
|
// In all other cases, we need to decrease current size to fit within new size
|
||||||
mAudioTime->Layout();
|
else if (sizerBR.x < timeBR.x || sizerBR.y < timeBR.y) {
|
||||||
//wxLogDebug(" accept height:%i", h);
|
do {
|
||||||
|
h--;
|
||||||
mDigitHeight = h;
|
timeBR = ComputeSizing(h);
|
||||||
}
|
} while (h > 8 && (sizerBR.x < timeBR.x || sizerBR.y < timeBR.y));
|
||||||
|
|
||||||
// This 'OnSize' function is also called during moving the
|
|
||||||
// toolbar.
|
|
||||||
void TimerToolBar::OnSize(wxSizeEvent & ev)
|
|
||||||
{
|
|
||||||
//wxLogDebug("OnSize");
|
|
||||||
if (!mbReady)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ev.Skip();
|
|
||||||
|
|
||||||
if (!mAudioTime)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If we are changing the time format, then we
|
|
||||||
// preserve the height. Otherwise we size the font to fit
|
|
||||||
// the space given.
|
|
||||||
if (mbPreserveWidth || !mbPreserveHeight) {
|
|
||||||
ResizeTime( ev.GetSize() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh and update immediately, so that we don't get
|
if (h != mAudioTime->GetDigitSize().y) {
|
||||||
// to see grot from partly redrawn toolbar during
|
mAudioTime->SetDigitSize(h * mDigitRatio, h);
|
||||||
// the resizing.
|
}
|
||||||
Refresh(true);
|
|
||||||
|
// Redraw the display immediately to smooth out resizing
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The intention of this is to get the resize handle in the
|
void TimerToolBar::OnIdle(wxIdleEvent &evt)
|
||||||
// correct position, after we've let go in dragging.
|
|
||||||
void TimerToolBar::ResizingDone() {
|
|
||||||
if (!mbReady)
|
|
||||||
return;
|
|
||||||
wxSize sz = GetSize();
|
|
||||||
//wxLogDebug("ReSizingDone %i,%i",sz.x,sz.y);
|
|
||||||
|
|
||||||
Fit();
|
|
||||||
sz.x = GetSize().GetX();
|
|
||||||
//wxLogDebug("Fitted %i,%i",sz.x,sz.y);
|
|
||||||
SetSize(sz);
|
|
||||||
Updated();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TimerToolBar::SetTimes(double audio)
|
|
||||||
{
|
|
||||||
mAudioTime->SetValue(wxMax( 0.0, audio));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerToolBar::OnFocus(wxFocusEvent &event)
|
|
||||||
{
|
|
||||||
KeyboardCapture::OnFocus(*this, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerToolBar::OnCaptureKey(wxCommandEvent &event)
|
|
||||||
{
|
|
||||||
wxKeyEvent *kevent = (wxKeyEvent *)event.GetEventObject();
|
|
||||||
wxWindow *w = FindFocus();
|
|
||||||
int keyCode = kevent->GetKeyCode();
|
|
||||||
|
|
||||||
// Convert numeric keypad entries.
|
|
||||||
if ((keyCode >= WXK_NUMPAD0) && (keyCode <= WXK_NUMPAD9)) {
|
|
||||||
keyCode -= WXK_NUMPAD0 - '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyCode >= '0' && keyCode <= '9') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.Skip();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerToolBar::OnIdle( wxIdleEvent &evt )
|
|
||||||
{
|
{
|
||||||
evt.Skip();
|
evt.Skip();
|
||||||
auto &project = mProject;
|
|
||||||
|
|
||||||
double audioTime;
|
double audioTime;
|
||||||
|
|
||||||
auto &projectAudioIO = ProjectAudioIO::Get( project );
|
auto &projectAudioIO = ProjectAudioIO::Get(mProject);
|
||||||
if ( projectAudioIO.IsAudioActive() ){
|
if (projectAudioIO.IsAudioActive()) {
|
||||||
auto gAudioIO = AudioIOBase::Get();
|
auto gAudioIO = AudioIOBase::Get();
|
||||||
audioTime = gAudioIO->GetStreamTime();
|
audioTime = gAudioIO->GetStreamTime();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const auto &playRegion = ViewInfo::Get( project ).playRegion;
|
const auto &playRegion = ViewInfo::Get(mProject).playRegion;
|
||||||
audioTime = playRegion.GetStart();
|
audioTime = playRegion.GetStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetTimes( audioTime);
|
mAudioTime->SetValue(wxMax(0.0, audioTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisteredToolbarFactory factory{ TimeBarID,
|
static RegisteredToolbarFactory factory
|
||||||
[]( AudacityProject &project ){
|
{
|
||||||
return ToolBar::Holder{ safenew TimerToolBar{ project } }; }
|
TimeBarID,
|
||||||
|
[]( AudacityProject &project )
|
||||||
|
{
|
||||||
|
return ToolBar::Holder{ safenew TimerToolBar{ project } };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_TIMER_TOOLBAR
|
|
||||||
namespace {
|
namespace {
|
||||||
AttachedToolBarMenuItem sAttachment{
|
AttachedToolBarMenuItem sAttachment
|
||||||
|
{
|
||||||
|
TimeBarID,
|
||||||
|
wxT("ShowTimeTB"),
|
||||||
/* i18n-hint: Clicking this menu item shows the toolbar
|
/* i18n-hint: Clicking this menu item shows the toolbar
|
||||||
for viewing actual time of the cursor */
|
for viewing actual time of the cursor */
|
||||||
TimeBarID, wxT("ShowTimeTB"), XXO("&Time Toolbar"),
|
XXO("&Time Toolbar"),
|
||||||
{ Registry::OrderingHint::After, "ShowSelectionTB" }
|
{
|
||||||
|
Registry::OrderingHint::After,
|
||||||
|
"ShowSelectionTB"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -2,26 +2,25 @@
|
|||||||
|
|
||||||
Audacity: A Digital Audio Editor
|
Audacity: A Digital Audio Editor
|
||||||
|
|
||||||
TimerToolBar.h
|
TimeToolBar.h
|
||||||
|
|
||||||
Jonatã Bolzan Loss
|
Jonatã Bolzan Loss
|
||||||
|
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#ifndef __AUDACITY_BIG_COUNTER__
|
#ifndef __AUDACITY_TIME_TOOLBAR__
|
||||||
#define __AUDACITY_BIG_COUNTER__
|
#define __AUDACITY_TIME_TOOLBAR__
|
||||||
|
|
||||||
#include <wx/defs.h>
|
#include <wx/defs.h>
|
||||||
|
|
||||||
#include "ToolBar.h"
|
#include "ToolBar.h"
|
||||||
#include "ToolManager.h"
|
#include "../widgets/NumericTextCtrl.h"
|
||||||
|
|
||||||
class SelectionBarListener;
|
|
||||||
class NumericTextCtrl;
|
class NumericTextCtrl;
|
||||||
class wxSize;
|
class TimerToolBarListener;
|
||||||
|
|
||||||
class TimerToolBar final : public ToolBar {
|
class TimerToolBar final : public ToolBar
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
TimerToolBar(AudacityProject &project);
|
TimerToolBar(AudacityProject &project);
|
||||||
virtual ~TimerToolBar();
|
virtual ~TimerToolBar();
|
||||||
@ -29,56 +28,41 @@ public:
|
|||||||
static TimerToolBar &Get(AudacityProject &project);
|
static TimerToolBar &Get(AudacityProject &project);
|
||||||
static const TimerToolBar &Get(const AudacityProject &project);
|
static const TimerToolBar &Get(const AudacityProject &project);
|
||||||
|
|
||||||
void Create(wxWindow *parent) override;
|
|
||||||
|
|
||||||
void Populate() override;
|
void Populate() override;
|
||||||
void Repaint(wxDC * WXUNUSED(dc)) override {};
|
void Repaint(wxDC * WXUNUSED(dc)) override {};
|
||||||
void EnableDisableButtons() override {};
|
void EnableDisableButtons() override {};
|
||||||
void UpdatePrefs() override;
|
void UpdatePrefs() override;
|
||||||
void OnUpdate(wxCommandEvent &evt);
|
void RegenerateTooltips() override {};
|
||||||
void SetTimes(double audio);
|
int GetInitialWidth() override {return 250;}
|
||||||
|
int GetMinToolbarWidth() override {return 50;}
|
||||||
|
void SetToDefaultSize() override;
|
||||||
|
wxSize GetDockedSize() override;
|
||||||
|
void SetDocked(ToolDock *dock, bool pushed) override;
|
||||||
void SetListener(TimerToolBarListener *l);
|
void SetListener(TimerToolBarListener *l);
|
||||||
void SetAudioTimeFormat(const NumericFormatSymbol & format);
|
void SetAudioTimeFormat(const NumericFormatSymbol & format);
|
||||||
void RegenerateTooltips() override {};
|
|
||||||
|
|
||||||
int GetInitialWidth() override {return 250;}
|
|
||||||
int GetMinToolbarWidth() override { return mMinWidth; }
|
|
||||||
void SetToDefaultSize() override;
|
|
||||||
wxSize GetDockedSize() override {
|
|
||||||
return GetSmartDockedSize();
|
|
||||||
};
|
|
||||||
void SetDocked(ToolDock *dock, bool pushed) override;
|
|
||||||
void ResizeTime( const wxSize & sz );
|
|
||||||
void SetResizingLimits();
|
|
||||||
void ResizingDone() override;
|
void ResizingDone() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NumericTextCtrl * AddTime( const TranslatableString &Name, int id,
|
void SetResizingLimits();
|
||||||
wxSizer * pSizer);
|
wxSize ComputeSizing(int digitH);
|
||||||
|
|
||||||
void OnFocus(wxFocusEvent &event);
|
void OnUpdate(wxCommandEvent &evt);
|
||||||
void OnCaptureKey(wxCommandEvent &event);
|
|
||||||
void OnSize(wxSizeEvent &evt);
|
void OnSize(wxSizeEvent &evt);
|
||||||
void OnIdle( wxIdleEvent &evt );
|
void OnIdle(wxIdleEvent &evt);
|
||||||
|
|
||||||
TimerToolBarListener * mListener;
|
TimerToolBarListener *mListener;
|
||||||
double mRate;
|
NumericTextCtrl *mAudioTime;
|
||||||
double mAudio;
|
float mDigitRatio;
|
||||||
int mMinWidth;
|
|
||||||
int mDigitHeight;
|
|
||||||
bool mbReady;
|
|
||||||
bool mbIsCreating;
|
|
||||||
bool mbPreserveWidth;
|
|
||||||
bool mbPreserveHeight;
|
|
||||||
|
|
||||||
NumericTextCtrl *mAudioTime;
|
|
||||||
wxChoice *mSnapTo;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DECLARE_CLASS(TimerToolBar)
|
DECLARE_CLASS(TimerToolBar)
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline wxSize TimerToolBar::ComputeSizing(int digitH)
|
||||||
|
{
|
||||||
|
return mAudioTime->ComputeSizing(false, digitH * mDigitRatio, digitH);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -228,17 +228,31 @@ void ToolBarResizer::OnMotion( wxMouseEvent & event )
|
|||||||
wxPoint pos = wxGetMousePosition();
|
wxPoint pos = wxGetMousePosition();
|
||||||
|
|
||||||
wxRect r = mBar->GetRect();
|
wxRect r = mBar->GetRect();
|
||||||
wxSize msz = mBar->GetMinSize();
|
wxSize minsz = mBar->GetMinSize();
|
||||||
|
wxSize maxsz = mBar->GetMaxSize();
|
||||||
wxSize psz = mBar->GetParent()->GetClientSize();
|
wxSize psz = mBar->GetParent()->GetClientSize();
|
||||||
|
|
||||||
// Adjust the size based on updated mouse position.
|
// Adjust the size based on updated mouse position.
|
||||||
r.width = ( pos.x - mResizeOffset.x ) - r.x;
|
r.width = ( pos.x - mResizeOffset.x ) - r.x;
|
||||||
|
|
||||||
|
// Keep it within max size, if specificed
|
||||||
|
if( maxsz != wxDefaultSize )
|
||||||
|
{
|
||||||
|
if( r.width > maxsz.x )
|
||||||
|
{
|
||||||
|
r.width = maxsz.x;
|
||||||
|
}
|
||||||
|
if( r.height > maxsz.y )
|
||||||
|
{
|
||||||
|
r.height = maxsz.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Constrain
|
// Constrain
|
||||||
if( r.width < msz.x )
|
if( r.width < minsz.x )
|
||||||
{
|
{
|
||||||
// Don't allow resizing to go too small
|
// Don't allow resizing to go too small
|
||||||
r.width = msz.x;
|
r.width = minsz.x;
|
||||||
}
|
}
|
||||||
else if( r.GetRight() > psz.x - 3 )
|
else if( r.GetRight() > psz.x - 3 )
|
||||||
{
|
{
|
||||||
@ -538,6 +552,7 @@ void ToolBar::ReCreateButtons()
|
|||||||
// Set dock after possibly creating resizer.
|
// Set dock after possibly creating resizer.
|
||||||
// (Re)Establish dock state
|
// (Re)Establish dock state
|
||||||
SetDocked(GetDock(), false);
|
SetDocked(GetDock(), false);
|
||||||
|
|
||||||
// Set the sizer
|
// Set the sizer
|
||||||
SetSizerAndFit(ms.release());
|
SetSizerAndFit(ms.release());
|
||||||
}
|
}
|
||||||
|
@ -231,6 +231,21 @@ void ToolFrame::OnMotion( wxMouseEvent & event )
|
|||||||
wxRect rect = GetRect();
|
wxRect rect = GetRect();
|
||||||
|
|
||||||
rect.SetBottomRight( pos );
|
rect.SetBottomRight( pos );
|
||||||
|
|
||||||
|
// Keep it within max size, if specificed
|
||||||
|
wxSize maxsz = mBar->GetMaxSize();
|
||||||
|
if (maxsz != wxDefaultSize)
|
||||||
|
{
|
||||||
|
if (maxsz.x != wxDefaultCoord && rect.width > maxsz.x)
|
||||||
|
{
|
||||||
|
rect.width = maxsz.x;
|
||||||
|
}
|
||||||
|
if (maxsz.y != wxDefaultCoord && rect.height > maxsz.y)
|
||||||
|
{
|
||||||
|
rect.height = maxsz.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( rect.width < mMinSize.x )
|
if( rect.width < mMinSize.x )
|
||||||
{
|
{
|
||||||
rect.width = mMinSize.x;
|
rect.width = mMinSize.x;
|
||||||
|
@ -1318,12 +1318,17 @@ NumericTextCtrl::NumericTextCtrl(wxWindow *parent, wxWindowID id,
|
|||||||
{
|
{
|
||||||
mAllowInvalidValue = false;
|
mAllowInvalidValue = false;
|
||||||
|
|
||||||
mDigitBoxW = 10;
|
mDigitBoxW = 11;
|
||||||
mDigitBoxH = 16;
|
mDigitBoxH = 19;
|
||||||
|
|
||||||
|
mBorderLeft = 1;
|
||||||
|
mBorderTop = 1;
|
||||||
|
mBorderRight = 1;
|
||||||
|
mBorderBottom = 1;
|
||||||
|
|
||||||
mReadOnly = options.readOnly;
|
mReadOnly = options.readOnly;
|
||||||
mMenuEnabled = options.menuEnabled;
|
mMenuEnabled = options.menuEnabled;
|
||||||
mButtonWidth = 9;
|
mButtonWidth = mMenuEnabled ? 9 : 0;
|
||||||
|
|
||||||
SetLayoutDirection(wxLayout_LeftToRight);
|
SetLayoutDirection(wxLayout_LeftToRight);
|
||||||
Layout();
|
Layout();
|
||||||
@ -1458,78 +1463,119 @@ void NumericTextCtrl::SetInvalidValue(double invalidValue)
|
|||||||
SetValue(invalidValue);
|
SetValue(invalidValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxSize NumericTextCtrl::ComputeSizing(bool update, wxCoord boxW, wxCoord boxH)
|
||||||
void NumericTextCtrl::ComputeSizing()
|
|
||||||
{
|
{
|
||||||
unsigned int i, j;
|
// Get current box size
|
||||||
int x, pos;
|
if (boxW == 0) {
|
||||||
|
boxW = mDigitBoxW;
|
||||||
|
}
|
||||||
|
|
||||||
wxMemoryDC memDC;
|
if (boxH == 0) {
|
||||||
|
boxH = mDigitBoxH;
|
||||||
|
}
|
||||||
|
boxH -= (mBorderTop + mBorderBottom);
|
||||||
|
|
||||||
// Placeholder bitmap so the memDC has something to reference
|
// We can use the screen device context since we're not drawing to it
|
||||||
mBackgroundBitmap = std::make_unique<wxBitmap>(1, 1, 24);
|
wxScreenDC dc;
|
||||||
memDC.SelectObject(*mBackgroundBitmap);
|
|
||||||
|
|
||||||
mDigits.clear();
|
// First calculate a rough point size
|
||||||
|
wxFont pf(wxSize(boxW, boxH), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||||
|
int fontSize = pf.GetPointSize();
|
||||||
|
wxCoord strW;
|
||||||
|
wxCoord strH;
|
||||||
|
|
||||||
mBorderLeft = 1;
|
// Now decrease it until we fit within our digit box
|
||||||
mBorderTop = 1;
|
dc.SetFont(pf);
|
||||||
mBorderRight = 1;
|
dc.GetTextExtent(wxT("0"), &strW, &strH);
|
||||||
mBorderBottom = 1;
|
while (strW > boxW || strH > boxH) {
|
||||||
|
dc.SetFont(wxFont(--fontSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
|
||||||
int fontSize = 4;
|
dc.GetTextExtent(wxT("0"), &strW, &strH);
|
||||||
wxCoord strW, strH;
|
|
||||||
wxString exampleText = wxT("0");
|
|
||||||
|
|
||||||
// Keep making the font bigger until it's too big, then subtract one.
|
|
||||||
memDC.SetFont(wxFont(fontSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
|
|
||||||
memDC.GetTextExtent(exampleText, &strW, &strH);
|
|
||||||
while (strW <= mDigitBoxW && strH <= mDigitBoxH) {
|
|
||||||
fontSize++;
|
|
||||||
memDC.SetFont(wxFont(fontSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
|
|
||||||
memDC.GetTextExtent(exampleText, &strW, &strH);
|
|
||||||
}
|
}
|
||||||
fontSize--;
|
fontSize--;
|
||||||
|
|
||||||
mDigitFont = std::make_unique<wxFont>(fontSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
// Create the digit font with the new point size
|
||||||
memDC.SetFont(*mDigitFont);
|
if (update) {
|
||||||
memDC.GetTextExtent(exampleText, &strW, &strH);
|
mDigitFont = std::make_unique<wxFont>(fontSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||||
mDigitW = strW;
|
dc.SetFont(*mDigitFont);
|
||||||
mDigitH = strH;
|
|
||||||
|
// Remember the actual digit width and height using the new font
|
||||||
|
dc.GetTextExtent(wxT("0"), &mDigitW, &mDigitH);
|
||||||
|
}
|
||||||
|
|
||||||
// The label font should be a little smaller
|
// The label font should be a little smaller
|
||||||
fontSize--;
|
std::unique_ptr<wxFont> labelFont = std::make_unique<wxFont>(fontSize - 1, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||||
mLabelFont = std::make_unique<wxFont>(fontSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
|
||||||
|
|
||||||
// Figure out the x-position of each field and label in the box
|
// Use the label font for all remaining measurements since only non-digit text is left
|
||||||
x = mBorderLeft;
|
dc.SetFont(*labelFont);
|
||||||
pos = 0;
|
|
||||||
|
// Remember the pointer if updating
|
||||||
memDC.SetFont(*mLabelFont);
|
if (update) {
|
||||||
memDC.GetTextExtent(mPrefix, &strW, &strH);
|
mLabelFont = std::move(labelFont);
|
||||||
x += strW;
|
|
||||||
pos += mPrefix.length();
|
|
||||||
|
|
||||||
for(i = 0; i < mFields.size(); i++) {
|
|
||||||
mFields[i].fieldX = x;
|
|
||||||
for(j=0; j<(unsigned int)mFields[i].digits; j++) {
|
|
||||||
mDigits.push_back(DigitInfo(i, j, pos, wxRect(x, mBorderTop,
|
|
||||||
mDigitBoxW, mDigitBoxH)));
|
|
||||||
x += mDigitBoxW;
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
mFields[i].labelX = x;
|
|
||||||
memDC.GetTextExtent(mFields[i].label, &strW, &strH);
|
|
||||||
pos += mFields[i].label.length();
|
|
||||||
x += strW;
|
|
||||||
mFields[i].fieldW = x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mWidth = x + mBorderRight;
|
// Get the width of the prefix, if any
|
||||||
mHeight = mDigitBoxH + mBorderTop + mBorderBottom;
|
dc.GetTextExtent(mPrefix, &strW, &strH);
|
||||||
}
|
|
||||||
|
|
||||||
|
// Bump x-position to the end of the prefix
|
||||||
|
int x = mBorderLeft + strW;
|
||||||
|
|
||||||
|
if (update) {
|
||||||
|
// Set the character position past the prefix
|
||||||
|
int pos = mPrefix.length();
|
||||||
|
|
||||||
|
// Reset digits array
|
||||||
|
mDigits.clear();
|
||||||
|
|
||||||
|
// Figure out the x-position of each field and label in the box
|
||||||
|
for (int i = 0, fcnt = mFields.size(); i < fcnt; ++i) {
|
||||||
|
// Get the size of the label
|
||||||
|
dc.GetTextExtent(mFields[i].label, &strW, &strH);
|
||||||
|
|
||||||
|
// Remember this field's x-position
|
||||||
|
mFields[i].fieldX = x;
|
||||||
|
|
||||||
|
// Remember metrics for each digit
|
||||||
|
for (int j = 0, dcnt = mFields[i].digits; j < dcnt; ++j) {
|
||||||
|
mDigits.push_back(DigitInfo(i, j, pos, wxRect(x, mBorderTop, boxW, boxH)));
|
||||||
|
x += boxW;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember the label's x-position
|
||||||
|
mFields[i].labelX = x;
|
||||||
|
|
||||||
|
// Bump to end of label
|
||||||
|
x += strW;
|
||||||
|
|
||||||
|
// Remember the label's width
|
||||||
|
mFields[i].fieldW = x;
|
||||||
|
|
||||||
|
// Bump character position to end of label
|
||||||
|
pos += mFields[i].label.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Determine the maximum x-position (length) of the remaining fields
|
||||||
|
for (int i = 0, fcnt = mFields.size(); i < fcnt; ++i) {
|
||||||
|
// Get the size of the label
|
||||||
|
dc.GetTextExtent(mFields[i].label, &strW, &strH);
|
||||||
|
|
||||||
|
// Just bump to next field
|
||||||
|
x += (boxW * mFields[i].digits) + strW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the maximum dimensions
|
||||||
|
wxSize dim(x + mBorderRight, boxH + mBorderTop + mBorderBottom);
|
||||||
|
|
||||||
|
// Save maximumFinally, calculate the minimum dimensions
|
||||||
|
if (update) {
|
||||||
|
mWidth = dim.x;
|
||||||
|
mHeight = dim.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxSize(dim.x + mButtonWidth, dim.y);
|
||||||
|
}
|
||||||
|
|
||||||
bool NumericTextCtrl::Layout()
|
bool NumericTextCtrl::Layout()
|
||||||
{
|
{
|
||||||
|
@ -192,8 +192,8 @@ class NumericTextCtrl final : public wxControl, public NumericConverter
|
|||||||
// Hide the inherited function that takes wxString
|
// Hide the inherited function that takes wxString
|
||||||
void SetName( const TranslatableString &name );
|
void SetName( const TranslatableString &name );
|
||||||
|
|
||||||
|
wxSize ComputeSizing(bool update = true, wxCoord digitW = 0, wxCoord digitH = 0);
|
||||||
bool Layout() override;
|
bool Layout() override;
|
||||||
void ComputeSizing();
|
|
||||||
void Fit() override;
|
void Fit() override;
|
||||||
|
|
||||||
void SetSampleRate(double sampleRate);
|
void SetSampleRate(double sampleRate);
|
||||||
@ -207,6 +207,8 @@ class NumericTextCtrl final : public wxControl, public NumericConverter
|
|||||||
|
|
||||||
void SetFieldFocus(int /* digit */);
|
void SetFieldFocus(int /* digit */);
|
||||||
|
|
||||||
|
wxSize GetDimensions() { return wxSize(mWidth + mButtonWidth, mHeight); }
|
||||||
|
wxSize GetDigitSize() { return wxSize(mDigitBoxW, mDigitBoxH); }
|
||||||
void SetDigitSize(int width, int height);
|
void SetDigitSize(int width, int height);
|
||||||
void SetReadOnly(bool readOnly = true);
|
void SetReadOnly(bool readOnly = true);
|
||||||
void EnableMenu(bool enable = true);
|
void EnableMenu(bool enable = true);
|
||||||
@ -219,11 +221,6 @@ class NumericTextCtrl final : public wxControl, public NumericConverter
|
|||||||
|
|
||||||
int GetFocusedField() { return mLastField; }
|
int GetFocusedField() { return mLastField; }
|
||||||
int GetFocusedDigit() { return mFocusedDigit; }
|
int GetFocusedDigit() { return mFocusedDigit; }
|
||||||
// give a sane aspect ratio even if zero height.
|
|
||||||
bool IsTooBig(int width, int height) {
|
|
||||||
ComputeSizing();
|
|
||||||
return (mWidth > width) || (mHeight > height);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user