mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-02 16:49:41 +02:00
Toggle buttons on ruler for scrub and seek; redo scrub menu items...
Two toggle buttons for three states (the state with both down is disallowed). Scrub, seek, or hidden scrub bar (but that still allows scrub via menu item). Also yet another button image for transport play, while seeking. Also change the appearance of the scrub handle in the ruler, for seeking.
This commit is contained in:
commit
6388ae3aa0
@ -69,6 +69,8 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
DEFINE_IMAGE( bmpAppendRecordDisabled, wxImage( 16, 16 ), wxT("AppendRecordDisabled"));
|
||||
DEFINE_IMAGE( bmpScrubDisabled, wxImage( 16, 16 ), wxT("ScrubDisabled"));
|
||||
DEFINE_IMAGE( bmpScrub, wxImage( 16, 16 ), wxT("Scrub"));
|
||||
DEFINE_IMAGE( bmpSeekDisabled, wxImage( 24, 16 ), wxT("SeekDisabled"));
|
||||
DEFINE_IMAGE( bmpSeek, wxImage( 24, 16 ), wxT("Seek"));
|
||||
|
||||
SET_THEME_FLAGS( resFlagNewLine );
|
||||
DEFINE_IMAGE( bmpUpButtonLarge, wxImage( 48, 48 ), wxT("UpButtonLarge"));
|
||||
|
@ -2384,7 +2384,6 @@ void AudacityProject::OnTogglePinnedHead()
|
||||
auto ruler = GetRulerPanel();
|
||||
if (ruler)
|
||||
// Update button image
|
||||
|
||||
ruler->UpdateButtonStates();
|
||||
|
||||
auto &scrubber = GetScrubber();
|
||||
|
@ -890,7 +890,7 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
|
||||
mRuler = safenew AdornedRulerPanel( this,
|
||||
wxID_ANY,
|
||||
wxDefaultPosition,
|
||||
wxSize( -1, AdornedRulerPanel::GetRulerHeight() ),
|
||||
wxSize( -1, AdornedRulerPanel::GetRulerHeight(false) ),
|
||||
&mViewInfo );
|
||||
|
||||
//
|
||||
|
8576
src/ThemeAsCeeCode.h
8576
src/ThemeAsCeeCode.h
File diff suppressed because it is too large
Load Diff
@ -168,6 +168,8 @@ void ControlToolBar::Populate()
|
||||
bmpCutPreview, bmpCutPreview, bmpCutPreviewDisabled);
|
||||
MakeAlternateImages(*mPlay, 3,
|
||||
bmpScrub, bmpScrub, bmpScrubDisabled);
|
||||
MakeAlternateImages(*mPlay, 4,
|
||||
bmpSeek, bmpSeek, bmpSeekDisabled);
|
||||
mPlay->FollowModifierKeys();
|
||||
|
||||
mStop = MakeButton( bmpStop, bmpStop, bmpStopDisabled ,
|
||||
|
@ -62,7 +62,7 @@ class ControlToolBar final : public ToolBar {
|
||||
|
||||
// Choice among the appearances of the play button:
|
||||
enum class PlayAppearance {
|
||||
Straight, Looped, CutPreview, Scrub
|
||||
Straight, Looped, CutPreview, Scrub, Seek
|
||||
};
|
||||
|
||||
//These allow buttons to be controlled externally:
|
||||
|
@ -99,7 +99,7 @@ void PlayIndicatorOverlayBase::Draw(OverlayPanel &panel, wxDC &dc)
|
||||
else if(auto ruler = dynamic_cast<AdornedRulerPanel*>(&panel)) {
|
||||
wxASSERT(!mIsMaster);
|
||||
|
||||
ruler->DoDrawIndicator(&dc, mLastIndicatorX, !rec, IndicatorMediumWidth, false);
|
||||
ruler->DoDrawIndicator(&dc, mLastIndicatorX, !rec, IndicatorMediumWidth, false, false);
|
||||
}
|
||||
else
|
||||
wxASSERT(false);
|
||||
|
@ -33,9 +33,6 @@ Paul Licameli split from TrackPanel.cpp
|
||||
|
||||
#include <wx/dc.h>
|
||||
|
||||
// Conditional compilation switch for making scrub menu items checkable
|
||||
#define CHECKABLE_SCRUB_MENU_ITEMS
|
||||
|
||||
enum {
|
||||
// PRL:
|
||||
// Mouse must move at least this far to distinguish ctrl-drag to scrub
|
||||
@ -221,24 +218,27 @@ namespace {
|
||||
wxString status;
|
||||
void (Scrubber::*memFn)(wxCommandEvent&);
|
||||
bool seek;
|
||||
bool (Scrubber::*StatusTest)() const;
|
||||
|
||||
const wxString &GetStatus() const { return status; }
|
||||
} menuItems[] = {
|
||||
/* i18n-hint: These commands assist the user in finding a sound by ear. ...
|
||||
"Scrubbing" is variable-speed playback, ...
|
||||
"Seeking" is normal speed playback but with skips, ...
|
||||
"Scrolling" keeps the playback position at a fixed place on screen while the waveform moves
|
||||
*/
|
||||
{ wxT("Scrub"), XO("&Scrub"), XO("Scrubbing"),
|
||||
&Scrubber::OnScrub, false },
|
||||
&Scrubber::OnScrub, false, &Scrubber::Scrubs },
|
||||
|
||||
{ wxT("Seek"), XO("See&k"), XO("Seeking"),
|
||||
&Scrubber::OnSeek, true },
|
||||
&Scrubber::OnSeek, true, &Scrubber::Seeks },
|
||||
|
||||
{ wxT("StartScrubSeek"), XO("Star&t"), XO(""),
|
||||
&Scrubber::OnStart, true, nullptr },
|
||||
};
|
||||
|
||||
enum { nMenuItems = sizeof(menuItems) / sizeof(*menuItems) };
|
||||
enum { nMenuItems = sizeof(menuItems) / sizeof(*menuItems), StartMenuItem = 2 };
|
||||
|
||||
// This never finds the last item:
|
||||
inline const MenuItem &FindMenuItem(bool seek)
|
||||
{
|
||||
return *std::find_if(menuItems, menuItems + nMenuItems,
|
||||
@ -252,16 +252,13 @@ namespace {
|
||||
|
||||
void Scrubber::MarkScrubStart(
|
||||
// Assume xx is relative to the left edge of TrackPanel!
|
||||
wxCoord xx, bool smoothScrolling, bool alwaysSeeking
|
||||
wxCoord xx, bool smoothScrolling
|
||||
)
|
||||
{
|
||||
UncheckAllMenuItems();
|
||||
|
||||
// Don't actually start scrubbing, but collect some information
|
||||
// needed for the decision to start scrubbing later when handling
|
||||
// drag events.
|
||||
mSmoothScrollingScrub = smoothScrolling;
|
||||
mAlwaysSeeking = alwaysSeeking;
|
||||
|
||||
ControlToolBar * const ctb = mProject->GetControlToolBar();
|
||||
|
||||
@ -272,14 +269,14 @@ void Scrubber::MarkScrubStart(
|
||||
// scrubber state
|
||||
mProject->SetAudioIOToken(0);
|
||||
|
||||
ctb->SetPlay(true, ControlToolBar::PlayAppearance::Scrub);
|
||||
ctb->SetPlay(true, mSeeking
|
||||
? ControlToolBar::PlayAppearance::Seek
|
||||
: ControlToolBar::PlayAppearance::Scrub);
|
||||
|
||||
ctb->UpdateStatusBar(mProject);
|
||||
|
||||
mScrubStartPosition = xx;
|
||||
mOptions.startClockTimeMillis = ::wxGetLocalTimeMillis();
|
||||
|
||||
CheckMenuItem();
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
|
||||
@ -354,8 +351,9 @@ bool Scrubber::MaybeStartScrubbing(wxCoord xx)
|
||||
mOptions.minStutter =
|
||||
mDragging ? 0.0 : lrint(std::max(0.0, MinStutter) * options.rate);
|
||||
|
||||
ControlToolBar::PlayAppearance appearance =
|
||||
ControlToolBar::PlayAppearance::Scrub;
|
||||
ControlToolBar::PlayAppearance appearance = mSeeking
|
||||
? ControlToolBar::PlayAppearance::Seek
|
||||
: ControlToolBar::PlayAppearance::Scrub;
|
||||
const bool cutPreview = false;
|
||||
const bool backwards = time1 < time0;
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||
@ -468,12 +466,12 @@ void Scrubber::ContinueScrubbingUI()
|
||||
|
||||
{
|
||||
// Show the correct status for seeking.
|
||||
bool backup = mAlwaysSeeking;
|
||||
mAlwaysSeeking = seek;
|
||||
bool backup = mSeeking;
|
||||
mSeeking = seek;
|
||||
const auto ctb = mProject->GetControlToolBar();
|
||||
if (ctb)
|
||||
ctb->UpdateStatusBar(mProject);
|
||||
mAlwaysSeeking = backup;
|
||||
mSeeking = backup;
|
||||
}
|
||||
|
||||
if (seek)
|
||||
@ -498,8 +496,6 @@ void Scrubber::StopScrubbing()
|
||||
|
||||
mPoller->Stop();
|
||||
|
||||
UncheckAllMenuItems();
|
||||
|
||||
mScrubStartPosition = -1;
|
||||
mDragging = false;
|
||||
|
||||
@ -770,13 +766,12 @@ Scrubber &ScrubbingOverlay::GetScrubber()
|
||||
|
||||
bool Scrubber::PollIsSeeking()
|
||||
{
|
||||
return mDragging || (mAlwaysSeeking || ::wxGetMouseState().LeftIsDown());
|
||||
return mDragging || (mSeeking || ::wxGetMouseState().LeftIsDown());
|
||||
}
|
||||
|
||||
void Scrubber::DoScrub(bool seek)
|
||||
void Scrubber::DoScrub()
|
||||
{
|
||||
const bool wasScrubbing = IsScrubbing();
|
||||
const bool match = (seek == mAlwaysSeeking);
|
||||
const bool scroll = PlaybackPrefs::GetPinnedHeadPreference();
|
||||
if (!wasScrubbing) {
|
||||
auto tp = mProject->GetTrackPanel();
|
||||
@ -788,33 +783,43 @@ void Scrubber::DoScrub(bool seek)
|
||||
const auto offset = tp->GetLeftOffset();
|
||||
xx = (std::max(offset, std::min(offset + width - 1, xx)));
|
||||
|
||||
MarkScrubStart(xx, scroll, seek);
|
||||
MarkScrubStart(xx, scroll);
|
||||
}
|
||||
else if(!match) {
|
||||
mSmoothScrollingScrub = scroll;
|
||||
mAlwaysSeeking = seek;
|
||||
UncheckAllMenuItems();
|
||||
CheckMenuItem();
|
||||
}
|
||||
|
||||
void Scrubber::OnScrubOrSeek(bool &toToggle, bool &other)
|
||||
{
|
||||
toToggle = !toToggle;
|
||||
if (toToggle)
|
||||
other = false;
|
||||
|
||||
if (HasStartedScrubbing()) {
|
||||
// Show the correct status.
|
||||
const auto ctb = mProject->GetControlToolBar();
|
||||
ctb->UpdateStatusBar(mProject);
|
||||
}
|
||||
else {
|
||||
// This will call back to Scrubber::StopScrubbing
|
||||
const auto ctb = mProject->GetControlToolBar();
|
||||
ctb->StopPlaying();
|
||||
}
|
||||
|
||||
auto ruler = mProject->GetRulerPanel();
|
||||
if (ruler)
|
||||
// Update button images
|
||||
ruler->UpdateButtonStates();
|
||||
|
||||
CheckMenuItem();
|
||||
}
|
||||
|
||||
void Scrubber::OnScrub(wxCommandEvent&)
|
||||
{
|
||||
DoScrub(false);
|
||||
OnScrubOrSeek(mScrubbing, mSeeking);
|
||||
}
|
||||
|
||||
void Scrubber::OnSeek(wxCommandEvent&)
|
||||
{
|
||||
DoScrub(true);
|
||||
OnScrubOrSeek(mSeeking, mScrubbing);
|
||||
}
|
||||
|
||||
void Scrubber::OnStart(wxCommandEvent&)
|
||||
{
|
||||
DoScrub();
|
||||
}
|
||||
|
||||
enum { CMD_ID = 8000 };
|
||||
@ -828,14 +833,14 @@ BEGIN_EVENT_TABLE(Scrubber::Forwarder, wxEvtHandler)
|
||||
EVT_MOUSE_EVENTS(Scrubber::Forwarder::OnMouse)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
static_assert(nMenuItems == 2, "wrong number of items");
|
||||
static_assert(nMenuItems == 3, "wrong number of items");
|
||||
|
||||
const wxString &Scrubber::GetUntranslatedStateString() const
|
||||
{
|
||||
static wxString empty;
|
||||
|
||||
if (HasStartedScrubbing()) {
|
||||
auto &item = FindMenuItem(mAlwaysSeeking);
|
||||
auto &item = FindMenuItem(mSeeking);
|
||||
return item.status;
|
||||
}
|
||||
else
|
||||
@ -846,15 +851,19 @@ std::vector<wxString> Scrubber::GetAllUntranslatedStatusStrings()
|
||||
{
|
||||
using namespace std;
|
||||
vector<wxString> results;
|
||||
transform(menuItems, menuItems + nMenuItems, back_inserter(results),
|
||||
mem_fun_ref(&MenuItem::GetStatus));
|
||||
for (const auto &item : menuItems) {
|
||||
const auto &status = item.GetStatus();
|
||||
if (!status.empty())
|
||||
results.push_back(status);
|
||||
}
|
||||
return move(results);
|
||||
}
|
||||
|
||||
bool Scrubber::CanScrub() const
|
||||
{
|
||||
// Return the enabled state for the menu item that really launches the scrub or seek.
|
||||
auto cm = mProject->GetCommandManager();
|
||||
return cm->GetEnabled(menuItems[0].name);
|
||||
return cm->GetEnabled(menuItems[StartMenuItem].name);
|
||||
}
|
||||
|
||||
void Scrubber::AddMenuItems()
|
||||
@ -865,15 +874,14 @@ void Scrubber::AddMenuItems()
|
||||
|
||||
cm->BeginSubMenu(_("Scru&bbing"));
|
||||
for (const auto &item : menuItems) {
|
||||
#ifdef CHECKABLE_SCRUB_MENU_ITEMS
|
||||
cm->AddCheck(item.name, wxGetTranslation(item.label),
|
||||
FNT(Scrubber, this, item.memFn),
|
||||
false, flags, mask);
|
||||
#else
|
||||
cm->AddItem(item.name, wxGetTranslation(item.label),
|
||||
FNT(Scrubber, this, item.memFn),
|
||||
flags, mask);
|
||||
#endif
|
||||
if (!item.GetStatus().empty())
|
||||
cm->AddCheck(item.name, wxGetTranslation(item.label),
|
||||
FNT(Scrubber, this, item.memFn),
|
||||
false, flags, mask);
|
||||
else
|
||||
cm->AddItem(item.name, wxGetTranslation(item.label),
|
||||
FNT(Scrubber, this, item.memFn),
|
||||
flags, mask);
|
||||
}
|
||||
cm->EndSubMenu();
|
||||
CheckMenuItem();
|
||||
@ -885,40 +893,23 @@ void Scrubber::PopulateMenu(wxMenu &menu)
|
||||
auto cm = mProject->GetCommandManager();
|
||||
const MenuItem *checkedItem =
|
||||
HasStartedScrubbing()
|
||||
? &FindMenuItem(mAlwaysSeeking)
|
||||
? &FindMenuItem(mSeeking)
|
||||
: nullptr;
|
||||
for (const auto &item : menuItems) {
|
||||
if (cm->GetEnabled(item.name)) {
|
||||
#ifdef CHECKABLE_SCRUB_MENU_ITEMS
|
||||
menu.AppendCheckItem(id, item.label);
|
||||
if(&item == checkedItem)
|
||||
menu.FindItem(id)->Check();
|
||||
#else
|
||||
menu.Append(id, item.label);
|
||||
#endif
|
||||
}
|
||||
++id;
|
||||
}
|
||||
}
|
||||
|
||||
void Scrubber::UncheckAllMenuItems()
|
||||
{
|
||||
#ifdef CHECKABLE_SCRUB_MENU_ITEMS
|
||||
auto cm = mProject->GetCommandManager();
|
||||
for (const auto &item : menuItems)
|
||||
cm->Check(item.name, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Scrubber::CheckMenuItem()
|
||||
{
|
||||
#ifdef CHECKABLE_SCRUB_MENU_ITEMS
|
||||
if(HasStartedScrubbing()) {
|
||||
auto cm = mProject->GetCommandManager();
|
||||
auto item = FindMenuItem(mAlwaysSeeking);
|
||||
cm->Check(item.name, true);
|
||||
}
|
||||
#endif
|
||||
auto cm = mProject->GetCommandManager();
|
||||
cm->Check(menuItems[0].name, mScrubbing);
|
||||
cm->Check(menuItems[1].name, mSeeking);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -71,11 +71,7 @@ public:
|
||||
~Scrubber();
|
||||
|
||||
// Assume xx is relative to the left edge of TrackPanel!
|
||||
void MarkScrubStart(
|
||||
wxCoord xx, bool smoothScrolling,
|
||||
bool alwaysSeeking // if false, can switch seeking or scrubbing
|
||||
// by mouse button state
|
||||
);
|
||||
void MarkScrubStart(wxCoord xx, bool smoothScrolling);
|
||||
|
||||
// Returns true iff the event should be considered consumed by this:
|
||||
// Assume xx is relative to the left edge of TrackPanel!
|
||||
@ -101,8 +97,11 @@ public:
|
||||
void SetScrollScrubbing(bool value)
|
||||
{ mSmoothScrollingScrub = value; }
|
||||
|
||||
bool IsAlwaysSeeking() const
|
||||
{ return mAlwaysSeeking; }
|
||||
bool Seeks() const
|
||||
{ return mSeeking; }
|
||||
|
||||
bool Scrubs() const
|
||||
{ return mScrubbing; }
|
||||
|
||||
bool ShouldDrawScrubSpeed();
|
||||
double FindScrubSpeed(bool seeking, double time) const;
|
||||
@ -120,10 +119,13 @@ public:
|
||||
// For popup
|
||||
void PopulateMenu(wxMenu &menu);
|
||||
|
||||
void OnScrubOrSeek(bool &toToggle, bool &other);
|
||||
void OnScrub(wxCommandEvent&);
|
||||
void OnSeek(wxCommandEvent&);
|
||||
void OnStart(wxCommandEvent&);
|
||||
|
||||
// A string to put in the leftmost part of the status bar.
|
||||
// A string to put in the leftmost part of the status bar
|
||||
// when scrub or seek is in progress, or else empty.
|
||||
const wxString &GetUntranslatedStateString() const;
|
||||
|
||||
// All possible status strings.
|
||||
@ -133,9 +135,8 @@ public:
|
||||
bool IsPaused() const;
|
||||
|
||||
private:
|
||||
void DoScrub(bool seek);
|
||||
void DoScrub();
|
||||
void OnActivateOrDeactivateApp(wxActivateEvent & event);
|
||||
void UncheckAllMenuItems();
|
||||
void CheckMenuItem();
|
||||
|
||||
// I need this because I can't push the scrubber as an event handler
|
||||
@ -158,7 +159,12 @@ private:
|
||||
wxCoord mLastScrubPosition {};
|
||||
bool mScrubSeekPress;
|
||||
bool mSmoothScrollingScrub;
|
||||
bool mAlwaysSeeking {};
|
||||
|
||||
// These hold the three-way choice among click-to-scrub, click-to-seek, or disabled.
|
||||
// Not both true.
|
||||
bool mScrubbing {};
|
||||
bool mSeeking {};
|
||||
|
||||
bool mDragging {};
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||
|
@ -1791,7 +1791,7 @@ std::pair<wxRect, bool> QuickPlayRulerOverlay::DoGetRectangle(wxSize size)
|
||||
if (x >= 0) {
|
||||
// These dimensions are always sufficient, even if a little
|
||||
// excessive for the small triangle:
|
||||
const int width = IndicatorBigWidth();
|
||||
const int width = IndicatorBigWidth() * 3 / 2;
|
||||
const auto height = IndicatorHeightForWidth(width);
|
||||
|
||||
const int indsize = width / 2;
|
||||
@ -1814,12 +1814,14 @@ void QuickPlayRulerOverlay::Draw(OverlayPanel &panel, wxDC &dc)
|
||||
mOldQPIndicatorPos = mNewQPIndicatorPos;
|
||||
if (mOldQPIndicatorPos >= 0) {
|
||||
auto ruler = GetRuler();
|
||||
const auto &scrubber = mPartner.mProject->GetScrubber();
|
||||
auto scrub =
|
||||
ruler->mMouseEventState == AdornedRulerPanel::mesNone &&
|
||||
(ruler->mPrevZone == AdornedRulerPanel::StatusChoice::EnteringScrubZone ||
|
||||
(mPartner.mProject->GetScrubber().HasStartedScrubbing()));
|
||||
(scrubber.HasStartedScrubbing()));
|
||||
auto seek = scrub && scrubber.Seeks();
|
||||
auto width = scrub ? IndicatorBigWidth() : IndicatorSmallWidth;
|
||||
ruler->DoDrawIndicator(&dc, mOldQPIndicatorPos, true, width, scrub);
|
||||
ruler->DoDrawIndicator(&dc, mOldQPIndicatorPos, true, width, scrub, seek);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1918,8 +1920,8 @@ enum {
|
||||
OnLockPlayRegionID,
|
||||
|
||||
OnTogglePinnedStateID,
|
||||
|
||||
OnShowHideScrubbingID,
|
||||
OnScrubID,
|
||||
OnSeekID,
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(AdornedRulerPanel, OverlayPanel)
|
||||
@ -1935,15 +1937,18 @@ BEGIN_EVENT_TABLE(AdornedRulerPanel, OverlayPanel)
|
||||
EVT_MENU(OnAutoScrollID, AdornedRulerPanel::OnAutoScroll)
|
||||
EVT_MENU(OnLockPlayRegionID, AdornedRulerPanel::OnLockPlayRegion)
|
||||
|
||||
// Scrub bar menu commands
|
||||
EVT_MENU(OnShowHideScrubbingID, AdornedRulerPanel::OnToggleScrubbing)
|
||||
|
||||
// Pop up menus on Windows
|
||||
EVT_CONTEXT_MENU(AdornedRulerPanel::OnContextMenu)
|
||||
|
||||
EVT_COMMAND( OnTogglePinnedStateID,
|
||||
wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
AdornedRulerPanel::OnTogglePinnedState )
|
||||
wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
AdornedRulerPanel::OnTogglePinnedState )
|
||||
EVT_COMMAND( OnScrubID,
|
||||
wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
AdornedRulerPanel::OnScrub )
|
||||
EVT_COMMAND( OnSeekID,
|
||||
wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
AdornedRulerPanel::OnSeek )
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
@ -2026,6 +2031,7 @@ AdornedRulerPanel::~AdornedRulerPanel()
|
||||
this);
|
||||
}
|
||||
|
||||
#if 0
|
||||
namespace {
|
||||
static const wxChar *scrubEnabledPrefName = wxT("/QuickPlay/ScrubbingEnabled");
|
||||
|
||||
@ -2041,6 +2047,7 @@ namespace {
|
||||
gPrefs->Write(scrubEnabledPrefName, value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void AdornedRulerPanel::UpdatePrefs()
|
||||
{
|
||||
@ -2058,7 +2065,7 @@ void AdornedRulerPanel::UpdatePrefs()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
mShowScrubbing = ReadScrubEnabledPref();
|
||||
// mShowScrubbing = ReadScrubEnabledPref();
|
||||
// Affected by the last
|
||||
UpdateRects();
|
||||
|
||||
@ -2088,9 +2095,10 @@ void AdornedRulerPanel::ReCreateButtons()
|
||||
|
||||
// Make the short row of time ruler pushbottons.
|
||||
// Don't bother with sizers. Their sizes and positions are fixed.
|
||||
wxPoint position{ FocusBorderLeft, FocusBorderTop };
|
||||
wxPoint position{ FocusBorderLeft, 0 };
|
||||
size_t iButton = 0;
|
||||
const auto size = theTheme.ImageSize( bmpRecoloredUpSmall );
|
||||
auto size = theTheme.ImageSize( bmpRecoloredUpSmall );
|
||||
size.y = std::min(size.y, GetRulerHeight(false));
|
||||
|
||||
auto buttonMaker = [&]
|
||||
(wxWindowID id, teBmps bitmap, bool toggle)
|
||||
@ -2113,6 +2121,8 @@ void AdornedRulerPanel::ReCreateButtons()
|
||||
bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredHiliteSmall,
|
||||
bmpUnpinnedPlayRecordHead, bmpUnpinnedPlayRecordHead, bmpUnpinnedPlayRecordHead,
|
||||
size);
|
||||
buttonMaker(OnScrubID, bmpScrub, true);
|
||||
buttonMaker(OnSeekID, bmpSeek, true);
|
||||
|
||||
UpdateButtonStates();
|
||||
}
|
||||
@ -2421,7 +2431,7 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
||||
}
|
||||
else if (!HasCapture() && inScrubZone) {
|
||||
if (evt.LeftDown()) {
|
||||
scrubber.MarkScrubStart(evt.m_x, PlaybackPrefs::GetPinnedHeadPreference(), false);
|
||||
scrubber.MarkScrubStart(evt.m_x, PlaybackPrefs::GetPinnedHeadPreference());
|
||||
UpdateStatusBarAndTooltips(StatusChoice::EnteringScrubZone);
|
||||
}
|
||||
ShowQuickPlayIndicator();
|
||||
@ -2730,12 +2740,10 @@ void AdornedRulerPanel::UpdateStatusBarAndTooltips(StatusChoice choice)
|
||||
|
||||
case StatusChoice::EnteringScrubZone:
|
||||
{
|
||||
if (scrubbing) {
|
||||
if(!scrubber.IsAlwaysSeeking())
|
||||
message = _("Click or drag to seek");
|
||||
}
|
||||
else
|
||||
message = _("Click to scrub, Double-Click to scroll, Drag to seek");
|
||||
if(scrubber.Seeks())
|
||||
message = _("Click or drag to seek");
|
||||
else if(scrubber.Scrubs())
|
||||
message = _("Click or drag to scrub");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2749,10 +2757,10 @@ void AdornedRulerPanel::UpdateStatusBarAndTooltips(StatusChoice choice)
|
||||
RegenerateTooltips(choice);
|
||||
}
|
||||
|
||||
void AdornedRulerPanel::OnToggleScrubbing(wxCommandEvent&)
|
||||
void AdornedRulerPanel::OnToggleScrubbing(/*wxCommandEvent&*/)
|
||||
{
|
||||
mShowScrubbing = !mShowScrubbing;
|
||||
WriteScrubEnabledPref(mShowScrubbing);
|
||||
//WriteScrubEnabledPref(mShowScrubbing);
|
||||
gPrefs->Flush();
|
||||
wxSize size { GetSize().GetWidth(), GetRulerHeight(mShowScrubbing) };
|
||||
SetSize(size);
|
||||
@ -2767,6 +2775,13 @@ void AdornedRulerPanel::OnContextMenu(wxContextMenuEvent & WXUNUSED(event))
|
||||
|
||||
void AdornedRulerPanel::UpdateButtonStates()
|
||||
{
|
||||
auto common = [this]
|
||||
(wxWindow *button, const wxString &commandName, const wxString &label){
|
||||
const auto &fullLabel = ComposeButtonLabel(*mProject, commandName, label);
|
||||
button->SetLabel(fullLabel);
|
||||
button->SetToolTip(fullLabel);
|
||||
};
|
||||
|
||||
{
|
||||
bool state = PlaybackPrefs::GetPinnedHeadPreference();
|
||||
auto pinButton = static_cast<AButton*>(FindWindow(OnTogglePinnedStateID));
|
||||
@ -2777,10 +2792,38 @@ void AdornedRulerPanel::UpdateButtonStates()
|
||||
// (which is, to toggle the state)
|
||||
? _("Pinned play/record Head")
|
||||
: _("Unpinned play/record Head");
|
||||
const auto &fullLabel = ComposeButtonLabel(*mProject, wxT("PinnedHead"), label);
|
||||
pinButton->SetLabel(fullLabel);
|
||||
pinButton->SetToolTip(fullLabel);
|
||||
common(pinButton, wxT("PinnedHead"), label);
|
||||
}
|
||||
|
||||
const auto scrubber = &mProject->GetScrubber();
|
||||
|
||||
{
|
||||
const auto scrubButton = static_cast<AButton*>(FindWindow(OnScrubID));
|
||||
/* i18n-hint: These commands assist the user in finding a sound by ear. ...
|
||||
"Scrubbing" is variable-speed playback
|
||||
*/
|
||||
common(scrubButton, wxT("Scrub"), _("Scrub"));
|
||||
if (scrubber && scrubber->Scrubs())
|
||||
scrubButton->PushDown();
|
||||
else
|
||||
scrubButton->PopUp();
|
||||
}
|
||||
|
||||
{
|
||||
const auto seekButton = static_cast<AButton*>(FindWindow(OnSeekID));
|
||||
/* i18n-hint: These commands assist the user in finding a sound by ear. ...
|
||||
"Seeking" is normal speed playback but with skips
|
||||
*/
|
||||
common(seekButton, wxT("Seek"), _("Seek"));
|
||||
if (scrubber && scrubber->Seeks())
|
||||
seekButton->PushDown();
|
||||
else
|
||||
seekButton->PopUp();
|
||||
}
|
||||
|
||||
if(scrubber &&
|
||||
mShowScrubbing != (scrubber->Scrubs() || scrubber->Seeks()))
|
||||
OnToggleScrubbing();
|
||||
}
|
||||
|
||||
void AdornedRulerPanel::OnTogglePinnedState(wxCommandEvent & event)
|
||||
@ -2789,6 +2832,16 @@ void AdornedRulerPanel::OnTogglePinnedState(wxCommandEvent & event)
|
||||
UpdateButtonStates();
|
||||
}
|
||||
|
||||
void AdornedRulerPanel::OnSeek(wxCommandEvent & event)
|
||||
{
|
||||
mProject->GetScrubber().OnSeek(event);
|
||||
}
|
||||
|
||||
void AdornedRulerPanel::OnScrub(wxCommandEvent & event)
|
||||
{
|
||||
mProject->GetScrubber().OnScrub(event);
|
||||
}
|
||||
|
||||
void AdornedRulerPanel::OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED(evt))
|
||||
{
|
||||
HideQuickPlayIndicator();
|
||||
@ -2858,12 +2911,6 @@ void AdornedRulerPanel::ShowScrubMenu(const wxPoint & pos)
|
||||
auto cleanup = finally([this]{ PopEventHandler(); });
|
||||
|
||||
wxMenu rulerMenu;
|
||||
rulerMenu.AppendCheckItem(OnShowHideScrubbingID, _("Scrub Bar"));
|
||||
if(mShowScrubbing)
|
||||
rulerMenu.FindItem(OnShowHideScrubbingID)->Check();
|
||||
|
||||
rulerMenu.AppendSeparator();
|
||||
|
||||
mProject->GetScrubber().PopulateMenu(rulerMenu);
|
||||
PopupMenu(&rulerMenu, pos);
|
||||
}
|
||||
@ -3104,11 +3151,6 @@ void AdornedRulerPanel::DoDrawSelection(wxDC * dc)
|
||||
dc->DrawRectangle( r );
|
||||
}
|
||||
|
||||
int AdornedRulerPanel::GetRulerHeight()
|
||||
{
|
||||
return GetRulerHeight(ReadScrubEnabledPref());
|
||||
}
|
||||
|
||||
int AdornedRulerPanel::GetRulerHeight(bool showScrubBar)
|
||||
{
|
||||
return ProperRulerHeight + (showScrubBar ? ScrubHeight : 0);
|
||||
@ -3122,14 +3164,46 @@ void AdornedRulerPanel::SetLeftOffset(int offset)
|
||||
|
||||
// Draws the play/recording position indicator.
|
||||
void AdornedRulerPanel::DoDrawIndicator
|
||||
(wxDC * dc, wxCoord xx, bool playing, int width, bool scrub)
|
||||
(wxDC * dc, wxCoord xx, bool playing, int width, bool scrub, bool seek)
|
||||
{
|
||||
ADCChanger changer(dc); // Undo pen and brush changes at function exit
|
||||
|
||||
AColor::IndicatorColor( dc, playing );
|
||||
|
||||
wxPoint tri[ 3 ];
|
||||
if (scrub) {
|
||||
if (seek) {
|
||||
auto height = IndicatorHeightForWidth(width);
|
||||
// Make four triangles
|
||||
const int TriangleWidth = width * 3 / 8;
|
||||
|
||||
// Double-double headed, left-right
|
||||
auto yy = mShowScrubbing
|
||||
? mScrubZone.y
|
||||
: (mInner.GetBottom() + 1) - 1 /* bevel */ - height;
|
||||
tri[ 0 ].x = xx - IndicatorOffset;
|
||||
tri[ 0 ].y = yy;
|
||||
tri[ 1 ].x = xx - IndicatorOffset;
|
||||
tri[ 1 ].y = yy + height;
|
||||
tri[ 2 ].x = xx - TriangleWidth;
|
||||
tri[ 2 ].y = yy + height / 2;
|
||||
dc->DrawPolygon( 3, tri );
|
||||
|
||||
tri[ 0 ].x -= TriangleWidth;
|
||||
tri[ 1 ].x -= TriangleWidth;
|
||||
tri[ 2 ].x -= TriangleWidth;
|
||||
dc->DrawPolygon( 3, tri );
|
||||
|
||||
tri[ 0 ].x = tri[ 1 ].x = xx + IndicatorOffset;
|
||||
tri[ 2 ].x = xx + TriangleWidth;
|
||||
dc->DrawPolygon( 3, tri );
|
||||
|
||||
|
||||
tri[ 0 ].x += TriangleWidth;
|
||||
tri[ 1 ].x += TriangleWidth;
|
||||
tri[ 2 ].x += TriangleWidth;
|
||||
dc->DrawPolygon( 3, tri );
|
||||
}
|
||||
else if (scrub) {
|
||||
auto height = IndicatorHeightForWidth(width);
|
||||
const int IndicatorHalfWidth = width / 2;
|
||||
|
||||
|
@ -298,7 +298,7 @@ public:
|
||||
#endif
|
||||
|
||||
public:
|
||||
static int GetRulerHeight();
|
||||
int GetRulerHeight() { return GetRulerHeight(mShowScrubbing); }
|
||||
static int GetRulerHeight(bool showScrubBar);
|
||||
wxRect GetInnerRect() const { return mInner; }
|
||||
|
||||
@ -351,7 +351,7 @@ private:
|
||||
void DoDrawSelection(wxDC * dc);
|
||||
|
||||
public:
|
||||
void DoDrawIndicator(wxDC * dc, wxCoord xx, bool playing, int width, bool scrub);
|
||||
void DoDrawIndicator(wxDC * dc, wxCoord xx, bool playing, int width, bool scrub, bool seek);
|
||||
void UpdateButtonStates();
|
||||
|
||||
private:
|
||||
@ -413,7 +413,9 @@ private:
|
||||
void OnAutoScroll(wxCommandEvent &evt);
|
||||
void OnLockPlayRegion(wxCommandEvent &evt);
|
||||
|
||||
void OnToggleScrubbing(wxCommandEvent&);
|
||||
void OnToggleScrubbing(/*wxCommandEvent&*/);
|
||||
void OnScrub(wxCommandEvent&);
|
||||
void OnSeek(wxCommandEvent&);
|
||||
|
||||
void OnContextMenu(wxContextMenuEvent & WXUNUSED(event));
|
||||
|
||||
@ -446,7 +448,7 @@ private:
|
||||
|
||||
friend QuickPlayRulerOverlay;
|
||||
|
||||
wxWindow *mButtons[1];
|
||||
wxWindow *mButtons[3];
|
||||
bool mNeedButtonUpdate { true };
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user