mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-24 16:20:05 +02:00
Merge branch 'master' into scrubbing
This commit is contained in:
commit
f7765a5068
@ -17,16 +17,32 @@ It is also a place to document colour usage policy in Audacity
|
|||||||
|
|
||||||
*//********************************************************************/
|
*//********************************************************************/
|
||||||
|
|
||||||
|
#include "Audacity.h"
|
||||||
|
#include "AColor.h"
|
||||||
|
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
#include <wx/dc.h>
|
#include <wx/dc.h>
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
#include <wx/utils.h>
|
#include <wx/utils.h>
|
||||||
|
|
||||||
#include "AColor.h"
|
|
||||||
#include "Theme.h"
|
#include "Theme.h"
|
||||||
#include "Experimental.h"
|
#include "Experimental.h"
|
||||||
#include "AllThemeResources.h"
|
#include "AllThemeResources.h"
|
||||||
|
|
||||||
|
void DCUnchanger::operator () (wxDC *pDC) const
|
||||||
|
{
|
||||||
|
if (pDC) {
|
||||||
|
pDC->SetPen(pen);
|
||||||
|
pDC->SetBrush(brush);
|
||||||
|
pDC->SetLogicalFunction(wxRasterOperationMode(logicalOperation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ADCChanger::ADCChanger(wxDC *pDC)
|
||||||
|
: Base{ pDC, ::DCUnchanger{ pDC->GetBrush(), pDC->GetPen(),
|
||||||
|
long(pDC->GetLogicalFunction()) } }
|
||||||
|
{}
|
||||||
|
|
||||||
bool AColor::inited = false;
|
bool AColor::inited = false;
|
||||||
wxBrush AColor::lightBrush[2];
|
wxBrush AColor::lightBrush[2];
|
||||||
wxBrush AColor::mediumBrush[2];
|
wxBrush AColor::mediumBrush[2];
|
||||||
|
27
src/AColor.h
27
src/AColor.h
@ -14,12 +14,39 @@
|
|||||||
#ifndef __AUDACITY_COLOR__
|
#ifndef __AUDACITY_COLOR__
|
||||||
#define __AUDACITY_COLOR__
|
#define __AUDACITY_COLOR__
|
||||||
|
|
||||||
|
#include "MemoryX.h"
|
||||||
#include <wx/brush.h>
|
#include <wx/brush.h>
|
||||||
#include <wx/pen.h>
|
#include <wx/pen.h>
|
||||||
|
|
||||||
class wxDC;
|
class wxDC;
|
||||||
class wxRect;
|
class wxRect;
|
||||||
|
|
||||||
|
struct DCUnchanger {
|
||||||
|
public:
|
||||||
|
DCUnchanger() {}
|
||||||
|
|
||||||
|
DCUnchanger(const wxBrush &brush_, const wxPen &pen_, long logicalOperation_)
|
||||||
|
: brush(brush_), pen(pen_), logicalOperation(logicalOperation_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator () (wxDC *pDC) const;
|
||||||
|
|
||||||
|
wxBrush brush {};
|
||||||
|
wxPen pen {};
|
||||||
|
long logicalOperation {};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Like wxDCPenChanger, etc., but simple and general
|
||||||
|
// Make temporary drawing context changes that you back out of, RAII style
|
||||||
|
|
||||||
|
class ADCChanger : public std::unique_ptr<wxDC, ::DCUnchanger>
|
||||||
|
{
|
||||||
|
using Base = std::unique_ptr<wxDC, ::DCUnchanger>;
|
||||||
|
public:
|
||||||
|
ADCChanger() : Base{} {}
|
||||||
|
ADCChanger(wxDC *pDC);
|
||||||
|
};
|
||||||
|
|
||||||
class AColor {
|
class AColor {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ void AboutDialog::CreateCreditsList()
|
|||||||
AddCredit(wxString(wxT("Greg Kozikowski, ")) + _("documentation and support"), roleTeamMember);
|
AddCredit(wxString(wxT("Greg Kozikowski, ")) + _("documentation and support"), roleTeamMember);
|
||||||
AddCredit(wxString(wxT("Paul Licameli, ")) + _("developer"), roleTeamMember);
|
AddCredit(wxString(wxT("Paul Licameli, ")) + _("developer"), roleTeamMember);
|
||||||
AddCredit(wxString(wxT("Leland Lucius, ")) + _("developer"), roleTeamMember);
|
AddCredit(wxString(wxT("Leland Lucius, ")) + _("developer"), roleTeamMember);
|
||||||
AddCredit(wxString(wxT("Peter Sampson, ")) + _("documentation and support"), roleTeamMember);
|
AddCredit(wxString(wxT("Peter Sampson")), roleTeamMember);
|
||||||
AddCredit(wxString(wxT("Martyn Shaw, ")) + _("developer"), roleTeamMember);
|
AddCredit(wxString(wxT("Martyn Shaw, ")) + _("developer"), roleTeamMember);
|
||||||
AddCredit(wxString(wxT("Bill Wharrie, ")) + _("documentation and support"), roleTeamMember);
|
AddCredit(wxString(wxT("Bill Wharrie, ")) + _("documentation and support"), roleTeamMember);
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_OPEN_AUDIO_FILE, -1);
|
|||||||
|
|
||||||
// These flags represent the majority of the states that affect
|
// These flags represent the majority of the states that affect
|
||||||
// whether or not items in menus are enabled or disabled.
|
// whether or not items in menus are enabled or disabled.
|
||||||
enum
|
enum CommandFlag : unsigned long long
|
||||||
{
|
{
|
||||||
AlwaysEnabledFlag = 0x00000000,
|
AlwaysEnabledFlag = 0x00000000,
|
||||||
|
|
||||||
@ -93,11 +93,89 @@ enum
|
|||||||
CaptureNotBusyFlag = 0x20000000,
|
CaptureNotBusyFlag = 0x20000000,
|
||||||
CanStopAudioStreamFlag = 0x40000000,
|
CanStopAudioStreamFlag = 0x40000000,
|
||||||
AudioStreamNotScrubbingFlag
|
AudioStreamNotScrubbingFlag
|
||||||
= 0x80000000,
|
= 0x80000000ULL, // prl
|
||||||
|
|
||||||
NoFlagsSpecifed = 0xffffffff
|
NoFlagsSpecifed = ~0ULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Prevent accidental misuse with narrower types
|
||||||
|
|
||||||
|
bool operator == (CommandFlag, unsigned long) PROHIBITED;
|
||||||
|
bool operator == (CommandFlag, long) PROHIBITED;
|
||||||
|
bool operator == (unsigned long, CommandFlag) PROHIBITED;
|
||||||
|
bool operator == (long, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
bool operator != (CommandFlag, unsigned long) PROHIBITED;
|
||||||
|
bool operator != (CommandFlag, long) PROHIBITED;
|
||||||
|
bool operator != (unsigned long, CommandFlag) PROHIBITED;
|
||||||
|
bool operator != (long, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
CommandFlag operator & (CommandFlag, unsigned long) PROHIBITED;
|
||||||
|
CommandFlag operator & (CommandFlag, long) PROHIBITED;
|
||||||
|
CommandFlag operator & (unsigned long, CommandFlag) PROHIBITED;
|
||||||
|
CommandFlag operator & (long, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
CommandFlag operator | (CommandFlag, unsigned long) PROHIBITED;
|
||||||
|
CommandFlag operator | (CommandFlag, long) PROHIBITED;
|
||||||
|
CommandFlag operator | (unsigned long, CommandFlag) PROHIBITED;
|
||||||
|
CommandFlag operator | (long, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
CommandFlag operator ^ (CommandFlag, unsigned long) PROHIBITED;
|
||||||
|
CommandFlag operator ^ (CommandFlag, long) PROHIBITED;
|
||||||
|
CommandFlag operator ^ (unsigned long, CommandFlag) PROHIBITED;
|
||||||
|
CommandFlag operator ^ (long, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
bool operator == (CommandFlag, unsigned int) PROHIBITED;
|
||||||
|
bool operator == (CommandFlag, int) PROHIBITED;
|
||||||
|
bool operator == (unsigned int, CommandFlag) PROHIBITED;
|
||||||
|
bool operator == (int, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
bool operator != (CommandFlag, unsigned int) PROHIBITED;
|
||||||
|
bool operator != (CommandFlag, int) PROHIBITED;
|
||||||
|
bool operator != (unsigned int, CommandFlag) PROHIBITED;
|
||||||
|
bool operator != (int, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
CommandFlag operator & (CommandFlag, unsigned int) PROHIBITED;
|
||||||
|
CommandFlag operator & (CommandFlag, int) PROHIBITED;
|
||||||
|
CommandFlag operator & (unsigned int, CommandFlag) PROHIBITED;
|
||||||
|
CommandFlag operator & (int, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
CommandFlag operator | (CommandFlag, unsigned int) PROHIBITED;
|
||||||
|
CommandFlag operator | (CommandFlag, int) PROHIBITED;
|
||||||
|
CommandFlag operator | (unsigned int, CommandFlag) PROHIBITED;
|
||||||
|
CommandFlag operator | (int, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
CommandFlag operator ^ (CommandFlag, unsigned int) PROHIBITED;
|
||||||
|
CommandFlag operator ^ (CommandFlag, int) PROHIBITED;
|
||||||
|
CommandFlag operator ^ (unsigned int, CommandFlag) PROHIBITED;
|
||||||
|
CommandFlag operator ^ (int, CommandFlag) PROHIBITED;
|
||||||
|
|
||||||
|
// Supply the bitwise operations
|
||||||
|
|
||||||
|
inline CommandFlag operator ~ (CommandFlag flag)
|
||||||
|
{
|
||||||
|
return static_cast<CommandFlag>( ~ static_cast<unsigned long long> (flag) );
|
||||||
|
}
|
||||||
|
inline CommandFlag operator & (CommandFlag lhs, CommandFlag rhs)
|
||||||
|
{
|
||||||
|
return static_cast<CommandFlag> (
|
||||||
|
static_cast<unsigned long long>(lhs) & static_cast<unsigned long long>(rhs)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
inline CommandFlag operator | (CommandFlag lhs, CommandFlag rhs)
|
||||||
|
{
|
||||||
|
return static_cast<CommandFlag> (
|
||||||
|
static_cast<unsigned long long>(lhs) | static_cast<unsigned long long>(rhs)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
inline CommandFlag & operator |= (CommandFlag &lhs, CommandFlag rhs)
|
||||||
|
{
|
||||||
|
lhs = lhs | rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
using CommandMask = CommandFlag;
|
||||||
|
|
||||||
class BlockFile;
|
class BlockFile;
|
||||||
|
|
||||||
class AudacityApp final : public wxApp {
|
class AudacityApp final : public wxApp {
|
||||||
|
@ -2258,7 +2258,9 @@ void AudioIO::StopStream()
|
|||||||
while( mAudioThreadShouldCallFillBuffersOnce == true )
|
while( mAudioThreadShouldCallFillBuffersOnce == true )
|
||||||
{
|
{
|
||||||
// LLL: Experienced recursive yield here...once.
|
// LLL: Experienced recursive yield here...once.
|
||||||
wxGetApp().Yield(true); // Pass true for onlyIfNeeded to avoid recursive call error.
|
// PRL: Made it safe yield to avoid a certain recursive event processing in the
|
||||||
|
// time ruler when switching from scrub to quick play.
|
||||||
|
wxGetApp().SafeYield(nullptr, true); // Pass true for onlyIfNeeded to avoid recursive call error.
|
||||||
wxMilliSleep( 50 );
|
wxMilliSleep( 50 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -907,7 +907,8 @@ void AudacityProject::CreateMenusAndCommands()
|
|||||||
#else
|
#else
|
||||||
wxT("Ctrl+M"),
|
wxT("Ctrl+M"),
|
||||||
#endif
|
#endif
|
||||||
0, AudioIONotBusyFlag);
|
AlwaysEnabledFlag, // is this correct??
|
||||||
|
AudioIONotBusyFlag);
|
||||||
c->AddItem(wxT("EditLabels"), _("&Edit Labels..."), FN(OnEditLabels));
|
c->AddItem(wxT("EditLabels"), _("&Edit Labels..."), FN(OnEditLabels));
|
||||||
|
|
||||||
c->AddSeparator();
|
c->AddSeparator();
|
||||||
@ -1214,7 +1215,7 @@ void AudacityProject::CreateMenusAndCommands()
|
|||||||
c->AddCommand(wxT("PlaySpeedInc"), _("Increase playback speed"), FN(OnPlaySpeedInc));
|
c->AddCommand(wxT("PlaySpeedInc"), _("Increase playback speed"), FN(OnPlaySpeedInc));
|
||||||
c->AddCommand(wxT("PlaySpeedDec"), _("Decrease playback speed"), FN(OnPlaySpeedDec));
|
c->AddCommand(wxT("PlaySpeedDec"), _("Decrease playback speed"), FN(OnPlaySpeedDec));
|
||||||
|
|
||||||
mLastFlags = 0;
|
mLastFlags = AlwaysEnabledFlag;
|
||||||
|
|
||||||
#if defined(__WXDEBUG__)
|
#if defined(__WXDEBUG__)
|
||||||
// c->CheckDups();
|
// c->CheckDups();
|
||||||
@ -1223,8 +1224,8 @@ void AudacityProject::CreateMenusAndCommands()
|
|||||||
|
|
||||||
void AudacityProject::PopulateEffectsMenu(CommandManager* c,
|
void AudacityProject::PopulateEffectsMenu(CommandManager* c,
|
||||||
EffectType type,
|
EffectType type,
|
||||||
int batchflags,
|
CommandFlag batchflags,
|
||||||
int realflags)
|
CommandFlag realflags)
|
||||||
{
|
{
|
||||||
PluginManager & pm = PluginManager::Get();
|
PluginManager & pm = PluginManager::Get();
|
||||||
|
|
||||||
@ -1295,8 +1296,8 @@ void AudacityProject::PopulateEffectsMenu(CommandManager* c,
|
|||||||
|
|
||||||
void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
||||||
EffectPlugs & plugs,
|
EffectPlugs & plugs,
|
||||||
int batchflags,
|
CommandFlag batchflags,
|
||||||
int realflags,
|
CommandFlag realflags,
|
||||||
bool isDefault)
|
bool isDefault)
|
||||||
{
|
{
|
||||||
size_t pluginCnt = plugs.GetCount();
|
size_t pluginCnt = plugs.GetCount();
|
||||||
@ -1311,7 +1312,7 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||||||
|
|
||||||
wxArrayString groupNames;
|
wxArrayString groupNames;
|
||||||
PluginIDList groupPlugs;
|
PluginIDList groupPlugs;
|
||||||
wxArrayInt groupFlags;
|
std::vector<CommandFlag> groupFlags;
|
||||||
if (grouped)
|
if (grouped)
|
||||||
{
|
{
|
||||||
wxString last;
|
wxString last;
|
||||||
@ -1361,13 +1362,13 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||||||
|
|
||||||
groupNames.Clear();
|
groupNames.Clear();
|
||||||
groupPlugs.Clear();
|
groupPlugs.Clear();
|
||||||
groupFlags.Clear();
|
groupFlags.clear();
|
||||||
last = current;
|
last = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
groupNames.Add(name);
|
groupNames.Add(name);
|
||||||
groupPlugs.Add(plug->GetID());
|
groupPlugs.Add(plug->GetID());
|
||||||
groupFlags.Add(plug->IsEffectRealtime() ? realflags : batchflags);
|
groupFlags.push_back(plug->IsEffectRealtime() ? realflags : batchflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupNames.GetCount() > 0)
|
if (groupNames.GetCount() > 0)
|
||||||
@ -1414,7 +1415,7 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||||||
|
|
||||||
groupNames.Add(group + name);
|
groupNames.Add(group + name);
|
||||||
groupPlugs.Add(plug->GetID());
|
groupPlugs.Add(plug->GetID());
|
||||||
groupFlags.Add(plug->IsEffectRealtime() ? realflags : batchflags);
|
groupFlags.push_back(plug->IsEffectRealtime() ? realflags : batchflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupNames.GetCount() > 0)
|
if (groupNames.GetCount() > 0)
|
||||||
@ -1430,7 +1431,7 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||||||
void AudacityProject::AddEffectMenuItemGroup(CommandManager *c,
|
void AudacityProject::AddEffectMenuItemGroup(CommandManager *c,
|
||||||
const wxArrayString & names,
|
const wxArrayString & names,
|
||||||
const PluginIDList & plugs,
|
const PluginIDList & plugs,
|
||||||
const wxArrayInt & flags,
|
const std::vector<CommandFlag> & flags,
|
||||||
bool isDefault)
|
bool isDefault)
|
||||||
{
|
{
|
||||||
int namesCnt = (int) names.GetCount();
|
int namesCnt = (int) names.GetCount();
|
||||||
@ -1609,7 +1610,7 @@ void AudacityProject::RebuildOtherMenus()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudacityProject::GetFocusedFrame()
|
CommandFlag AudacityProject::GetFocusedFrame()
|
||||||
{
|
{
|
||||||
wxWindow *w = FindFocus();
|
wxWindow *w = FindFocus();
|
||||||
|
|
||||||
@ -1629,16 +1630,16 @@ int AudacityProject::GetFocusedFrame()
|
|||||||
w = w->GetParent();
|
w = w->GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return AlwaysEnabledFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxUint32 AudacityProject::GetUpdateFlags()
|
CommandFlag AudacityProject::GetUpdateFlags()
|
||||||
{
|
{
|
||||||
// This method determines all of the flags that determine whether
|
// This method determines all of the flags that determine whether
|
||||||
// certain menu items and commands should be enabled or disabled,
|
// certain menu items and commands should be enabled or disabled,
|
||||||
// and returns them in a bitfield. Note that if none of the flags
|
// and returns them in a bitfield. Note that if none of the flags
|
||||||
// have changed, it's not necessary to even check for updates.
|
// have changed, it's not necessary to even check for updates.
|
||||||
wxUint32 flags = 0;
|
auto flags = AlwaysEnabledFlag;
|
||||||
|
|
||||||
if (!gAudioIO->IsAudioTokenActive(GetAudioIOToken()))
|
if (!gAudioIO->IsAudioTokenActive(GetAudioIOToken()))
|
||||||
flags |= AudioIONotBusyFlag;
|
flags |= AudioIONotBusyFlag;
|
||||||
@ -1767,8 +1768,8 @@ wxUint32 AudacityProject::GetUpdateFlags()
|
|||||||
|
|
||||||
void AudacityProject::SelectAllIfNone()
|
void AudacityProject::SelectAllIfNone()
|
||||||
{
|
{
|
||||||
wxUint32 flags = GetUpdateFlags();
|
auto flags = GetUpdateFlags();
|
||||||
if(((flags & TracksSelectedFlag) ==0) ||
|
if(!(flags & TracksSelectedFlag) ||
|
||||||
(mViewInfo.selectedRegion.isPoint()))
|
(mViewInfo.selectedRegion.isPoint()))
|
||||||
OnSelectAll();
|
OnSelectAll();
|
||||||
}
|
}
|
||||||
@ -1850,17 +1851,17 @@ void AudacityProject::UpdateMenus(bool checkActive)
|
|||||||
if (checkActive && !IsActive())
|
if (checkActive && !IsActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wxUint32 flags = GetUpdateFlags();
|
auto flags = GetUpdateFlags();
|
||||||
wxUint32 flags2 = flags;
|
auto flags2 = flags;
|
||||||
|
|
||||||
// We can enable some extra items if we have select-all-on-none.
|
// We can enable some extra items if we have select-all-on-none.
|
||||||
//EXPLAIN-ME: Why is this here rather than in GetUpdateFlags()?
|
//EXPLAIN-ME: Why is this here rather than in GetUpdateFlags()?
|
||||||
if (mSelectAllOnNone)
|
if (mSelectAllOnNone)
|
||||||
{
|
{
|
||||||
if ((flags & TracksExistFlag) != 0)
|
if ((flags & TracksExistFlag))
|
||||||
{
|
{
|
||||||
flags2 |= TracksSelectedFlag;
|
flags2 |= TracksSelectedFlag;
|
||||||
if ((flags & WaveTracksExistFlag) != 0 )
|
if ((flags & WaveTracksExistFlag))
|
||||||
{
|
{
|
||||||
flags2 |= TimeSelectedFlag
|
flags2 |= TimeSelectedFlag
|
||||||
| WaveTracksSelectedFlag
|
| WaveTracksSelectedFlag
|
||||||
@ -1875,21 +1876,21 @@ void AudacityProject::UpdateMenus(bool checkActive)
|
|||||||
return;
|
return;
|
||||||
mLastFlags = flags;
|
mLastFlags = flags;
|
||||||
|
|
||||||
mCommandManager.EnableUsingFlags(flags2 , 0xFFFFFFFF);
|
mCommandManager.EnableUsingFlags(flags2 , NoFlagsSpecifed);
|
||||||
|
|
||||||
// With select-all-on-none, some items that we don't want enabled may have
|
// With select-all-on-none, some items that we don't want enabled may have
|
||||||
// been enabled, since we changed the flags. Here we manually disable them.
|
// been enabled, since we changed the flags. Here we manually disable them.
|
||||||
if (mSelectAllOnNone)
|
if (mSelectAllOnNone)
|
||||||
{
|
{
|
||||||
if ((flags & TracksSelectedFlag) == 0)
|
if (!(flags & TracksSelectedFlag))
|
||||||
{
|
{
|
||||||
mCommandManager.Enable(wxT("SplitCut"), false);
|
mCommandManager.Enable(wxT("SplitCut"), false);
|
||||||
|
|
||||||
if ((flags & WaveTracksSelectedFlag) == 0)
|
if (!(flags & WaveTracksSelectedFlag))
|
||||||
{
|
{
|
||||||
mCommandManager.Enable(wxT("Split"), false);
|
mCommandManager.Enable(wxT("Split"), false);
|
||||||
}
|
}
|
||||||
if ((flags & TimeSelectedFlag) == 0)
|
if (!(flags & TimeSelectedFlag))
|
||||||
{
|
{
|
||||||
mCommandManager.Enable(wxT("ExportSel"), false);
|
mCommandManager.Enable(wxT("ExportSel"), false);
|
||||||
mCommandManager.Enable(wxT("SplitNew"), false);
|
mCommandManager.Enable(wxT("SplitNew"), false);
|
||||||
@ -2690,6 +2691,9 @@ void AudacityProject::NextFrame()
|
|||||||
case BotDockHasFocus:
|
case BotDockHasFocus:
|
||||||
mToolManager->GetTopDock()->SetFocus();
|
mToolManager->GetTopDock()->SetFocus();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2708,6 +2712,9 @@ void AudacityProject::PrevFrame()
|
|||||||
case BotDockHasFocus:
|
case BotDockHasFocus:
|
||||||
mTrackPanel->SetFocus();
|
mTrackPanel->SetFocus();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/Menus.h
14
src/Menus.h
@ -24,17 +24,21 @@
|
|||||||
private:
|
private:
|
||||||
void CreateMenusAndCommands();
|
void CreateMenusAndCommands();
|
||||||
|
|
||||||
void PopulateEffectsMenu(CommandManager *c, EffectType type, int batchflags, int realflags);
|
void PopulateEffectsMenu(CommandManager *c, EffectType type,
|
||||||
void AddEffectMenuItems(CommandManager *c, EffectPlugs & plugs, int batchflags, int realflags, bool isDefault);
|
CommandFlag batchflags, CommandFlag realflags);
|
||||||
void AddEffectMenuItemGroup(CommandManager *c, const wxArrayString & names, const PluginIDList & plugs, const wxArrayInt & flags, bool isDefault);
|
void AddEffectMenuItems(CommandManager *c, EffectPlugs & plugs,
|
||||||
|
CommandFlag batchflags, CommandFlag realflags, bool isDefault);
|
||||||
|
void AddEffectMenuItemGroup(CommandManager *c, const wxArrayString & names,
|
||||||
|
const PluginIDList & plugs,
|
||||||
|
const std::vector<CommandFlag> & flags, bool isDefault);
|
||||||
void CreateRecentFilesMenu(CommandManager *c);
|
void CreateRecentFilesMenu(CommandManager *c);
|
||||||
void ModifyUndoMenuItems();
|
void ModifyUndoMenuItems();
|
||||||
void ModifyToolbarMenus();
|
void ModifyToolbarMenus();
|
||||||
// Calls ModifyToolbarMenus() on all projects
|
// Calls ModifyToolbarMenus() on all projects
|
||||||
void ModifyAllProjectToolbarMenus();
|
void ModifyAllProjectToolbarMenus();
|
||||||
|
|
||||||
int GetFocusedFrame();
|
CommandFlag GetFocusedFrame();
|
||||||
wxUint32 GetUpdateFlags();
|
CommandFlag GetUpdateFlags();
|
||||||
|
|
||||||
double NearestZeroCrossing(double t0);
|
double NearestZeroCrossing(double t0);
|
||||||
|
|
||||||
|
@ -243,10 +243,31 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetScrollbar(int position, int thumbSize,
|
||||||
|
int range, int pageSize,
|
||||||
|
bool refresh = true) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ScrollBar::SetScrollbar(int position, int thumbSize,
|
||||||
|
int range, int pageSize,
|
||||||
|
bool refresh)
|
||||||
|
{
|
||||||
|
// Mitigate flashing of scrollbars by refreshing only when something really changes.
|
||||||
|
|
||||||
|
auto changed =
|
||||||
|
position != GetThumbPosition() ||
|
||||||
|
thumbSize != GetThumbSize() ||
|
||||||
|
range != GetRange() ||
|
||||||
|
pageSize != GetPageSize();
|
||||||
|
if (!changed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxScrollBar::SetScrollbar(position, thumbSize, range, pageSize, refresh);
|
||||||
|
}
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(ScrollBar, wxScrollBar)
|
BEGIN_EVENT_TABLE(ScrollBar, wxScrollBar)
|
||||||
EVT_SET_FOCUS(ScrollBar::OnSetFocus)
|
EVT_SET_FOCUS(ScrollBar::OnSetFocus)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
@ -933,14 +954,18 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
|
|||||||
mCursorOverlay = std::make_unique<EditCursorOverlay>(this);
|
mCursorOverlay = std::make_unique<EditCursorOverlay>(this);
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||||
// This must follow construction of *mIndicatorOverlay, because it must
|
|
||||||
// attach its timer event handler later (so that its handler is invoked
|
|
||||||
// earlier)
|
|
||||||
mScrubOverlay = std::make_unique<ScrubbingOverlay>(this);
|
mScrubOverlay = std::make_unique<ScrubbingOverlay>(this);
|
||||||
mScrubber = std::make_unique<Scrubber>(this);
|
mScrubber = std::make_unique<Scrubber>(this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This must follow construction of *mScrubOverlay, because it must
|
// More order dependencies here...
|
||||||
|
// This must follow construction of *mIndicatorOverlay, because it must
|
||||||
|
// attach its timer event handler later (so that its handler is invoked
|
||||||
|
// earlier)
|
||||||
|
mPlaybackScroller = std::make_unique<PlaybackScroller>(this);
|
||||||
|
|
||||||
|
// This must follow construction of *mPlaybackScroller,
|
||||||
|
// because it must
|
||||||
// attach its timer event handler later (so that its handler is invoked
|
// attach its timer event handler later (so that its handler is invoked
|
||||||
// earlier)
|
// earlier)
|
||||||
this->Connect(EVT_TRACK_PANEL_TIMER,
|
this->Connect(EVT_TRACK_PANEL_TIMER,
|
||||||
@ -1771,7 +1796,6 @@ void AudacityProject::FixScrollbars()
|
|||||||
|
|
||||||
mHsbar->SetScrollbar(scaledSbarH + offset, scaledSbarScreen, scaledSbarTotal,
|
mHsbar->SetScrollbar(scaledSbarH + offset, scaledSbarScreen, scaledSbarTotal,
|
||||||
scaledSbarScreen, TRUE);
|
scaledSbarScreen, TRUE);
|
||||||
mHsbar->Refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertical scrollbar
|
// Vertical scrollbar
|
||||||
@ -1779,7 +1803,6 @@ void AudacityProject::FixScrollbars()
|
|||||||
panelHeight / mViewInfo.scrollStep,
|
panelHeight / mViewInfo.scrollStep,
|
||||||
totalHeight / mViewInfo.scrollStep,
|
totalHeight / mViewInfo.scrollStep,
|
||||||
panelHeight / mViewInfo.scrollStep, TRUE);
|
panelHeight / mViewInfo.scrollStep, TRUE);
|
||||||
mVsbar->Refresh();
|
|
||||||
|
|
||||||
if (refresh || (rescroll &&
|
if (refresh || (rescroll &&
|
||||||
(GetScreenEndTime() - mViewInfo.h) < mViewInfo.total)) {
|
(GetScreenEndTime() - mViewInfo.h) < mViewInfo.total)) {
|
||||||
@ -2049,11 +2072,12 @@ void AudacityProject::OnScroll(wxScrollEvent & WXUNUSED(event))
|
|||||||
/// Determines if flags for command are compatible with current state.
|
/// Determines if flags for command are compatible with current state.
|
||||||
/// If not, then try some recovery action to make it so.
|
/// If not, then try some recovery action to make it so.
|
||||||
/// @return whether compatible or not after any actions taken.
|
/// @return whether compatible or not after any actions taken.
|
||||||
bool AudacityProject::TryToMakeActionAllowed( wxUint32 & flags, wxUint32 flagsRqd, wxUint32 mask )
|
bool AudacityProject::TryToMakeActionAllowed
|
||||||
|
( CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask )
|
||||||
{
|
{
|
||||||
bool bAllowed;
|
bool bAllowed;
|
||||||
|
|
||||||
if( flags == 0 )
|
if( !flags )
|
||||||
flags = GetUpdateFlags();
|
flags = GetUpdateFlags();
|
||||||
|
|
||||||
bAllowed = ((flags & mask) == (flagsRqd & mask));
|
bAllowed = ((flags & mask) == (flagsRqd & mask));
|
||||||
@ -2065,12 +2089,12 @@ bool AudacityProject::TryToMakeActionAllowed( wxUint32 & flags, wxUint32 flagsRq
|
|||||||
if( !mSelectAllOnNone )
|
if( !mSelectAllOnNone )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wxUint32 MissingFlags = (flags & ~flagsRqd) & mask;
|
auto MissingFlags = (flags & ~flagsRqd) & mask;
|
||||||
|
|
||||||
// IF selecting all audio won't do any good, THEN return with failure.
|
// IF selecting all audio won't do any good, THEN return with failure.
|
||||||
if( (flags & WaveTracksExistFlag) == 0 )
|
if( !(flags & WaveTracksExistFlag) )
|
||||||
return false;
|
return false;
|
||||||
if( (MissingFlags & ~( TimeSelectedFlag | WaveTracksSelectedFlag))!=0)
|
if( (MissingFlags & ~( TimeSelectedFlag | WaveTracksSelectedFlag)) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
OnSelectAll();
|
OnSelectAll();
|
||||||
@ -2084,7 +2108,7 @@ void AudacityProject::OnMenu(wxCommandEvent & event)
|
|||||||
|
|
||||||
bool handled = mCommandManager.HandleMenuID(event.GetId(),
|
bool handled = mCommandManager.HandleMenuID(event.GetId(),
|
||||||
GetUpdateFlags(),
|
GetUpdateFlags(),
|
||||||
0xFFFFFFFF);
|
NoFlagsSpecifed);
|
||||||
|
|
||||||
if (handled)
|
if (handled)
|
||||||
event.Skip(false);
|
event.Skip(false);
|
||||||
@ -5315,3 +5339,46 @@ int AudacityProject::GetEstimatedRecordingMinsLeftOnDisk() {
|
|||||||
int iRecMins = (int)(dRecTime / 60.0);
|
int iRecMins = (int)(dRecTime / 60.0);
|
||||||
return iRecMins;
|
return iRecMins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudacityProject::PlaybackScroller::PlaybackScroller(AudacityProject *project)
|
||||||
|
: mProject(project)
|
||||||
|
{
|
||||||
|
mProject->Connect(EVT_TRACK_PANEL_TIMER,
|
||||||
|
wxCommandEventHandler(PlaybackScroller::OnTimer),
|
||||||
|
NULL,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
AudacityProject::PlaybackScroller::~PlaybackScroller()
|
||||||
|
{
|
||||||
|
mProject->Disconnect(EVT_TRACK_PANEL_TIMER,
|
||||||
|
wxCommandEventHandler(PlaybackScroller::OnTimer),
|
||||||
|
NULL,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::PlaybackScroller::OnTimer(wxCommandEvent &event)
|
||||||
|
{
|
||||||
|
// Let other listeners get the notification
|
||||||
|
event.Skip();
|
||||||
|
|
||||||
|
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||||
|
if (mActive && mProject->IsAudioActive())
|
||||||
|
{
|
||||||
|
// Pan the view, so that we center the play indicator.
|
||||||
|
|
||||||
|
ViewInfo &viewInfo = mProject->GetViewInfo();
|
||||||
|
TrackPanel *const trackPanel = mProject->GetTrackPanel();
|
||||||
|
const int posX = viewInfo.TimeToPosition(viewInfo.mRecentStreamTime);
|
||||||
|
int width;
|
||||||
|
trackPanel->GetTracksUsableArea(&width, NULL);
|
||||||
|
const int deltaX = posX - width / 2;
|
||||||
|
viewInfo.h =
|
||||||
|
viewInfo.OffsetTimeByPixels(viewInfo.h, deltaX, true);
|
||||||
|
if (!viewInfo.bScrollBeyondZero)
|
||||||
|
// Can't scroll too far left
|
||||||
|
viewInfo.h = std::max(0.0, viewInfo.h);
|
||||||
|
trackPanel->Refresh(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -504,7 +504,8 @@ public:
|
|||||||
void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override;
|
void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override;
|
||||||
|
|
||||||
// Command Handling
|
// Command Handling
|
||||||
bool TryToMakeActionAllowed( wxUint32 & flags, wxUint32 flagsRqd, wxUint32 mask );
|
bool TryToMakeActionAllowed
|
||||||
|
( CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask );
|
||||||
|
|
||||||
///Prevents DELETE from external thread - for e.g. use of GetActiveProject
|
///Prevents DELETE from external thread - for e.g. use of GetActiveProject
|
||||||
static void AllProjectsDeleteLock();
|
static void AllProjectsDeleteLock();
|
||||||
@ -580,7 +581,7 @@ public:
|
|||||||
|
|
||||||
CommandManager mCommandManager;
|
CommandManager mCommandManager;
|
||||||
|
|
||||||
wxUint32 mLastFlags;
|
CommandFlag mLastFlags;
|
||||||
|
|
||||||
// Window elements
|
// Window elements
|
||||||
|
|
||||||
@ -720,6 +721,28 @@ public:
|
|||||||
const Scrubber &GetScrubber() const { return *mScrubber; }
|
const Scrubber &GetScrubber() const { return *mScrubber; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class PlaybackScroller final : public wxEvtHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit PlaybackScroller(AudacityProject *project);
|
||||||
|
~PlaybackScroller();
|
||||||
|
|
||||||
|
void Activate(bool active)
|
||||||
|
{
|
||||||
|
mActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnTimer(wxCommandEvent &event);
|
||||||
|
|
||||||
|
AudacityProject *mProject;
|
||||||
|
bool mActive { false };
|
||||||
|
};
|
||||||
|
std::unique_ptr<PlaybackScroller> mPlaybackScroller;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PlaybackScroller &GetPlaybackScroller() { return *mPlaybackScroller; }
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
8321
src/ThemeAsCeeCode.h
8321
src/ThemeAsCeeCode.h
File diff suppressed because it is too large
Load Diff
@ -1015,6 +1015,25 @@ void TrackPanel::ScrollDuringDrag()
|
|||||||
mAutoScrolling = true;
|
mAutoScrolling = true;
|
||||||
mListener->TP_ScrollLeft();
|
mListener->TP_ScrollLeft();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// Bug1387: enable autoscroll during drag, if the pointer is at either extreme x
|
||||||
|
// coordinate of the screen, even if that is still within the track area.
|
||||||
|
|
||||||
|
int xx = mMouseMostRecentX, yy = 0;
|
||||||
|
this->ClientToScreen(&xx, &yy);
|
||||||
|
if (xx == 0) {
|
||||||
|
mAutoScrolling = true;
|
||||||
|
mListener->TP_ScrollLeft();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int width, height;
|
||||||
|
::wxDisplaySize(&width, &height);
|
||||||
|
if (xx == width - 1) {
|
||||||
|
mAutoScrolling = true;
|
||||||
|
mListener->TP_ScrollRight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mAutoScrolling) {
|
if (mAutoScrolling) {
|
||||||
// AS: To keep the selection working properly as we scroll,
|
// AS: To keep the selection working properly as we scroll,
|
||||||
@ -5901,16 +5920,26 @@ void TrackPanel::OnMouseEvent(wxMouseEvent & event)
|
|||||||
ReleaseMouse();
|
ReleaseMouse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.Leaving() && !event.ButtonIsDown(wxMOUSE_BTN_ANY))
|
if (event.Leaving())
|
||||||
{
|
{
|
||||||
|
|
||||||
// PRL: was this test really needed? It interfered with my refactoring
|
// PRL: was this test really needed? It interfered with my refactoring
|
||||||
// that tried to eliminate those enum values.
|
// that tried to eliminate those enum values.
|
||||||
// I think it was never true, that mouse capture was pan or gain sliding,
|
// I think it was never true, that mouse capture was pan or gain sliding,
|
||||||
// but no mouse button was down.
|
// but no mouse button was down.
|
||||||
// if (mMouseCapture != IsPanSliding && mMouseCapture != IsGainSliding)
|
// if (mMouseCapture != IsPanSliding && mMouseCapture != IsGainSliding)
|
||||||
{
|
|
||||||
|
auto buttons =
|
||||||
|
// Bug 1325: button state in Leaving events is unreliable on Mac.
|
||||||
|
// Poll the global state instead.
|
||||||
|
// event.ButtonIsDown(wxMOUSE_BTN_ANY);
|
||||||
|
::wxGetMouseState().ButtonIsDown(wxMOUSE_BTN_ANY);
|
||||||
|
|
||||||
|
if(!buttons) {
|
||||||
SetCapturedTrack(NULL);
|
SetCapturedTrack(NULL);
|
||||||
|
|
||||||
#if defined(__WXMAC__)
|
#if defined(__WXMAC__)
|
||||||
|
|
||||||
// We must install the cursor ourselves since the window under
|
// We must install the cursor ourselves since the window under
|
||||||
// the mouse is no longer this one and wx2.8.12 makes that check.
|
// the mouse is no longer this one and wx2.8.12 makes that check.
|
||||||
// Should re-evaluate with wx3.
|
// Should re-evaluate with wx3.
|
||||||
|
@ -395,8 +395,8 @@ CommandManager::CommandManager():
|
|||||||
mCurrentID(17000),
|
mCurrentID(17000),
|
||||||
mCurrentMenuName(COMMAND),
|
mCurrentMenuName(COMMAND),
|
||||||
mCurrentMenu(NULL),
|
mCurrentMenu(NULL),
|
||||||
mDefaultFlags(0),
|
mDefaultFlags(AlwaysEnabledFlag),
|
||||||
mDefaultMask(0)
|
mDefaultMask(AlwaysEnabledFlag)
|
||||||
{
|
{
|
||||||
mbSeparatorAllowed = false;
|
mbSeparatorAllowed = false;
|
||||||
}
|
}
|
||||||
@ -647,15 +647,15 @@ void CommandManager::AddCheck(const wxChar *name,
|
|||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
int checkmark)
|
int checkmark)
|
||||||
{
|
{
|
||||||
AddItem(name, label, callback, wxT(""), (unsigned int)NoFlagsSpecifed, (unsigned int)NoFlagsSpecifed, checkmark);
|
AddItem(name, label, callback, wxT(""), NoFlagsSpecifed, NoFlagsSpecifed, checkmark);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::AddCheck(const wxChar *name,
|
void CommandManager::AddCheck(const wxChar *name,
|
||||||
const wxChar *label,
|
const wxChar *label,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
int checkmark,
|
int checkmark,
|
||||||
unsigned int flags,
|
CommandFlag flags,
|
||||||
unsigned int mask)
|
CommandMask mask)
|
||||||
{
|
{
|
||||||
AddItem(name, label, callback, wxT(""), flags, mask, checkmark);
|
AddItem(name, label, callback, wxT(""), flags, mask, checkmark);
|
||||||
}
|
}
|
||||||
@ -663,8 +663,8 @@ void CommandManager::AddCheck(const wxChar *name,
|
|||||||
void CommandManager::AddItem(const wxChar *name,
|
void CommandManager::AddItem(const wxChar *name,
|
||||||
const wxChar *label,
|
const wxChar *label,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
unsigned int flags,
|
CommandFlag flags,
|
||||||
unsigned int mask)
|
CommandMask mask)
|
||||||
{
|
{
|
||||||
AddItem(name, label, callback, wxT(""), flags, mask);
|
AddItem(name, label, callback, wxT(""), flags, mask);
|
||||||
}
|
}
|
||||||
@ -673,8 +673,8 @@ void CommandManager::AddItem(const wxChar *name,
|
|||||||
const wxChar *label_in,
|
const wxChar *label_in,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
const wxChar *accel,
|
const wxChar *accel,
|
||||||
unsigned int flags,
|
CommandFlag flags,
|
||||||
unsigned int mask,
|
CommandMask mask,
|
||||||
int checkmark)
|
int checkmark)
|
||||||
{
|
{
|
||||||
CommandListEntry *entry = NewIdentifier(name, label_in, accel, CurrentMenu(), callback, false, 0, 0);
|
CommandListEntry *entry = NewIdentifier(name, label_in, accel, CurrentMenu(), callback, false, 0, 0);
|
||||||
@ -726,8 +726,8 @@ void CommandManager::AddItemList(const wxString & name,
|
|||||||
void CommandManager::AddCommand(const wxChar *name,
|
void CommandManager::AddCommand(const wxChar *name,
|
||||||
const wxChar *label,
|
const wxChar *label,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
unsigned int flags,
|
CommandFlag flags,
|
||||||
unsigned int mask)
|
CommandMask mask)
|
||||||
{
|
{
|
||||||
AddCommand(name, label, callback, wxT(""), flags, mask);
|
AddCommand(name, label, callback, wxT(""), flags, mask);
|
||||||
}
|
}
|
||||||
@ -736,8 +736,8 @@ void CommandManager::AddCommand(const wxChar *name,
|
|||||||
const wxChar *label_in,
|
const wxChar *label_in,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
const wxChar *accel,
|
const wxChar *accel,
|
||||||
unsigned int flags,
|
CommandFlag flags,
|
||||||
unsigned int mask)
|
CommandMask mask)
|
||||||
{
|
{
|
||||||
NewIdentifier(name, label_in, accel, NULL, callback, false, 0, 0);
|
NewIdentifier(name, label_in, accel, NULL, callback, false, 0, 0);
|
||||||
|
|
||||||
@ -755,8 +755,8 @@ void CommandManager::AddGlobalCommand(const wxChar *name,
|
|||||||
|
|
||||||
entry->enabled = false;
|
entry->enabled = false;
|
||||||
entry->isGlobal = true;
|
entry->isGlobal = true;
|
||||||
entry->flags = 0;
|
entry->flags = AlwaysEnabledFlag;
|
||||||
entry->mask = 0;
|
entry->mask = AlwaysEnabledFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::AddSeparator()
|
void CommandManager::AddSeparator()
|
||||||
@ -978,13 +978,13 @@ void CommandManager::Enable(const wxString &name, bool enabled)
|
|||||||
Enable(entry, enabled);
|
Enable(entry, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::EnableUsingFlags(wxUint32 flags, wxUint32 mask)
|
void CommandManager::EnableUsingFlags(CommandFlag flags, CommandMask mask)
|
||||||
{
|
{
|
||||||
for(const auto &entry : mCommandList) {
|
for(const auto &entry : mCommandList) {
|
||||||
if (entry->multi && entry->index != 0)
|
if (entry->multi && entry->index != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
wxUint32 combinedMask = (mask & entry->mask);
|
auto combinedMask = (mask & entry->mask);
|
||||||
if (combinedMask) {
|
if (combinedMask) {
|
||||||
bool enable = ((flags & combinedMask) ==
|
bool enable = ((flags & combinedMask) ==
|
||||||
(entry->flags & combinedMask));
|
(entry->flags & combinedMask));
|
||||||
@ -1038,15 +1038,15 @@ void CommandManager::SetKeyFromIndex(int i, const wxString &key)
|
|||||||
entry->key = KeyStringNormalize(key);
|
entry->key = KeyStringNormalize(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::TellUserWhyDisallowed( wxUint32 flagsGot, wxUint32 flagsRequired )
|
void CommandManager::TellUserWhyDisallowed( CommandFlag flagsGot, CommandMask flagsRequired )
|
||||||
{
|
{
|
||||||
// The default string for 'reason' is a catch all. I hope it won't ever be seen
|
// The default string for 'reason' is a catch all. I hope it won't ever be seen
|
||||||
// and that we will get something more specific.
|
// and that we will get something more specific.
|
||||||
wxString reason = _("There was a problem with your last action. If you think\nthis is a bug, please tell us exactly where it occurred.");
|
wxString reason = _("There was a problem with your last action. If you think\nthis is a bug, please tell us exactly where it occurred.");
|
||||||
|
|
||||||
wxUint32 missingFlags = flagsRequired & (~flagsGot );
|
auto missingFlags = flagsRequired & (~flagsGot );
|
||||||
if( missingFlags & AudioIONotBusyFlag )
|
if( missingFlags & AudioIONotBusyFlag )
|
||||||
reason= _("You can only do this when playing and recording are\n stopped. (Pausing is not sufficient.)");
|
reason = _("You can only do this when playing and recording are\n stopped. (Pausing is not sufficient.)");
|
||||||
else if( missingFlags & StereoRequiredFlag )
|
else if( missingFlags & StereoRequiredFlag )
|
||||||
reason = _("You must first select some stereo audio for this\n to use. (You cannot use this with mono.)");
|
reason = _("You must first select some stereo audio for this\n to use. (You cannot use this with mono.)");
|
||||||
else if( missingFlags & TimeSelectedFlag )
|
else if( missingFlags & TimeSelectedFlag )
|
||||||
@ -1081,7 +1081,7 @@ bool CommandManager::FilterKeyEvent(AudacityProject *project, const wxKeyEvent &
|
|||||||
// enable them temporarily and then disable them again after handling.
|
// enable them temporarily and then disable them again after handling.
|
||||||
// LL: Why do they need to be disabled???
|
// LL: Why do they need to be disabled???
|
||||||
entry->enabled = true;
|
entry->enabled = true;
|
||||||
bool ret = HandleCommandEntry(entry, 0xffffffff, 0xffffffff, &evt);
|
bool ret = HandleCommandEntry(entry, NoFlagsSpecifed, NoFlagsSpecifed, &evt);
|
||||||
entry->enabled = false;
|
entry->enabled = false;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1094,7 +1094,7 @@ bool CommandManager::FilterKeyEvent(AudacityProject *project, const wxKeyEvent &
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxUint32 flags = project->GetUpdateFlags();
|
auto flags = project->GetUpdateFlags();
|
||||||
|
|
||||||
wxKeyEvent temp = evt;
|
wxKeyEvent temp = evt;
|
||||||
|
|
||||||
@ -1105,12 +1105,12 @@ bool CommandManager::FilterKeyEvent(AudacityProject *project, const wxKeyEvent &
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return HandleCommandEntry(entry, flags, 0xffffffff, &temp);
|
return HandleCommandEntry(entry, flags, NoFlagsSpecifed, &temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == wxEVT_KEY_UP && entry->wantKeyup)
|
if (type == wxEVT_KEY_UP && entry->wantKeyup)
|
||||||
{
|
{
|
||||||
return HandleCommandEntry(entry, flags, 0xffffffff, &temp);
|
return HandleCommandEntry(entry, flags, NoFlagsSpecifed, &temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -1120,12 +1120,13 @@ bool CommandManager::FilterKeyEvent(AudacityProject *project, const wxKeyEvent &
|
|||||||
/// returning true iff successful. If you pass any flags,
|
/// returning true iff successful. If you pass any flags,
|
||||||
///the command won't be executed unless the flags are compatible
|
///the command won't be executed unless the flags are compatible
|
||||||
///with the command's flags.
|
///with the command's flags.
|
||||||
bool CommandManager::HandleCommandEntry(const CommandListEntry * entry, wxUint32 flags, wxUint32 mask, const wxEvent * evt)
|
bool CommandManager::HandleCommandEntry(const CommandListEntry * entry,
|
||||||
|
CommandFlag flags, CommandMask mask, const wxEvent * evt)
|
||||||
{
|
{
|
||||||
if (!entry || !entry->enabled)
|
if (!entry || !entry->enabled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wxUint32 combinedMask = (mask & entry->mask);
|
auto combinedMask = (mask & entry->mask);
|
||||||
if (combinedMask) {
|
if (combinedMask) {
|
||||||
|
|
||||||
AudacityProject * proj;
|
AudacityProject * proj;
|
||||||
@ -1154,7 +1155,7 @@ bool CommandManager::HandleCommandEntry(const CommandListEntry * entry, wxUint32
|
|||||||
///CommandManagerListener function. If you pass any flags,
|
///CommandManagerListener function. If you pass any flags,
|
||||||
///the command won't be executed unless the flags are compatible
|
///the command won't be executed unless the flags are compatible
|
||||||
///with the command's flags.
|
///with the command's flags.
|
||||||
bool CommandManager::HandleMenuID(int id, wxUint32 flags, wxUint32 mask)
|
bool CommandManager::HandleMenuID(int id, CommandFlag flags, CommandMask mask)
|
||||||
{
|
{
|
||||||
CommandListEntry *entry = mCommandIDHash[id];
|
CommandListEntry *entry = mCommandIDHash[id];
|
||||||
return HandleCommandEntry( entry, flags, mask );
|
return HandleCommandEntry( entry, flags, mask );
|
||||||
@ -1163,7 +1164,7 @@ bool CommandManager::HandleMenuID(int id, wxUint32 flags, wxUint32 mask)
|
|||||||
/// HandleTextualCommand() allows us a limitted version of script/batch
|
/// HandleTextualCommand() allows us a limitted version of script/batch
|
||||||
/// behavior, since we can get from a string command name to the actual
|
/// behavior, since we can get from a string command name to the actual
|
||||||
/// code to run.
|
/// code to run.
|
||||||
bool CommandManager::HandleTextualCommand(wxString & Str, wxUint32 flags, wxUint32 mask)
|
bool CommandManager::HandleTextualCommand(wxString & Str, CommandFlag flags, CommandMask mask)
|
||||||
{
|
{
|
||||||
// Linear search for now...
|
// Linear search for now...
|
||||||
for (const auto &entry : mCommandList)
|
for (const auto &entry : mCommandList)
|
||||||
@ -1410,14 +1411,14 @@ void CommandManager::WriteXML(XMLWriter &xmlFile)
|
|||||||
xmlFile.EndTag(wxT("audacitykeyboard"));
|
xmlFile.EndTag(wxT("audacitykeyboard"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::SetDefaultFlags(wxUint32 flags, wxUint32 mask)
|
void CommandManager::SetDefaultFlags(CommandFlag flags, CommandMask mask)
|
||||||
{
|
{
|
||||||
mDefaultFlags = flags;
|
mDefaultFlags = flags;
|
||||||
mDefaultMask = mask;
|
mDefaultMask = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::SetCommandFlags(const wxString &name,
|
void CommandManager::SetCommandFlags(const wxString &name,
|
||||||
wxUint32 flags, wxUint32 mask)
|
CommandFlag flags, CommandMask mask)
|
||||||
{
|
{
|
||||||
CommandListEntry *entry = mCommandNameHash[name];
|
CommandListEntry *entry = mCommandNameHash[name];
|
||||||
if (entry) {
|
if (entry) {
|
||||||
@ -1427,7 +1428,7 @@ void CommandManager::SetCommandFlags(const wxString &name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::SetCommandFlags(const wxChar **names,
|
void CommandManager::SetCommandFlags(const wxChar **names,
|
||||||
wxUint32 flags, wxUint32 mask)
|
CommandFlag flags, CommandMask mask)
|
||||||
{
|
{
|
||||||
const wxChar **nptr = names;
|
const wxChar **nptr = names;
|
||||||
while(*nptr) {
|
while(*nptr) {
|
||||||
@ -1436,7 +1437,7 @@ void CommandManager::SetCommandFlags(const wxChar **names,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::SetCommandFlags(wxUint32 flags, wxUint32 mask, ...)
|
void CommandManager::SetCommandFlags(CommandFlag flags, CommandMask mask, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list, mask);
|
va_start(list, mask);
|
||||||
|
@ -66,8 +66,8 @@ struct CommandListEntry
|
|||||||
bool skipKeydown;
|
bool skipKeydown;
|
||||||
bool wantKeyup;
|
bool wantKeyup;
|
||||||
bool isGlobal;
|
bool isGlobal;
|
||||||
wxUint32 flags;
|
CommandFlag flags;
|
||||||
wxUint32 mask;
|
CommandMask mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
using MenuBarList = std::vector < MenuBarListEntry >;
|
using MenuBarList = std::vector < MenuBarListEntry >;
|
||||||
@ -132,21 +132,21 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
|
|||||||
const wxChar *label,
|
const wxChar *label,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
int checkmark,
|
int checkmark,
|
||||||
unsigned int flags,
|
CommandFlag flags,
|
||||||
unsigned int mask);
|
CommandMask mask);
|
||||||
|
|
||||||
void AddItem(const wxChar *name,
|
void AddItem(const wxChar *name,
|
||||||
const wxChar *label,
|
const wxChar *label,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
unsigned int flags = NoFlagsSpecifed,
|
CommandFlag flags = NoFlagsSpecifed,
|
||||||
unsigned int mask = NoFlagsSpecifed);
|
CommandMask mask = NoFlagsSpecifed);
|
||||||
|
|
||||||
void AddItem(const wxChar *name,
|
void AddItem(const wxChar *name,
|
||||||
const wxChar *label_in,
|
const wxChar *label_in,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
const wxChar *accel,
|
const wxChar *accel,
|
||||||
unsigned int flags = NoFlagsSpecifed,
|
CommandFlag flags = NoFlagsSpecifed,
|
||||||
unsigned int mask = NoFlagsSpecifed,
|
CommandMask mask = NoFlagsSpecifed,
|
||||||
int checkmark = -1);
|
int checkmark = -1);
|
||||||
|
|
||||||
void AddSeparator();
|
void AddSeparator();
|
||||||
@ -156,15 +156,15 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
|
|||||||
void AddCommand(const wxChar *name,
|
void AddCommand(const wxChar *name,
|
||||||
const wxChar *label,
|
const wxChar *label,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
unsigned int flags = NoFlagsSpecifed,
|
CommandFlag flags = NoFlagsSpecifed,
|
||||||
unsigned int mask = NoFlagsSpecifed);
|
CommandMask mask = NoFlagsSpecifed);
|
||||||
|
|
||||||
void AddCommand(const wxChar *name,
|
void AddCommand(const wxChar *name,
|
||||||
const wxChar *label,
|
const wxChar *label,
|
||||||
const CommandFunctorPointer &callback,
|
const CommandFunctorPointer &callback,
|
||||||
const wxChar *accel,
|
const wxChar *accel,
|
||||||
unsigned int flags = NoFlagsSpecifed,
|
CommandFlag flags = NoFlagsSpecifed,
|
||||||
unsigned int mask = NoFlagsSpecifed);
|
CommandMask mask = NoFlagsSpecifed);
|
||||||
|
|
||||||
void AddGlobalCommand(const wxChar *name,
|
void AddGlobalCommand(const wxChar *name,
|
||||||
const wxChar *label,
|
const wxChar *label,
|
||||||
@ -175,21 +175,21 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
|
|||||||
//
|
//
|
||||||
|
|
||||||
// For NEW items/commands
|
// For NEW items/commands
|
||||||
void SetDefaultFlags(wxUint32 flags, wxUint32 mask);
|
void SetDefaultFlags(CommandFlag flags, CommandMask mask);
|
||||||
wxUint32 GetDefaultFlags() const { return mDefaultFlags; }
|
CommandFlag GetDefaultFlags() const { return mDefaultFlags; }
|
||||||
wxUint32 GetDefaultMask() const { return mDefaultMask; }
|
CommandMask GetDefaultMask() const { return mDefaultMask; }
|
||||||
|
|
||||||
void SetCommandFlags(const wxString &name, wxUint32 flags, wxUint32 mask);
|
void SetCommandFlags(const wxString &name, CommandFlag flags, CommandMask mask);
|
||||||
void SetCommandFlags(const wxChar **names,
|
void SetCommandFlags(const wxChar **names,
|
||||||
wxUint32 flags, wxUint32 mask);
|
CommandFlag flags, CommandMask mask);
|
||||||
// Pass multiple command names as const wxChar *, terminated by NULL
|
// Pass multiple command names as const wxChar *, terminated by NULL
|
||||||
void SetCommandFlags(wxUint32 flags, wxUint32 mask, ...);
|
void SetCommandFlags(CommandFlag flags, CommandMask mask, ...);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Modifying menus
|
// Modifying menus
|
||||||
//
|
//
|
||||||
|
|
||||||
void EnableUsingFlags(wxUint32 flags, wxUint32 mask);
|
void EnableUsingFlags(CommandFlag flags, CommandMask mask);
|
||||||
void Enable(const wxString &name, bool enabled);
|
void Enable(const wxString &name, bool enabled);
|
||||||
void Check(const wxString &name, bool checked);
|
void Check(const wxString &name, bool checked);
|
||||||
void Modify(const wxString &name, const wxString &newLabel);
|
void Modify(const wxString &name, const wxString &newLabel);
|
||||||
@ -208,8 +208,8 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
|
|||||||
// "permit" allows filtering even if the active window isn't a child of the project.
|
// "permit" allows filtering even if the active window isn't a child of the project.
|
||||||
// Lyrics and MixerTrackCluster classes use it.
|
// Lyrics and MixerTrackCluster classes use it.
|
||||||
bool FilterKeyEvent(AudacityProject *project, const wxKeyEvent & evt, bool permit = false);
|
bool FilterKeyEvent(AudacityProject *project, const wxKeyEvent & evt, bool permit = false);
|
||||||
bool HandleMenuID(int id, wxUint32 flags, wxUint32 mask);
|
bool HandleMenuID(int id, CommandFlag flags, CommandMask mask);
|
||||||
bool HandleTextualCommand(wxString & Str, wxUint32 flags, wxUint32 mask);
|
bool HandleTextualCommand(wxString & Str, CommandFlag flags, CommandMask mask);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Accessing
|
// Accessing
|
||||||
@ -271,8 +271,8 @@ protected:
|
|||||||
// Executing commands
|
// Executing commands
|
||||||
//
|
//
|
||||||
|
|
||||||
bool HandleCommandEntry(const CommandListEntry * entry, wxUint32 flags, wxUint32 mask, const wxEvent * evt = NULL);
|
bool HandleCommandEntry(const CommandListEntry * entry, CommandFlag flags, CommandMask mask, const wxEvent * evt = NULL);
|
||||||
void TellUserWhyDisallowed(wxUint32 flagsGot, wxUint32 flagsRequired);
|
void TellUserWhyDisallowed(CommandFlag flagsGot, CommandFlag flagsRequired);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Modifying
|
// Modifying
|
||||||
@ -313,8 +313,8 @@ private:
|
|||||||
wxString mCurrentMenuName;
|
wxString mCurrentMenuName;
|
||||||
wxMenu * mCurrentMenu;
|
wxMenu * mCurrentMenu;
|
||||||
|
|
||||||
wxUint32 mDefaultFlags;
|
CommandFlag mDefaultFlags;
|
||||||
wxUint32 mDefaultMask;
|
CommandMask mDefaultMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,7 +38,7 @@ bool ExecMenuCommand::Apply(CommandExecutionContext context)
|
|||||||
CommandManager *cmdManager = context.GetProject()->GetCommandManager();
|
CommandManager *cmdManager = context.GetProject()->GetCommandManager();
|
||||||
|
|
||||||
wxString cmdName = GetString(wxT("CommandName"));
|
wxString cmdName = GetString(wxT("CommandName"));
|
||||||
wxUint32 cmdFlags = 0; // TODO ?
|
auto cmdFlags = AlwaysEnabledFlag; // TODO ?
|
||||||
wxUint32 cmdMask = 0;
|
auto cmdMask = AlwaysEnabledFlag;
|
||||||
return cmdManager->HandleTextualCommand(cmdName, cmdFlags, cmdMask);
|
return cmdManager->HandleTextualCommand(cmdName, cmdFlags, cmdMask);
|
||||||
}
|
}
|
||||||
|
@ -3219,7 +3219,7 @@ void EffectUIHost::OnApply(wxCommandEvent & evt)
|
|||||||
// Honor the "select all if none" preference...a little hackish, but whatcha gonna do...
|
// Honor the "select all if none" preference...a little hackish, but whatcha gonna do...
|
||||||
if (!mIsBatch && mEffect->GetType() != EffectTypeGenerate && mProject->mViewInfo.selectedRegion.isPoint())
|
if (!mIsBatch && mEffect->GetType() != EffectTypeGenerate && mProject->mViewInfo.selectedRegion.isPoint())
|
||||||
{
|
{
|
||||||
wxUint32 flags = 0;
|
auto flags = AlwaysEnabledFlag;
|
||||||
bool allowed = mProject->TryToMakeActionAllowed(flags,
|
bool allowed = mProject->TryToMakeActionAllowed(flags,
|
||||||
WaveTracksSelectedFlag | TimeSelectedFlag,
|
WaveTracksSelectedFlag | TimeSelectedFlag,
|
||||||
WaveTracksSelectedFlag | TimeSelectedFlag);
|
WaveTracksSelectedFlag | TimeSelectedFlag);
|
||||||
|
@ -738,16 +738,24 @@ void ControlToolBar::OnKeyEvent(wxKeyEvent & event)
|
|||||||
|
|
||||||
void ControlToolBar::OnPlay(wxCommandEvent & WXUNUSED(evt))
|
void ControlToolBar::OnPlay(wxCommandEvent & WXUNUSED(evt))
|
||||||
{
|
{
|
||||||
if (!CanStopAudioStream())
|
auto doubleClicked = mPlay->IsDoubleClicked();
|
||||||
return;
|
mPlay->ClearDoubleClicked();
|
||||||
|
|
||||||
StopPlaying();
|
auto p = GetActiveProject();
|
||||||
|
|
||||||
AudacityProject *p = GetActiveProject();
|
if (doubleClicked)
|
||||||
if (p) p->TP_DisplaySelection();
|
p->GetPlaybackScroller().Activate(true);
|
||||||
|
else {
|
||||||
|
if (!CanStopAudioStream())
|
||||||
|
return;
|
||||||
|
|
||||||
PlayDefault();
|
StopPlaying();
|
||||||
UpdateStatusBar(GetActiveProject());
|
|
||||||
|
if (p) p->TP_DisplaySelection();
|
||||||
|
|
||||||
|
PlayDefault();
|
||||||
|
UpdateStatusBar(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlToolBar::OnStop(wxCommandEvent & WXUNUSED(evt))
|
void ControlToolBar::OnStop(wxCommandEvent & WXUNUSED(evt))
|
||||||
@ -778,9 +786,11 @@ void ControlToolBar::StopPlaying(bool stopStream /* = true*/)
|
|||||||
{
|
{
|
||||||
AudacityProject *project = GetActiveProject();
|
AudacityProject *project = GetActiveProject();
|
||||||
|
|
||||||
if(project)
|
if(project) {
|
||||||
|
project->GetPlaybackScroller().Activate(false);
|
||||||
// Let scrubbing code do some appearance change
|
// Let scrubbing code do some appearance change
|
||||||
project->GetScrubber().StopScrubbing();
|
project->GetScrubber().StopScrubbing();
|
||||||
|
}
|
||||||
|
|
||||||
if (!CanStopAudioStream())
|
if (!CanStopAudioStream())
|
||||||
return;
|
return;
|
||||||
|
@ -474,11 +474,24 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview)
|
|||||||
// Come here from button clicks only
|
// Come here from button clicks only
|
||||||
void TranscriptionToolBar::OnPlaySpeed(wxCommandEvent & WXUNUSED(event))
|
void TranscriptionToolBar::OnPlaySpeed(wxCommandEvent & WXUNUSED(event))
|
||||||
{
|
{
|
||||||
// Let control have precedence over shift
|
auto button = mButtons[TTB_PlaySpeed];
|
||||||
const bool cutPreview = mButtons[TTB_PlaySpeed]->WasControlDown();
|
|
||||||
const bool looped = !cutPreview &&
|
auto doubleClicked = button->IsDoubleClicked();
|
||||||
mButtons[TTB_PlaySpeed]->WasShiftDown();
|
button->ClearDoubleClicked();
|
||||||
PlayAtSpeed(looped, cutPreview);
|
|
||||||
|
if (doubleClicked) {
|
||||||
|
GetActiveProject()->GetPlaybackScroller().Activate(true);
|
||||||
|
|
||||||
|
// Pop up the button
|
||||||
|
SetButton(false, button);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Let control have precedence over shift
|
||||||
|
const bool cutPreview = mButtons[TTB_PlaySpeed]->WasControlDown();
|
||||||
|
const bool looped = !cutPreview &&
|
||||||
|
button->WasShiftDown();
|
||||||
|
PlayAtSpeed(looped, cutPreview);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranscriptionToolBar::OnSpeedSlider(wxCommandEvent& WXUNUSED(event))
|
void TranscriptionToolBar::OnSpeedSlider(wxCommandEvent& WXUNUSED(event))
|
||||||
|
@ -8,6 +8,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
|
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
|
#include "../../Audacity.h"
|
||||||
#include "PlayIndicatorOverlay.h"
|
#include "PlayIndicatorOverlay.h"
|
||||||
|
|
||||||
#include "../../AColor.h"
|
#include "../../AColor.h"
|
||||||
|
@ -200,7 +200,7 @@ void Scrubber::MarkScrubStart(
|
|||||||
// needed for the decision to start scrubbing later when handling
|
// needed for the decision to start scrubbing later when handling
|
||||||
// drag events.
|
// drag events.
|
||||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||||
mSmoothScrollingScrub = smoothScrolling;
|
SetScrollScrubbing (smoothScrolling);
|
||||||
#endif
|
#endif
|
||||||
mAlwaysSeeking = alwaysSeeking;
|
mAlwaysSeeking = alwaysSeeking;
|
||||||
mScrubStartPosition = xx;
|
mScrubStartPosition = xx;
|
||||||
@ -356,25 +356,6 @@ void Scrubber::ContinueScrubbing()
|
|||||||
if (mScrubSpeedDisplayCountdown > 0)
|
if (mScrubSpeedDisplayCountdown > 0)
|
||||||
--mScrubSpeedDisplayCountdown;
|
--mScrubSpeedDisplayCountdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
|
||||||
if (mSmoothScrollingScrub) {
|
|
||||||
// Pan the view, so that we center the play indicator.
|
|
||||||
|
|
||||||
ViewInfo &viewInfo = mProject->GetViewInfo();
|
|
||||||
TrackPanel *const trackPanel = mProject->GetTrackPanel();
|
|
||||||
const int posX = viewInfo.TimeToPosition(viewInfo.mRecentStreamTime);
|
|
||||||
int width;
|
|
||||||
trackPanel->GetTracksUsableArea(&width, NULL);
|
|
||||||
const int deltaX = posX - width / 2;
|
|
||||||
viewInfo.h =
|
|
||||||
viewInfo.OffsetTimeByPixels(viewInfo.h, deltaX, true);
|
|
||||||
if (!viewInfo.bScrollBeyondZero)
|
|
||||||
// Can't scroll too far left
|
|
||||||
viewInfo.h = std::max(0.0, viewInfo.h);
|
|
||||||
trackPanel->Refresh(false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scrubber::StopScrubbing()
|
void Scrubber::StopScrubbing()
|
||||||
@ -382,7 +363,7 @@ void Scrubber::StopScrubbing()
|
|||||||
UncheckAllMenuItems();
|
UncheckAllMenuItems();
|
||||||
|
|
||||||
mScrubStartPosition = -1;
|
mScrubStartPosition = -1;
|
||||||
mSmoothScrollingScrub = false;
|
SetScrollScrubbing (false);
|
||||||
|
|
||||||
if (!IsScrubbing())
|
if (!IsScrubbing())
|
||||||
{
|
{
|
||||||
@ -393,6 +374,12 @@ void Scrubber::StopScrubbing()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scrubber::SetScrollScrubbing(bool scrollScrubbing)
|
||||||
|
{
|
||||||
|
mSmoothScrollingScrub = scrollScrubbing;
|
||||||
|
mProject->GetPlaybackScroller().Activate(scrollScrubbing);
|
||||||
|
}
|
||||||
|
|
||||||
bool Scrubber::IsScrubbing() const
|
bool Scrubber::IsScrubbing() const
|
||||||
{
|
{
|
||||||
if (mScrubToken <= 0)
|
if (mScrubToken <= 0)
|
||||||
@ -403,6 +390,7 @@ bool Scrubber::IsScrubbing() const
|
|||||||
const_cast<Scrubber&>(*this).mScrubToken = -1;
|
const_cast<Scrubber&>(*this).mScrubToken = -1;
|
||||||
const_cast<Scrubber&>(*this).mScrubStartPosition = -1;
|
const_cast<Scrubber&>(*this).mScrubStartPosition = -1;
|
||||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||||
|
// Don't call SetScrollScrubbing
|
||||||
const_cast<Scrubber&>(*this).mSmoothScrollingScrub = false;
|
const_cast<Scrubber&>(*this).mSmoothScrollingScrub = false;
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
@ -557,7 +545,6 @@ void ScrubbingOverlay::Draw
|
|||||||
dc.DrawText(mLastScrubSpeedText, mLastScrubRect.GetX(), mLastScrubRect.GetY());
|
dc.DrawText(mLastScrubSpeedText, mLastScrubRect.GetX(), mLastScrubRect.GetY());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ScrubbingOverlay::OnTimer(wxCommandEvent &event)
|
void ScrubbingOverlay::OnTimer(wxCommandEvent &event)
|
||||||
{
|
{
|
||||||
// Let other listeners get the notification
|
// Let other listeners get the notification
|
||||||
@ -666,7 +653,7 @@ void Scrubber::DoScrub(bool scroll, bool seek)
|
|||||||
MarkScrubStart(xx, scroll, seek);
|
MarkScrubStart(xx, scroll, seek);
|
||||||
}
|
}
|
||||||
else if(!match) {
|
else if(!match) {
|
||||||
mSmoothScrollingScrub = scroll;
|
SetScrollScrubbing(scroll);
|
||||||
mAlwaysSeeking = seek;
|
mAlwaysSeeking = seek;
|
||||||
UncheckAllMenuItems();
|
UncheckAllMenuItems();
|
||||||
CheckMenuItem();
|
CheckMenuItem();
|
||||||
|
@ -54,8 +54,11 @@ public:
|
|||||||
bool HasStartedScrubbing() const
|
bool HasStartedScrubbing() const
|
||||||
{ return GetScrubStartPosition() >= 0; }
|
{ return GetScrubStartPosition() >= 0; }
|
||||||
bool IsScrubbing() const;
|
bool IsScrubbing() const;
|
||||||
|
|
||||||
bool IsScrollScrubbing() const // If true, implies HasStartedScrubbing()
|
bool IsScrollScrubbing() const // If true, implies HasStartedScrubbing()
|
||||||
{ return mSmoothScrollingScrub; }
|
{ return mSmoothScrollingScrub; }
|
||||||
|
void SetScrollScrubbing(bool scrollScrubbing);
|
||||||
|
|
||||||
bool IsAlwaysSeeking() const
|
bool IsAlwaysSeeking() const
|
||||||
{ return mAlwaysSeeking; }
|
{ return mAlwaysSeeking; }
|
||||||
|
|
||||||
|
@ -407,6 +407,8 @@ void AButton::OnMouseEvent(wxMouseEvent & event)
|
|||||||
if (mEnabled && event.IsButton()) {
|
if (mEnabled && event.IsButton()) {
|
||||||
if (event.ButtonIsDown(wxMOUSE_BTN_ANY)) {
|
if (event.ButtonIsDown(wxMOUSE_BTN_ANY)) {
|
||||||
mIsClicking = true;
|
mIsClicking = true;
|
||||||
|
if (event.ButtonDClick())
|
||||||
|
mIsDoubleClicked = true;
|
||||||
if( !HasCapture() )
|
if( !HasCapture() )
|
||||||
CaptureMouse();
|
CaptureMouse();
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,11 @@ class AButton final : public wxWindow {
|
|||||||
bool WasControlDown(); // returns true if control was held down
|
bool WasControlDown(); // returns true if control was held down
|
||||||
// the last time the button was clicked
|
// the last time the button was clicked
|
||||||
bool IsDown(){ return mButtonIsDown;}
|
bool IsDown(){ return mButtonIsDown;}
|
||||||
|
|
||||||
|
// Double click is detected, but not automatically cleared.
|
||||||
|
bool IsDoubleClicked() const { return mIsDoubleClicked; }
|
||||||
|
void ClearDoubleClicked() { mIsDoubleClicked = false; }
|
||||||
|
|
||||||
void SetButtonToggles( bool toggler ){ mToggle = toggler;}
|
void SetButtonToggles( bool toggler ){ mToggle = toggler;}
|
||||||
void Toggle(){ mButtonIsDown ? PopUp() : PushDown();}
|
void Toggle(){ mButtonIsDown ? PopUp() : PushDown();}
|
||||||
void Click();
|
void Click();
|
||||||
@ -157,6 +162,7 @@ class AButton final : public wxWindow {
|
|||||||
bool mIsClicking;
|
bool mIsClicking;
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
bool mUseDisabledAsDownHiliteImage;
|
bool mUseDisabledAsDownHiliteImage;
|
||||||
|
bool mIsDoubleClicked {};
|
||||||
|
|
||||||
struct ImageArr { ImageRoll mArr[4]; };
|
struct ImageArr { ImageRoll mArr[4]; };
|
||||||
std::vector<ImageArr> mImages;
|
std::vector<ImageArr> mImages;
|
||||||
|
@ -467,6 +467,15 @@ void Meter::OnPaint(wxPaintEvent & WXUNUSED(event))
|
|||||||
// MixerTrackCluster style has no icon or L/R labels
|
// MixerTrackCluster style has no icon or L/R labels
|
||||||
if (mStyle != MixerTrackCluster)
|
if (mStyle != MixerTrackCluster)
|
||||||
{
|
{
|
||||||
|
bool highlight = InIcon();
|
||||||
|
if (highlight) {
|
||||||
|
auto rect = mIconRect;
|
||||||
|
rect.Inflate(gap, gap);
|
||||||
|
wxColour colour(247, 247, 247);
|
||||||
|
dc.SetBrush(colour);
|
||||||
|
dc.SetPen(colour );
|
||||||
|
dc.DrawRectangle(rect);
|
||||||
|
}
|
||||||
dc.DrawBitmap(*mIcon, mIconRect.GetPosition(), true);
|
dc.DrawBitmap(*mIcon, mIconRect.GetPosition(), true);
|
||||||
dc.SetFont(GetFont());
|
dc.SetFont(GetFont());
|
||||||
dc.DrawText(mLeftText, mLeftTextPos.x, mLeftTextPos.y);
|
dc.DrawText(mLeftText, mLeftTextPos.x, mLeftTextPos.y);
|
||||||
@ -668,8 +677,22 @@ void Meter::OnSize(wxSizeEvent & WXUNUSED(event))
|
|||||||
mLayoutValid = false;
|
mLayoutValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Meter::InIcon(wxMouseEvent *pEvent) const
|
||||||
|
{
|
||||||
|
auto point = pEvent ? pEvent->GetPosition() : ScreenToClient(::wxGetMousePosition());
|
||||||
|
return mIconRect.Contains(point);
|
||||||
|
}
|
||||||
|
|
||||||
void Meter::OnMouse(wxMouseEvent &evt)
|
void Meter::OnMouse(wxMouseEvent &evt)
|
||||||
{
|
{
|
||||||
|
bool shouldHighlight = InIcon(&evt);
|
||||||
|
if ((evt.GetEventType() == wxEVT_MOTION || evt.Entering() || evt.Leaving()) &&
|
||||||
|
(mHighlighted != shouldHighlight)) {
|
||||||
|
mHighlighted = shouldHighlight;
|
||||||
|
mLayoutValid = false;
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
if (mStyle == MixerTrackCluster) // MixerTrackCluster style has no menu.
|
if (mStyle == MixerTrackCluster) // MixerTrackCluster style has no menu.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -688,7 +711,7 @@ void Meter::OnMouse(wxMouseEvent &evt)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (evt.RightDown() ||
|
if (evt.RightDown() ||
|
||||||
(evt.ButtonDown() && mIconRect.Contains(evt.m_x, evt.m_y)))
|
(evt.ButtonDown() && InIcon(&evt)))
|
||||||
{
|
{
|
||||||
wxMenu menu;
|
wxMenu menu;
|
||||||
// Note: these should be kept in the same order as the enum
|
// Note: these should be kept in the same order as the enum
|
||||||
|
@ -186,6 +186,7 @@ class Meter final : public wxPanel
|
|||||||
void OnErase(wxEraseEvent &evt);
|
void OnErase(wxEraseEvent &evt);
|
||||||
void OnPaint(wxPaintEvent &evt);
|
void OnPaint(wxPaintEvent &evt);
|
||||||
void OnSize(wxSizeEvent &evt);
|
void OnSize(wxSizeEvent &evt);
|
||||||
|
bool InIcon(wxMouseEvent *pEvent = nullptr) const;
|
||||||
void OnMouse(wxMouseEvent &evt);
|
void OnMouse(wxMouseEvent &evt);
|
||||||
void OnKeyDown(wxKeyEvent &evt);
|
void OnKeyDown(wxKeyEvent &evt);
|
||||||
void OnKeyUp(wxKeyEvent &evt);
|
void OnKeyUp(wxKeyEvent &evt);
|
||||||
@ -280,6 +281,8 @@ class Meter final : public wxPanel
|
|||||||
|
|
||||||
friend class MeterAx;
|
friend class MeterAx;
|
||||||
|
|
||||||
|
bool mHighlighted {};
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,6 +84,9 @@ array of Ruler::Label.
|
|||||||
#include "../Snap.h"
|
#include "../Snap.h"
|
||||||
#include "../tracks/ui/Scrubbing.h"
|
#include "../tracks/ui/Scrubbing.h"
|
||||||
|
|
||||||
|
//#define SCRUB_ABOVE
|
||||||
|
#define RULER_DOUBLE_CLICK
|
||||||
|
|
||||||
using std::min;
|
using std::min;
|
||||||
using std::max;
|
using std::max;
|
||||||
|
|
||||||
@ -1774,6 +1777,9 @@ BEGIN_EVENT_TABLE(AdornedRulerPanel, wxPanel)
|
|||||||
EVT_MENU(OnAutoScrollID, AdornedRulerPanel::OnAutoScroll)
|
EVT_MENU(OnAutoScrollID, AdornedRulerPanel::OnAutoScroll)
|
||||||
EVT_MENU(OnLockPlayRegionID, AdornedRulerPanel::OnLockPlayRegion)
|
EVT_MENU(OnLockPlayRegionID, AdornedRulerPanel::OnLockPlayRegion)
|
||||||
|
|
||||||
|
// Scrub bar menu commands
|
||||||
|
EVT_MENU(OnShowHideScrubbingID, AdornedRulerPanel::OnToggleScrubbing)
|
||||||
|
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
AdornedRulerPanel::AdornedRulerPanel(AudacityProject* parent,
|
AdornedRulerPanel::AdornedRulerPanel(AudacityProject* parent,
|
||||||
@ -1869,7 +1875,7 @@ namespace {
|
|||||||
bool ReadScrubEnabledPref()
|
bool ReadScrubEnabledPref()
|
||||||
{
|
{
|
||||||
bool result {};
|
bool result {};
|
||||||
gPrefs->Read(scrubEnabledPrefName, &result, true);
|
gPrefs->Read(scrubEnabledPrefName, &result, false);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1895,11 +1901,56 @@ void AdornedRulerPanel::UpdatePrefs()
|
|||||||
// Affected by the last
|
// Affected by the last
|
||||||
UpdateRects();
|
UpdateRects();
|
||||||
|
|
||||||
RegenerateTooltips();
|
RegenerateTooltips(mPrevZone);
|
||||||
|
|
||||||
mButtonFontSize = -1;
|
mButtonFontSize = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
enum { ArrowWidth = 8, ArrowSpacing = 1, ArrowHeight = ArrowWidth / 2 };
|
||||||
|
|
||||||
|
// Find the part of the button rectangle in which you can click the arrow.
|
||||||
|
// It includes the lower right corner.
|
||||||
|
wxRect GetArrowRect(const wxRect &buttonRect)
|
||||||
|
{
|
||||||
|
// Change the following lines to change the size of the hot zone.
|
||||||
|
// Make the hot zone as tall as the button
|
||||||
|
auto width = std::min(
|
||||||
|
std::max(1, buttonRect.GetWidth()) - 1,
|
||||||
|
ArrowWidth + 2 * ArrowSpacing
|
||||||
|
+ 2 // bevel around arrow
|
||||||
|
+ 2 // outline around the bevel
|
||||||
|
);
|
||||||
|
auto height = buttonRect.GetHeight();
|
||||||
|
|
||||||
|
return wxRect {
|
||||||
|
buttonRect.GetRight() + 1 - width,
|
||||||
|
buttonRect.GetBottom() + 1 - height,
|
||||||
|
width, height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
wxRect GetTextRect(const wxRect &buttonRect)
|
||||||
|
{
|
||||||
|
auto result = buttonRect;
|
||||||
|
result.width -= GetArrowRect(buttonRect).width;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compensate for off-by-one problem in the bevel-drawing functions
|
||||||
|
struct Deflator {
|
||||||
|
Deflator(wxRect &rect) : mRect(rect) {
|
||||||
|
--mRect.width;
|
||||||
|
--mRect.height;
|
||||||
|
}
|
||||||
|
~Deflator() {
|
||||||
|
++mRect.width;
|
||||||
|
++mRect.height;
|
||||||
|
}
|
||||||
|
wxRect mRect;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
wxFont &AdornedRulerPanel::GetButtonFont() const
|
wxFont &AdornedRulerPanel::GetButtonFont() const
|
||||||
{
|
{
|
||||||
if (mButtonFontSize < 0) {
|
if (mButtonFontSize < 0) {
|
||||||
@ -1911,12 +1962,21 @@ wxFont &AdornedRulerPanel::GetButtonFont() const
|
|||||||
mButtonFont.SetPointSize(mButtonFontSize);
|
mButtonFont.SetPointSize(mButtonFontSize);
|
||||||
wxCoord width, height;
|
wxCoord width, height;
|
||||||
for (auto button = StatusChoice::FirstButton; done && IsButton(button); ++button) {
|
for (auto button = StatusChoice::FirstButton; done && IsButton(button); ++button) {
|
||||||
auto allowableWidth = GetButtonRect(button).GetWidth() - 2;
|
auto rect = GetTextRect(GetButtonRect(button));
|
||||||
// 2 corresponds with the Inflate(-1, -1)
|
auto availableWidth = rect.GetWidth();
|
||||||
|
auto availableHeight = rect.GetHeight();
|
||||||
|
|
||||||
|
// Deduct for outlines, and room to move text
|
||||||
|
// I might deduct 2 more for bevel, but that made the text too small.
|
||||||
|
availableWidth -= 2 + 1;
|
||||||
|
availableHeight -= 2 + 1;
|
||||||
|
|
||||||
GetParent()->GetTextExtent(
|
GetParent()->GetTextExtent(
|
||||||
wxGetTranslation(GetPushButtonStrings(button)->label),
|
wxGetTranslation(GetPushButtonStrings(button)->label),
|
||||||
&width, &height, NULL, NULL, &mButtonFont);
|
&width, &height, NULL, NULL, &mButtonFont);
|
||||||
done = width < allowableWidth;
|
|
||||||
|
// Yes, < not <= ! Leave at least some room.
|
||||||
|
done = width < availableWidth && height < availableHeight;
|
||||||
}
|
}
|
||||||
mButtonFontSize--;
|
mButtonFontSize--;
|
||||||
} while (mButtonFontSize > 0 && !done);
|
} while (mButtonFontSize > 0 && !done);
|
||||||
@ -1930,7 +1990,7 @@ void AdornedRulerPanel::InvalidateRuler()
|
|||||||
mRuler.Invalidate();
|
mRuler.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdornedRulerPanel::RegenerateTooltips()
|
void AdornedRulerPanel::RegenerateTooltips(StatusChoice choice)
|
||||||
{
|
{
|
||||||
#if wxUSE_TOOLTIPS
|
#if wxUSE_TOOLTIPS
|
||||||
if (mTimelineToolTip) {
|
if (mTimelineToolTip) {
|
||||||
@ -1938,7 +1998,7 @@ void AdornedRulerPanel::RegenerateTooltips()
|
|||||||
this->SetToolTip(_("Timeline actions disabled during recording"));
|
this->SetToolTip(_("Timeline actions disabled during recording"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch(mPrevZone) {
|
switch(choice) {
|
||||||
case StatusChoice::QuickPlayButton :
|
case StatusChoice::QuickPlayButton :
|
||||||
case StatusChoice::EnteringQP :
|
case StatusChoice::EnteringQP :
|
||||||
if (!mQuickPlayEnabled) {
|
if (!mQuickPlayEnabled) {
|
||||||
@ -1988,12 +2048,15 @@ void AdornedRulerPanel::OnCapture(wxCommandEvent & evt)
|
|||||||
// if recording is initiated by a modal window (Timer Record).
|
// if recording is initiated by a modal window (Timer Record).
|
||||||
SetCursor(mCursorDefault);
|
SetCursor(mCursorDefault);
|
||||||
mIsRecording = true;
|
mIsRecording = true;
|
||||||
|
|
||||||
|
// The quick play indicator is useless during recording
|
||||||
|
HideQuickPlayIndicator();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SetCursor(mCursorHand);
|
SetCursor(mCursorHand);
|
||||||
mIsRecording = false;
|
mIsRecording = false;
|
||||||
}
|
}
|
||||||
RegenerateTooltips();
|
RegenerateTooltips(mPrevZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum : int {
|
enum : int {
|
||||||
@ -2051,7 +2114,7 @@ void AdornedRulerPanel::OnPaint(wxPaintEvent & WXUNUSED(evt))
|
|||||||
mBack->Create(sz.x, sz.y, dc);
|
mBack->Create(sz.x, sz.y, dc);
|
||||||
mBackDC.SelectObject(*mBack);
|
mBackDC.SelectObject(*mBack);
|
||||||
|
|
||||||
DoDrawBorder(&mBackDC);
|
DoDrawBackground(&mBackDC);
|
||||||
|
|
||||||
if (!mViewInfo->selectedRegion.isPoint())
|
if (!mViewInfo->selectedRegion.isPoint())
|
||||||
{
|
{
|
||||||
@ -2063,8 +2126,7 @@ void AdornedRulerPanel::OnPaint(wxPaintEvent & WXUNUSED(evt))
|
|||||||
if (mIndType >= 0)
|
if (mIndType >= 0)
|
||||||
{
|
{
|
||||||
const bool scrub = mProject->GetScrubber().HasStartedScrubbing();
|
const bool scrub = mProject->GetScrubber().HasStartedScrubbing();
|
||||||
auto width = scrub ? IndicatorBigWidth() : IndicatorMediumWidth;
|
DoDrawIndicator(&mBackDC, mIndTime, mIndType != 0, IndicatorMediumWidth, false);
|
||||||
DoDrawIndicator(&mBackDC, mIndTime, mIndType != 0, width, scrub);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mViewInfo->selectedRegion.isPoint())
|
if (mViewInfo->selectedRegion.isPoint())
|
||||||
@ -2076,11 +2138,13 @@ void AdornedRulerPanel::OnPaint(wxPaintEvent & WXUNUSED(evt))
|
|||||||
|
|
||||||
DoDrawPushbuttons(&mBackDC);
|
DoDrawPushbuttons(&mBackDC);
|
||||||
|
|
||||||
|
DoDrawEdge(&mBackDC);
|
||||||
|
|
||||||
dc.Blit(0, 0, mBack->GetWidth(), mBack->GetHeight(), &mBackDC, 0, 0);
|
dc.Blit(0, 0, mBack->GetWidth(), mBack->GetHeight(), &mBackDC, 0, 0);
|
||||||
|
|
||||||
if (mQuickPlayInd)
|
if (mQuickPlayInd)
|
||||||
{
|
{
|
||||||
DrawQuickPlayIndicator(&dc);
|
DrawQuickPlayIndicator(&dc, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2103,21 +2167,30 @@ void AdornedRulerPanel::UpdateRects()
|
|||||||
mInner.x += LeftMargin;
|
mInner.x += LeftMargin;
|
||||||
mInner.width -= (LeftMargin + RightMargin);
|
mInner.width -= (LeftMargin + RightMargin);
|
||||||
|
|
||||||
wxRect *top = &mInner;
|
auto top = &mInner;
|
||||||
|
auto bottom = &mInner;
|
||||||
|
|
||||||
if (mShowScrubbing) {
|
if (mShowScrubbing) {
|
||||||
mScrubZone = mInner;
|
mScrubZone = mInner;
|
||||||
auto scrubHeight = std::min(mScrubZone.height, int(ScrubHeight));
|
auto scrubHeight = std::min(mScrubZone.height, int(ScrubHeight));
|
||||||
mScrubZone.height = scrubHeight;
|
|
||||||
mInner.height -= scrubHeight;
|
int topHeight;
|
||||||
mInner.y += scrubHeight;
|
#ifdef SCRUB_ABOVE
|
||||||
top = &mScrubZone;
|
top = &mScrubZone, topHeight = scrubHeight;
|
||||||
|
#else
|
||||||
|
auto qpHeight = mScrubZone.height - scrubHeight;
|
||||||
|
bottom = &mScrubZone, topHeight = qpHeight;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
top->height = topHeight;
|
||||||
|
bottom->height -= topHeight;
|
||||||
|
bottom->y += topHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
top->y += TopMargin;
|
top->y += TopMargin;
|
||||||
top->height -= TopMargin;
|
top->height -= TopMargin;
|
||||||
|
|
||||||
mInner.height -= BottomMargin;
|
bottom->height -= BottomMargin;
|
||||||
|
|
||||||
if (!mShowScrubbing)
|
if (!mShowScrubbing)
|
||||||
mScrubZone = mInner;
|
mScrubZone = mInner;
|
||||||
@ -2166,7 +2239,7 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool overButtons = GetButtonAreaRect(true).Contains(evt.GetPosition());
|
const bool overButtons = GetButtonAreaRect(true).Contains(evt.GetPosition());
|
||||||
const StatusChoice button = FindButton(evt.GetPosition());
|
auto button = FindButton(evt).button;
|
||||||
const bool inScrubZone = !overButtons &&
|
const bool inScrubZone = !overButtons &&
|
||||||
// only if scrubbing is allowed now
|
// only if scrubbing is allowed now
|
||||||
mProject->GetScrubber().CanScrub() &&
|
mProject->GetScrubber().CanScrub() &&
|
||||||
@ -2179,9 +2252,11 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
? button
|
? button
|
||||||
: inScrubZone
|
: inScrubZone
|
||||||
? StatusChoice::EnteringScrubZone
|
? StatusChoice::EnteringScrubZone
|
||||||
: StatusChoice::EnteringQP;
|
: mInner.Contains(evt.GetPosition())
|
||||||
|
? StatusChoice::EnteringQP
|
||||||
|
: StatusChoice::NoChange;
|
||||||
const bool changeInZone = (zone != mPrevZone);
|
const bool changeInZone = (zone != mPrevZone);
|
||||||
mPrevZone = zone;
|
const bool changing = evt.Leaving() || evt.Entering() || changeInZone;
|
||||||
|
|
||||||
wxCoord xx = evt.GetX();
|
wxCoord xx = evt.GetX();
|
||||||
wxCoord mousePosX = xx;
|
wxCoord mousePosX = xx;
|
||||||
@ -2195,36 +2270,49 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle status bar messages
|
// Handle status bar messages
|
||||||
UpdateStatusBarAndTooltips (
|
UpdateStatusBarAndTooltips (changing ? zone : StatusChoice::NoChange);
|
||||||
evt.Leaving() || evt.Entering() || changeInZone
|
|
||||||
? zone
|
if ((IsButton(zone) || IsButton(mPrevZone)) &&
|
||||||
: StatusChoice::NoChange
|
(changing || evt.Moving() || evt.Dragging()))
|
||||||
);
|
// So that the highlights in pushbuttons can update
|
||||||
|
Refresh(false);
|
||||||
|
|
||||||
|
mPrevZone = zone;
|
||||||
|
|
||||||
auto &scrubber = mProject->GetScrubber();
|
auto &scrubber = mProject->GetScrubber();
|
||||||
if (scrubber.HasStartedScrubbing()) {
|
if (scrubber.HasStartedScrubbing()) {
|
||||||
// If already clicked for scrub, preempt the usual event handling,
|
if (zone == StatusChoice::EnteringQP &&
|
||||||
// no matter what the y coordinate.
|
evt.LeftDown()) {
|
||||||
|
// Stop scrubbing
|
||||||
|
if (HasCapture())
|
||||||
|
ReleaseMouse();
|
||||||
|
mProject->OnStop();
|
||||||
|
// Continue to quick play event handling
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If already clicked for scrub, preempt the usual event handling,
|
||||||
|
// no matter what the y coordinate.
|
||||||
|
|
||||||
// Do this hack so scrubber can detect mouse drags anywhere
|
// Do this hack so scrubber can detect mouse drags anywhere
|
||||||
evt.ResumePropagation(wxEVENT_PROPAGATE_MAX);
|
evt.ResumePropagation(wxEVENT_PROPAGATE_MAX);
|
||||||
|
|
||||||
if (scrubber.IsScrubbing())
|
if (scrubber.IsScrubbing())
|
||||||
evt.Skip();
|
evt.Skip();
|
||||||
else if (evt.LeftDClick())
|
else if (evt.LeftDClick())
|
||||||
// On the second button down, switch the pending scrub to scrolling
|
// On the second button down, switch the pending scrub to scrolling
|
||||||
scrubber.MarkScrubStart(evt.m_x, true, false);
|
scrubber.MarkScrubStart(evt.m_x, true, false);
|
||||||
else
|
else
|
||||||
evt.Skip();
|
evt.Skip();
|
||||||
|
|
||||||
mQuickPlayInd = true;
|
mQuickPlayInd = true;
|
||||||
wxClientDC dc(this);
|
wxClientDC dc(this);
|
||||||
DrawQuickPlayIndicator(&dc);
|
DrawQuickPlayIndicator(&dc);
|
||||||
|
|
||||||
if (HasCapture())
|
if (HasCapture())
|
||||||
ReleaseMouse();
|
ReleaseMouse();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the initial play region state
|
// Store the initial play region state
|
||||||
@ -2260,7 +2348,7 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasCapture() && mCaptureState != StatusChoice::NoButton)
|
if (HasCapture() && mCaptureState.button != StatusChoice::NoButton)
|
||||||
HandlePushbuttonEvent(evt);
|
HandlePushbuttonEvent(evt);
|
||||||
else if (!HasCapture() && overButtons)
|
else if (!HasCapture() && overButtons)
|
||||||
HandlePushbuttonClick(evt);
|
HandlePushbuttonClick(evt);
|
||||||
@ -2304,7 +2392,15 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RULER_DOUBLE_CLICK
|
||||||
|
if (evt.LeftDClick()) {
|
||||||
|
mDoubleClick = true;
|
||||||
|
HandleQPDoubleClick(evt, mousePosX);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (evt.LeftDown()) {
|
if (evt.LeftDown()) {
|
||||||
|
mDoubleClick = false;
|
||||||
HandleQPClick(evt, mousePosX);
|
HandleQPClick(evt, mousePosX);
|
||||||
HandleQPDrag(evt, mousePosX);
|
HandleQPDrag(evt, mousePosX);
|
||||||
}
|
}
|
||||||
@ -2319,6 +2415,11 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdornedRulerPanel::HandleQPDoubleClick(wxMouseEvent &evt, wxCoord mousePosX)
|
||||||
|
{
|
||||||
|
mProject->GetPlaybackScroller().Activate(true);
|
||||||
|
}
|
||||||
|
|
||||||
void AdornedRulerPanel::HandleQPClick(wxMouseEvent &evt, wxCoord mousePosX)
|
void AdornedRulerPanel::HandleQPClick(wxMouseEvent &evt, wxCoord mousePosX)
|
||||||
{
|
{
|
||||||
// Temporarily unlock locked play region
|
// Temporarily unlock locked play region
|
||||||
@ -2452,12 +2553,15 @@ void AdornedRulerPanel::HandleQPDrag(wxMouseEvent &event, wxCoord mousePosX)
|
|||||||
|
|
||||||
void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
||||||
{
|
{
|
||||||
|
if (mDoubleClick)
|
||||||
|
return;
|
||||||
|
|
||||||
HideQuickPlayIndicator();
|
HideQuickPlayIndicator();
|
||||||
|
|
||||||
if (HasCapture())
|
if (HasCapture())
|
||||||
ReleaseMouse();
|
ReleaseMouse();
|
||||||
|
|
||||||
mCaptureState = StatusChoice::NoButton;
|
mCaptureState = CaptureState{};
|
||||||
|
|
||||||
if (mPlayRegionEnd < mPlayRegionStart) {
|
if (mPlayRegionEnd < mPlayRegionStart) {
|
||||||
// Swap values to ensure mPlayRegionStart < mPlayRegionEnd
|
// Swap values to ensure mPlayRegionStart < mPlayRegionEnd
|
||||||
@ -2492,6 +2596,28 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
|||||||
ClearPlayRegion();
|
ClearPlayRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StartQPPlay(evt.ShiftDown(), evt.ControlDown());
|
||||||
|
|
||||||
|
mMouseEventState = mesNone;
|
||||||
|
mIsDragging = false;
|
||||||
|
mLeftDownClick = -1;
|
||||||
|
|
||||||
|
if (mPlayRegionLock) {
|
||||||
|
// Restore Locked Play region
|
||||||
|
SetPlayRegion(mOldPlayRegionStart, mOldPlayRegionEnd);
|
||||||
|
mProject->OnLockPlayRegion();
|
||||||
|
// and release local lock
|
||||||
|
mPlayRegionLock = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdornedRulerPanel::StartQPPlay(bool looped, bool cutPreview)
|
||||||
|
{
|
||||||
|
const double t0 = mTracks->GetStartTime();
|
||||||
|
const double t1 = mTracks->GetEndTime();
|
||||||
|
const double sel0 = mProject->GetSel0();
|
||||||
|
const double sel1 = mProject->GetSel1();
|
||||||
|
|
||||||
// Start / Restart playback on left click.
|
// Start / Restart playback on left click.
|
||||||
bool startPlaying = (mPlayRegionStart >= 0);
|
bool startPlaying = (mPlayRegionStart >= 0);
|
||||||
|
|
||||||
@ -2502,7 +2628,7 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
|||||||
bool loopEnabled = true;
|
bool loopEnabled = true;
|
||||||
double start, end;
|
double start, end;
|
||||||
|
|
||||||
if ((mPlayRegionEnd - mPlayRegionStart == 0.0) && evt.ShiftDown()) {
|
if ((mPlayRegionEnd - mPlayRegionStart == 0.0) && looped) {
|
||||||
// Loop play a point will loop either a selection or the project.
|
// Loop play a point will loop either a selection or the project.
|
||||||
if ((mPlayRegionStart > sel0) && (mPlayRegionStart < sel1)) {
|
if ((mPlayRegionStart > sel0) && (mPlayRegionStart < sel1)) {
|
||||||
// we are in a selection, so use the selection
|
// we are in a selection, so use the selection
|
||||||
@ -2522,15 +2648,15 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
|||||||
loopEnabled = ((end - start) > 0.001)? true : false;
|
loopEnabled = ((end - start) > 0.001)? true : false;
|
||||||
|
|
||||||
AudioIOStartStreamOptions options(mProject->GetDefaultPlayOptions());
|
AudioIOStartStreamOptions options(mProject->GetDefaultPlayOptions());
|
||||||
options.playLooped = (loopEnabled && evt.ShiftDown());
|
options.playLooped = (loopEnabled && looped);
|
||||||
|
|
||||||
if (!evt.ControlDown())
|
if (!cutPreview)
|
||||||
options.pStartTime = &mPlayRegionStart;
|
options.pStartTime = &mPlayRegionStart;
|
||||||
else
|
else
|
||||||
options.timeTrack = NULL;
|
options.timeTrack = NULL;
|
||||||
|
|
||||||
ControlToolBar::PlayAppearance appearance =
|
ControlToolBar::PlayAppearance appearance =
|
||||||
evt.ControlDown() ? ControlToolBar::PlayAppearance::CutPreview
|
cutPreview ? ControlToolBar::PlayAppearance::CutPreview
|
||||||
: options.playLooped ? ControlToolBar::PlayAppearance::Looped
|
: options.playLooped ? ControlToolBar::PlayAppearance::Looped
|
||||||
: ControlToolBar::PlayAppearance::Straight;
|
: ControlToolBar::PlayAppearance::Straight;
|
||||||
ctb->PlayPlayRegion((SelectedRegion(start, end)),
|
ctb->PlayPlayRegion((SelectedRegion(start, end)),
|
||||||
@ -2543,18 +2669,6 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
|||||||
mPlayRegionEnd = end;
|
mPlayRegionEnd = end;
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
mMouseEventState = mesNone;
|
|
||||||
mIsDragging = false;
|
|
||||||
mLeftDownClick = -1;
|
|
||||||
|
|
||||||
if (mPlayRegionLock) {
|
|
||||||
// Restore Locked Play region
|
|
||||||
SetPlayRegion(mOldPlayRegionStart, mOldPlayRegionEnd);
|
|
||||||
mProject->OnLockPlayRegion();
|
|
||||||
// and release local lock
|
|
||||||
mPlayRegionLock = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdornedRulerPanel::UpdateStatusBarAndTooltips(StatusChoice choice)
|
void AdornedRulerPanel::UpdateStatusBarAndTooltips(StatusChoice choice)
|
||||||
@ -2567,8 +2681,7 @@ void AdornedRulerPanel::UpdateStatusBarAndTooltips(StatusChoice choice)
|
|||||||
if (IsButton(choice)) {
|
if (IsButton(choice)) {
|
||||||
bool state = GetButtonState(choice);
|
bool state = GetButtonState(choice);
|
||||||
const auto &strings = *GetPushButtonStrings(choice);
|
const auto &strings = *GetPushButtonStrings(choice);
|
||||||
message += wxGetTranslation(state ? strings.disable : strings.enable);
|
message = wxGetTranslation(state ? strings.disable : strings.enable);
|
||||||
message += wxT(" ") + _("(Right-Click for options)");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const auto &scrubber = mProject->GetScrubber();
|
const auto &scrubber = mProject->GetScrubber();
|
||||||
@ -2603,10 +2716,10 @@ void AdornedRulerPanel::UpdateStatusBarAndTooltips(StatusChoice choice)
|
|||||||
// Display a message, or empty message
|
// Display a message, or empty message
|
||||||
mProject->TP_DisplayStatusMessage(message);
|
mProject->TP_DisplayStatusMessage(message);
|
||||||
|
|
||||||
RegenerateTooltips();
|
RegenerateTooltips(choice);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdornedRulerPanel::OnToggleScrubbing()
|
void AdornedRulerPanel::OnToggleScrubbing(wxCommandEvent&)
|
||||||
{
|
{
|
||||||
mShowScrubbing = !mShowScrubbing;
|
mShowScrubbing = !mShowScrubbing;
|
||||||
WriteScrubEnabledPref(mShowScrubbing);
|
WriteScrubEnabledPref(mShowScrubbing);
|
||||||
@ -2686,6 +2799,15 @@ void AdornedRulerPanel::ShowScrubMenu(const wxPoint & pos)
|
|||||||
auto cleanup = finally([this]{ PopEventHandler(); });
|
auto cleanup = finally([this]{ PopEventHandler(); });
|
||||||
|
|
||||||
wxMenu rulerMenu;
|
wxMenu rulerMenu;
|
||||||
|
auto label = wxGetTranslation(
|
||||||
|
AdornedRulerPanel::PushbuttonLabels
|
||||||
|
[static_cast<int>(StatusChoice::ScrubBarButton)].label);
|
||||||
|
rulerMenu.AppendCheckItem(OnShowHideScrubbingID, _("Scrub Bar"));
|
||||||
|
if(GetButtonState(StatusChoice::ScrubBarButton))
|
||||||
|
rulerMenu.FindItem(OnShowHideScrubbingID)->Check();
|
||||||
|
|
||||||
|
rulerMenu.AppendSeparator();
|
||||||
|
|
||||||
mProject->GetScrubber().PopulateMenu(rulerMenu);
|
mProject->GetScrubber().PopulateMenu(rulerMenu);
|
||||||
PopupMenu(&rulerMenu, pos);
|
PopupMenu(&rulerMenu, pos);
|
||||||
}
|
}
|
||||||
@ -2695,7 +2817,7 @@ void AdornedRulerPanel::OnToggleQuickPlay(wxCommandEvent&)
|
|||||||
mQuickPlayEnabled = (mQuickPlayEnabled)? false : true;
|
mQuickPlayEnabled = (mQuickPlayEnabled)? false : true;
|
||||||
gPrefs->Write(wxT("/QuickPlay/QuickPlayEnabled"), mQuickPlayEnabled);
|
gPrefs->Write(wxT("/QuickPlay/QuickPlayEnabled"), mQuickPlayEnabled);
|
||||||
gPrefs->Flush();
|
gPrefs->Flush();
|
||||||
RegenerateTooltips();
|
RegenerateTooltips(mPrevZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdornedRulerPanel::OnSyncSelToQuickPlay(wxCommandEvent&)
|
void AdornedRulerPanel::OnSyncSelToQuickPlay(wxCommandEvent&)
|
||||||
@ -2736,7 +2858,7 @@ void AdornedRulerPanel::OnTimelineToolTips(wxCommandEvent&)
|
|||||||
gPrefs->Write(wxT("/QuickPlay/ToolTips"), mTimelineToolTip);
|
gPrefs->Write(wxT("/QuickPlay/ToolTips"), mTimelineToolTip);
|
||||||
gPrefs->Flush();
|
gPrefs->Flush();
|
||||||
#if wxUSE_TOOLTIPS
|
#if wxUSE_TOOLTIPS
|
||||||
RegenerateTooltips();
|
RegenerateTooltips(mPrevZone);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2860,19 +2982,40 @@ wxRect AdornedRulerPanel::GetButtonRect( StatusChoice button ) const
|
|||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AdornedRulerPanel::InButtonRect( StatusChoice button ) const
|
auto AdornedRulerPanel::InButtonRect( StatusChoice button, wxMouseEvent *pEvent ) const
|
||||||
|
-> PointerState
|
||||||
{
|
{
|
||||||
return GetButtonRect(button).Contains(ScreenToClient(::wxGetMousePosition()));
|
auto rect = GetButtonRect(button);
|
||||||
|
auto state = pEvent ? *pEvent : ::wxGetMouseState();
|
||||||
|
auto point = pEvent ? pEvent->GetPosition() : ScreenToClient(state.GetPosition());
|
||||||
|
if(!rect.Contains(point))
|
||||||
|
return PointerState::Out;
|
||||||
|
else {
|
||||||
|
auto rightDown = state.RightIsDown()
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
// make drag with Mac Control down act like right drag
|
||||||
|
|| (state.RawControlDown() && state.ButtonIsDown(wxMOUSE_BTN_ANY))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
if(rightDown ||
|
||||||
|
(pEvent && pEvent->RightUp()) ||
|
||||||
|
GetArrowRect(rect).Contains(point))
|
||||||
|
return PointerState::InArrow;
|
||||||
|
else
|
||||||
|
return PointerState::In;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AdornedRulerPanel::FindButton( wxPoint position ) const -> StatusChoice
|
auto AdornedRulerPanel::FindButton( wxMouseEvent &mouseEvent ) const
|
||||||
|
-> CaptureState
|
||||||
{
|
{
|
||||||
for (auto button = StatusChoice::FirstButton; IsButton(button); ++button) {
|
for (auto button = StatusChoice::FirstButton; IsButton(button); ++button) {
|
||||||
if(GetButtonRect(button).Contains(position))
|
auto state = InButtonRect( button, &mouseEvent );
|
||||||
return button;
|
if (state != PointerState::Out)
|
||||||
|
return CaptureState{ button, state };
|
||||||
}
|
}
|
||||||
|
|
||||||
return StatusChoice::NoButton;
|
return { StatusChoice::NoButton, PointerState::Out };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AdornedRulerPanel::GetButtonState( StatusChoice button ) const
|
bool AdornedRulerPanel::GetButtonState( StatusChoice button ) const
|
||||||
@ -2890,30 +3033,33 @@ bool AdornedRulerPanel::GetButtonState( StatusChoice button ) const
|
|||||||
|
|
||||||
void AdornedRulerPanel::ToggleButtonState( StatusChoice button )
|
void AdornedRulerPanel::ToggleButtonState( StatusChoice button )
|
||||||
{
|
{
|
||||||
|
wxCommandEvent dummy;
|
||||||
switch(button) {
|
switch(button) {
|
||||||
case StatusChoice::QuickPlayButton: {
|
case StatusChoice::QuickPlayButton:
|
||||||
wxCommandEvent dummy;
|
|
||||||
OnToggleQuickPlay(dummy);
|
OnToggleQuickPlay(dummy);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case StatusChoice::ScrubBarButton:
|
case StatusChoice::ScrubBarButton:
|
||||||
OnToggleScrubbing();
|
OnToggleScrubbing(dummy);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
wxASSERT(false);
|
wxASSERT(false);
|
||||||
}
|
}
|
||||||
|
UpdateStatusBarAndTooltips(mCaptureState.button);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdornedRulerPanel::ShowButtonMenu( StatusChoice button, wxPoint position)
|
void AdornedRulerPanel::ShowButtonMenu( StatusChoice button, wxPoint position)
|
||||||
{
|
{
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case StatusChoice::QuickPlayButton:
|
case StatusChoice::QuickPlayButton:
|
||||||
return ShowMenu(position);
|
ShowMenu(position); break;
|
||||||
case StatusChoice::ScrubBarButton:
|
case StatusChoice::ScrubBarButton:
|
||||||
return ShowScrubMenu(position);
|
ShowScrubMenu(position); break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dismiss and clear Quick-Play indicator
|
||||||
|
HideQuickPlayIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
const AdornedRulerPanel::ButtonStrings AdornedRulerPanel::PushbuttonLabels
|
const AdornedRulerPanel::ButtonStrings AdornedRulerPanel::PushbuttonLabels
|
||||||
@ -2924,48 +3070,105 @@ const AdornedRulerPanel::ButtonStrings AdornedRulerPanel::PushbuttonLabels
|
|||||||
{ XO("Scrub Bar"), XO("Show Scrub Bar"), XO("Hide Scrub Bar") },
|
{ XO("Scrub Bar"), XO("Show Scrub Bar"), XO("Hide Scrub Bar") },
|
||||||
};
|
};
|
||||||
|
|
||||||
void AdornedRulerPanel::DoDrawPushbutton(wxDC *dc, StatusChoice button, bool down) const
|
namespace {
|
||||||
|
void DrawButtonBackground(wxDC *dc, const wxRect &rect, bool down, bool highlight) {
|
||||||
|
// Choose the pen
|
||||||
|
if (highlight)
|
||||||
|
AColor::Light(dc, false);
|
||||||
|
else
|
||||||
|
// This color choice corresponds to part of TrackInfo::DrawBordersWithin() :
|
||||||
|
AColor::Dark(dc, false);
|
||||||
|
auto pen = dc->GetPen();
|
||||||
|
// pen.SetWidth(2);
|
||||||
|
|
||||||
|
// Choose the brush
|
||||||
|
if (down)
|
||||||
|
AColor::Solo(dc, true, false);
|
||||||
|
else
|
||||||
|
AColor::MediumTrackInfo(dc, false);
|
||||||
|
|
||||||
|
dc->SetPen(pen);
|
||||||
|
dc->DrawRectangle(rect);
|
||||||
|
|
||||||
|
// Draw the bevel
|
||||||
|
auto rect2 = rect.Deflate(1, 1);
|
||||||
|
Deflator def(rect2);
|
||||||
|
AColor::BevelTrackInfo(*dc, !down, rect2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdornedRulerPanel::DoDrawPushbutton
|
||||||
|
(wxDC *dc, StatusChoice button, PointerState down, PointerState pointerState) const
|
||||||
{
|
{
|
||||||
// Adapted from TrackInfo::DrawMuteSolo()
|
// Adapted from TrackInfo::DrawMuteSolo()
|
||||||
|
ADCChanger changer(dc);
|
||||||
|
|
||||||
auto bev = GetButtonRect( button );
|
const auto rect = GetButtonRect( button );
|
||||||
|
const auto arrowRect = GetArrowRect(rect);
|
||||||
|
auto arrowBev = arrowRect.Deflate(1, 1);
|
||||||
|
const auto textRect = GetTextRect(rect);
|
||||||
|
auto textBev = textRect.Deflate(1, 1);
|
||||||
|
|
||||||
// This part corresponds to part of TrackInfo::DrawBordersWithin() :
|
// Draw borders, bevels, and backgrounds of the split sections
|
||||||
AColor::Dark(dc, false);
|
|
||||||
dc->DrawRectangle(bev);
|
|
||||||
|
|
||||||
bev.Inflate(-1, -1);
|
if (pointerState == PointerState::InArrow) {
|
||||||
if (down)
|
// Draw highlighted arrow after
|
||||||
AColor::Solo(dc, true, false);
|
DrawButtonBackground(dc, textRect, (down == PointerState::In), false);
|
||||||
else
|
DrawButtonBackground(dc, arrowRect, (down == PointerState::InArrow), true);
|
||||||
AColor::MediumTrackInfo(dc, false);
|
}
|
||||||
dc->SetPen( *wxTRANSPARENT_PEN );//No border!
|
else {
|
||||||
dc->DrawRectangle(bev);
|
// Draw maybe highlighted text after
|
||||||
|
DrawButtonBackground(dc, arrowRect, (down == PointerState::InArrow), false);
|
||||||
|
DrawButtonBackground(
|
||||||
|
dc, textRect, (down == PointerState::In), (pointerState == PointerState::In));
|
||||||
|
}
|
||||||
|
|
||||||
dc->SetTextForeground(theTheme.Colour(clrTrackPanelText));
|
// Draw the menu triangle
|
||||||
|
{
|
||||||
|
auto x = arrowBev.GetX() + ArrowSpacing;
|
||||||
|
auto y = arrowBev.GetY() + (arrowBev.GetHeight() - ArrowHeight) / 2;
|
||||||
|
|
||||||
wxCoord textWidth, textHeight;
|
// Color it as in TrackInfo::DrawTitleBar
|
||||||
wxString str = wxGetTranslation(GetPushButtonStrings(button)->label);
|
#ifdef EXPERIMENTAL_THEMING
|
||||||
dc->SetFont(GetButtonFont());
|
wxColour c = theTheme.Colour( clrTrackPanelText );
|
||||||
dc->GetTextExtent(str, &textWidth, &textHeight);
|
#else
|
||||||
dc->DrawText(str, bev.x + (bev.width - textWidth) / 2,
|
wxColour c = *wxBLACK;
|
||||||
bev.y + (bev.height - textHeight) / 2);
|
#endif
|
||||||
AColor::BevelTrackInfo(*dc, !down, bev);
|
if (pointerState == PointerState::InArrow)
|
||||||
|
dc->SetBrush( wxBrush{ c } );
|
||||||
|
else
|
||||||
|
dc->SetBrush( wxBrush{ *wxTRANSPARENT_BRUSH } ); // Make outlined arrow only
|
||||||
|
dc->SetPen( wxPen{ c } );
|
||||||
|
|
||||||
|
// This function draws an arrow half as tall as wide:
|
||||||
|
AColor::Arrow(*dc, x, y, ArrowWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the text
|
||||||
|
|
||||||
|
{
|
||||||
|
dc->SetTextForeground(theTheme.Colour(clrTrackPanelText));
|
||||||
|
wxCoord textWidth, textHeight;
|
||||||
|
wxString str = wxGetTranslation(GetPushButtonStrings(button)->label);
|
||||||
|
dc->SetFont(GetButtonFont());
|
||||||
|
dc->GetTextExtent(str, &textWidth, &textHeight);
|
||||||
|
auto xx = textBev.x + (textBev.width - textWidth) / 2;
|
||||||
|
auto yy = textBev.y + (textBev.height - textHeight) / 2;
|
||||||
|
if (down == PointerState::In)
|
||||||
|
// Shift the text a bit for "down" appearance
|
||||||
|
++xx, ++yy;
|
||||||
|
dc->DrawText(str, xx, yy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdornedRulerPanel::HandlePushbuttonClick(wxMouseEvent &evt)
|
void AdornedRulerPanel::HandlePushbuttonClick(wxMouseEvent &evt)
|
||||||
{
|
{
|
||||||
auto button = FindButton(evt.GetPosition());
|
auto pair = FindButton(evt);
|
||||||
if (IsButton(button)) {
|
auto button = pair.button;
|
||||||
if (evt.LeftDown()) {
|
if (IsButton(button) && evt.ButtonDown()) {
|
||||||
CaptureMouse();
|
CaptureMouse();
|
||||||
mCaptureState = button;
|
mCaptureState = pair;
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
|
||||||
else if (evt.RightDown()) {
|
|
||||||
auto rect = GetButtonRect(button);
|
|
||||||
ShowButtonMenu( button, wxPoint{ rect.GetX() + 1, rect.GetBottom() + 1 } );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2974,11 +3177,21 @@ void AdornedRulerPanel::HandlePushbuttonEvent(wxMouseEvent &evt)
|
|||||||
if(evt.ButtonUp()) {
|
if(evt.ButtonUp()) {
|
||||||
if(HasCapture())
|
if(HasCapture())
|
||||||
ReleaseMouse();
|
ReleaseMouse();
|
||||||
if(InButtonRect(mCaptureState)) {
|
|
||||||
ToggleButtonState(mCaptureState);
|
auto button = mCaptureState.button;
|
||||||
UpdateStatusBarAndTooltips(mCaptureState);
|
auto capturedIn = mCaptureState.state;
|
||||||
|
auto in = InButtonRect(button, &evt);
|
||||||
|
if (in != capturedIn)
|
||||||
|
;
|
||||||
|
else if (in == PointerState::In)
|
||||||
|
ToggleButtonState(button);
|
||||||
|
else {
|
||||||
|
auto rect = GetArrowRect(GetButtonRect(button));
|
||||||
|
wxPoint point { rect.GetLeft() + 1, rect.GetBottom() + 1 };
|
||||||
|
ShowButtonMenu(button, point);
|
||||||
}
|
}
|
||||||
mCaptureState = StatusChoice::NoButton;
|
|
||||||
|
mCaptureState = CaptureState{};
|
||||||
}
|
}
|
||||||
|
|
||||||
Refresh();
|
Refresh();
|
||||||
@ -2988,18 +3201,37 @@ void AdornedRulerPanel::DoDrawPushbuttons(wxDC *dc) const
|
|||||||
{
|
{
|
||||||
// Paint the area behind the buttons
|
// Paint the area behind the buttons
|
||||||
wxRect background = GetButtonAreaRect();
|
wxRect background = GetButtonAreaRect();
|
||||||
|
|
||||||
|
#ifndef SCRUB_ABOVE
|
||||||
|
// Reduce the height
|
||||||
|
background.y = mInner.y;
|
||||||
|
background.height = mInner.height;
|
||||||
|
#endif
|
||||||
|
|
||||||
AColor::MediumTrackInfo(dc, false);
|
AColor::MediumTrackInfo(dc, false);
|
||||||
dc->DrawRectangle(background);
|
dc->DrawRectangle(background);
|
||||||
|
|
||||||
for (auto button = StatusChoice::FirstButton; IsButton(button); ++button) {
|
for (auto button = StatusChoice::FirstButton; IsButton(button); ++button) {
|
||||||
auto state = GetButtonState(button);
|
bool state = GetButtonState(button);
|
||||||
auto toggle = (button == mCaptureState && InButtonRect(button));
|
auto in = InButtonRect(button, nullptr);
|
||||||
auto down = (state != toggle);
|
auto down = PointerState::Out;
|
||||||
DoDrawPushbutton(dc, button, down);
|
if (button == mCaptureState.button && in == mCaptureState.state) {
|
||||||
|
if (in == PointerState::In) {
|
||||||
|
// Toggle button's apparent state for mouseover
|
||||||
|
down = state ? PointerState::Out : in;
|
||||||
|
}
|
||||||
|
else if (in == PointerState::InArrow) {
|
||||||
|
// Menu arrow is not sticky
|
||||||
|
down = in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state)
|
||||||
|
down = PointerState::In;
|
||||||
|
DoDrawPushbutton(dc, button, down, in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdornedRulerPanel::DoDrawBorder(wxDC * dc)
|
void AdornedRulerPanel::DoDrawBackground(wxDC * dc)
|
||||||
{
|
{
|
||||||
// Draw AdornedRulerPanel border
|
// Draw AdornedRulerPanel border
|
||||||
AColor::MediumTrackInfo( dc, false );
|
AColor::MediumTrackInfo( dc, false );
|
||||||
@ -3012,6 +3244,10 @@ void AdornedRulerPanel::DoDrawBorder(wxDC * dc)
|
|||||||
dc->DrawRectangle(mScrubZone);
|
dc->DrawRectangle(mScrubZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdornedRulerPanel::DoDrawEdge(wxDC *dc)
|
||||||
|
{
|
||||||
wxRect r = mOuter;
|
wxRect r = mOuter;
|
||||||
r.width -= RightMargin;
|
r.width -= RightMargin;
|
||||||
r.height -= BottomMargin;
|
r.height -= BottomMargin;
|
||||||
@ -3112,6 +3348,7 @@ void AdornedRulerPanel::DrawIndicator( double time, bool rec )
|
|||||||
void AdornedRulerPanel::DoDrawIndicator
|
void AdornedRulerPanel::DoDrawIndicator
|
||||||
(wxDC * dc, double time, bool playing, int width, bool scrub)
|
(wxDC * dc, double time, bool playing, int width, bool scrub)
|
||||||
{
|
{
|
||||||
|
ADCChanger changer(dc); // Undo pen and brush changes at function exit
|
||||||
|
|
||||||
const int x = Time2Pos(time);
|
const int x = Time2Pos(time);
|
||||||
AColor::IndicatorColor( dc, playing );
|
AColor::IndicatorColor( dc, playing );
|
||||||
@ -3122,12 +3359,15 @@ void AdornedRulerPanel::DoDrawIndicator
|
|||||||
const int IndicatorHalfWidth = width / 2;
|
const int IndicatorHalfWidth = width / 2;
|
||||||
|
|
||||||
// Double headed, left-right
|
// Double headed, left-right
|
||||||
|
auto yy = mShowScrubbing
|
||||||
|
? mScrubZone.y
|
||||||
|
: (mInner.GetBottom() + 1) - 1 /* bevel */ - height;
|
||||||
tri[ 0 ].x = x - IndicatorOffset;
|
tri[ 0 ].x = x - IndicatorOffset;
|
||||||
tri[ 0 ].y = mScrubZone.y;
|
tri[ 0 ].y = yy;
|
||||||
tri[ 1 ].x = x - IndicatorOffset;
|
tri[ 1 ].x = x - IndicatorOffset;
|
||||||
tri[ 1 ].y = mScrubZone.y + height;
|
tri[ 1 ].y = yy + height;
|
||||||
tri[ 2 ].x = x - IndicatorHalfWidth;
|
tri[ 2 ].x = x - IndicatorHalfWidth;
|
||||||
tri[ 2 ].y = mScrubZone.y + height / 2;
|
tri[ 2 ].y = yy + height / 2;
|
||||||
dc->DrawPolygon( 3, tri );
|
dc->DrawPolygon( 3, tri );
|
||||||
tri[ 0 ].x = tri[ 1 ].x = x + IndicatorOffset;
|
tri[ 0 ].x = tri[ 1 ].x = x + IndicatorOffset;
|
||||||
tri[ 2 ].x = x + IndicatorHalfWidth;
|
tri[ 2 ].x = x + IndicatorHalfWidth;
|
||||||
@ -3138,11 +3378,11 @@ void AdornedRulerPanel::DoDrawIndicator
|
|||||||
auto height = IndicatorHeightForWidth(width);
|
auto height = IndicatorHeightForWidth(width);
|
||||||
const int IndicatorHalfWidth = width / 2;
|
const int IndicatorHalfWidth = width / 2;
|
||||||
tri[ 0 ].x = x - IndicatorHalfWidth;
|
tri[ 0 ].x = x - IndicatorHalfWidth;
|
||||||
tri[ 0 ].y = mScrubZone.y;
|
tri[ 0 ].y = mInner.y;
|
||||||
tri[ 1 ].x = x + IndicatorHalfWidth;
|
tri[ 1 ].x = x + IndicatorHalfWidth;
|
||||||
tri[ 1 ].y = mScrubZone.y;
|
tri[ 1 ].y = mInner.y;
|
||||||
tri[ 2 ].x = x;
|
tri[ 2 ].x = x;
|
||||||
tri[ 2 ].y = mScrubZone.y + height;
|
tri[ 2 ].y = mInner.y + height;
|
||||||
dc->DrawPolygon( 3, tri );
|
dc->DrawPolygon( 3, tri );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3159,13 +3399,13 @@ void AdornedRulerPanel::DoEraseIndicator(wxDC *dc, int x)
|
|||||||
|
|
||||||
// Restore the background, but make it a little oversized to make
|
// Restore the background, but make it a little oversized to make
|
||||||
// it happy OSX.
|
// it happy OSX.
|
||||||
dc->Blit(x - indsize - 1,
|
auto xx = x - indsize - 1;
|
||||||
mScrubZone.y - 1,
|
auto yy = 0;
|
||||||
|
dc->Blit(xx, yy,
|
||||||
indsize * 2 + 1 + 2,
|
indsize * 2 + 1 + 2,
|
||||||
mScrubZone.y + height + 2,
|
GetSize().GetHeight(),
|
||||||
&mBackDC,
|
&mBackDC,
|
||||||
x - indsize - 1,
|
xx, yy);
|
||||||
0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3180,7 +3420,7 @@ QuickPlayIndicatorOverlay *AdornedRulerPanel::GetOverlay()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draws the vertical line and green triangle indicating the Quick Play cursor position.
|
// Draws the vertical line and green triangle indicating the Quick Play cursor position.
|
||||||
void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc)
|
void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc, bool repainting)
|
||||||
{
|
{
|
||||||
double latestEnd = std::max(mTracks->GetEndTime(), mProject->GetSel1());
|
double latestEnd = std::max(mTracks->GetEndTime(), mProject->GetSel1());
|
||||||
if (dc == NULL || (mQuickPlayPos >= latestEnd)) {
|
if (dc == NULL || (mQuickPlayPos >= latestEnd)) {
|
||||||
@ -3195,7 +3435,9 @@ void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc)
|
|||||||
!mProject->GetScrubber().IsScrubbing();
|
!mProject->GetScrubber().IsScrubbing();
|
||||||
GetOverlay()->Update(x, mIsSnapped, previewScrub);
|
GetOverlay()->Update(x, mIsSnapped, previewScrub);
|
||||||
|
|
||||||
DoEraseIndicator(dc, mLastQuickPlayX);
|
if (!repainting)
|
||||||
|
DoEraseIndicator(dc, mLastQuickPlayX);
|
||||||
|
|
||||||
mLastQuickPlayX = x;
|
mLastQuickPlayX = x;
|
||||||
|
|
||||||
auto scrub = mPrevZone == StatusChoice::EnteringScrubZone ||
|
auto scrub = mPrevZone == StatusChoice::EnteringScrubZone ||
|
||||||
|
@ -312,20 +312,6 @@ public:
|
|||||||
void InvalidateRuler();
|
void InvalidateRuler();
|
||||||
|
|
||||||
void UpdatePrefs();
|
void UpdatePrefs();
|
||||||
void RegenerateTooltips();
|
|
||||||
void HideQuickPlayIndicator();
|
|
||||||
|
|
||||||
void UpdateQuickPlayPos(wxCoord &mousPosX);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void OnCapture(wxCommandEvent & evt);
|
|
||||||
void OnPaint(wxPaintEvent &evt);
|
|
||||||
void OnSize(wxSizeEvent &evt);
|
|
||||||
void UpdateRects();
|
|
||||||
void OnMouseEvents(wxMouseEvent &evt);
|
|
||||||
void HandleQPClick(wxMouseEvent &event, wxCoord mousePosX);
|
|
||||||
void HandleQPDrag(wxMouseEvent &event, wxCoord mousePosX);
|
|
||||||
void HandleQPRelease(wxMouseEvent &event);
|
|
||||||
|
|
||||||
enum class StatusChoice {
|
enum class StatusChoice {
|
||||||
FirstButton = 0,
|
FirstButton = 0,
|
||||||
@ -340,10 +326,38 @@ private:
|
|||||||
Leaving,
|
Leaving,
|
||||||
NoChange
|
NoChange
|
||||||
};
|
};
|
||||||
|
enum class PointerState {
|
||||||
|
Out = 0, In, InArrow
|
||||||
|
};
|
||||||
|
struct CaptureState {
|
||||||
|
CaptureState() {}
|
||||||
|
CaptureState(StatusChoice s, PointerState p) : button(s), state(p) {}
|
||||||
|
StatusChoice button { StatusChoice::NoButton };
|
||||||
|
PointerState state { PointerState::Out };
|
||||||
|
};
|
||||||
|
|
||||||
friend inline StatusChoice &operator++ (StatusChoice &choice) {
|
friend inline StatusChoice &operator++ (StatusChoice &choice) {
|
||||||
choice = static_cast<StatusChoice>(1 + static_cast<int>(choice));
|
choice = static_cast<StatusChoice>(1 + static_cast<int>(choice));
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegenerateTooltips(StatusChoice choice);
|
||||||
|
void HideQuickPlayIndicator();
|
||||||
|
|
||||||
|
void UpdateQuickPlayPos(wxCoord &mousPosX);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnCapture(wxCommandEvent & evt);
|
||||||
|
void OnPaint(wxPaintEvent &evt);
|
||||||
|
void OnSize(wxSizeEvent &evt);
|
||||||
|
void UpdateRects();
|
||||||
|
void OnMouseEvents(wxMouseEvent &evt);
|
||||||
|
void HandleQPDoubleClick(wxMouseEvent &event, wxCoord mousePosX);
|
||||||
|
void HandleQPClick(wxMouseEvent &event, wxCoord mousePosX);
|
||||||
|
void HandleQPDrag(wxMouseEvent &event, wxCoord mousePosX);
|
||||||
|
void HandleQPRelease(wxMouseEvent &event);
|
||||||
|
void StartQPPlay(bool looped, bool cutPreview);
|
||||||
|
|
||||||
static inline bool IsButton(StatusChoice choice)
|
static inline bool IsButton(StatusChoice choice)
|
||||||
{
|
{
|
||||||
auto integer = static_cast<int>(choice);
|
auto integer = static_cast<int>(choice);
|
||||||
@ -357,14 +371,15 @@ private:
|
|||||||
|
|
||||||
void OnCaptureLost(wxMouseCaptureLostEvent &evt);
|
void OnCaptureLost(wxMouseCaptureLostEvent &evt);
|
||||||
|
|
||||||
void DoDrawBorder(wxDC * dc);
|
void DoDrawBackground(wxDC * dc);
|
||||||
|
void DoDrawEdge(wxDC *dc);
|
||||||
void DoDrawMarks(wxDC * dc, bool /*text */ );
|
void DoDrawMarks(wxDC * dc, bool /*text */ );
|
||||||
void DoDrawCursor(wxDC * dc);
|
void DoDrawCursor(wxDC * dc);
|
||||||
void DoDrawSelection(wxDC * dc);
|
void DoDrawSelection(wxDC * dc);
|
||||||
void DoDrawIndicator(wxDC * dc, double time, bool playing, int width, bool scrub);
|
void DoDrawIndicator(wxDC * dc, double time, bool playing, int width, bool scrub);
|
||||||
void DoEraseIndicator(wxDC *dc, int x);
|
void DoEraseIndicator(wxDC *dc, int x);
|
||||||
QuickPlayIndicatorOverlay *GetOverlay();
|
QuickPlayIndicatorOverlay *GetOverlay();
|
||||||
void DrawQuickPlayIndicator(wxDC * dc /*NULL to DELETE old only*/);
|
void DrawQuickPlayIndicator(wxDC * dc /*NULL to DELETE old only*/, bool repainting = false);
|
||||||
void DoDrawPlayRegion(wxDC * dc);
|
void DoDrawPlayRegion(wxDC * dc);
|
||||||
|
|
||||||
wxRect GetButtonAreaRect(bool includeBorder = false) const;
|
wxRect GetButtonAreaRect(bool includeBorder = false) const;
|
||||||
@ -381,12 +396,13 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
wxRect GetButtonRect( StatusChoice button ) const;
|
wxRect GetButtonRect( StatusChoice button ) const;
|
||||||
bool InButtonRect( StatusChoice button ) const;
|
PointerState InButtonRect( StatusChoice button, wxMouseEvent *pEvent ) const;
|
||||||
StatusChoice FindButton( wxPoint position ) const;
|
CaptureState FindButton( wxMouseEvent &mouseEvent ) const;
|
||||||
bool GetButtonState( StatusChoice button ) const;
|
bool GetButtonState( StatusChoice button ) const;
|
||||||
void ToggleButtonState( StatusChoice button );
|
void ToggleButtonState( StatusChoice button );
|
||||||
void ShowButtonMenu( StatusChoice button, wxPoint position);
|
void ShowButtonMenu( StatusChoice button, wxPoint position);
|
||||||
void DoDrawPushbutton(wxDC *dc, StatusChoice button, bool down) const;
|
void DoDrawPushbutton(wxDC *dc, StatusChoice button, PointerState down,
|
||||||
|
PointerState pointerState) const;
|
||||||
void DoDrawPushbuttons(wxDC *dc) const;
|
void DoDrawPushbuttons(wxDC *dc) const;
|
||||||
void HandlePushbuttonClick(wxMouseEvent &evt);
|
void HandlePushbuttonClick(wxMouseEvent &evt);
|
||||||
void HandlePushbuttonEvent(wxMouseEvent &evt);
|
void HandlePushbuttonEvent(wxMouseEvent &evt);
|
||||||
@ -453,14 +469,13 @@ private:
|
|||||||
void OnAutoScroll(wxCommandEvent &evt);
|
void OnAutoScroll(wxCommandEvent &evt);
|
||||||
void OnLockPlayRegion(wxCommandEvent &evt);
|
void OnLockPlayRegion(wxCommandEvent &evt);
|
||||||
|
|
||||||
void OnToggleScrubbing();
|
void OnToggleScrubbing(wxCommandEvent&);
|
||||||
|
|
||||||
bool mPlayRegionDragsSelection;
|
bool mPlayRegionDragsSelection;
|
||||||
bool mTimelineToolTip;
|
bool mTimelineToolTip;
|
||||||
bool mQuickPlayEnabled;
|
bool mQuickPlayEnabled;
|
||||||
|
|
||||||
|
CaptureState mCaptureState {};
|
||||||
StatusChoice mCaptureState { StatusChoice::NoButton };
|
|
||||||
|
|
||||||
enum MouseEventState {
|
enum MouseEventState {
|
||||||
mesNone,
|
mesNone,
|
||||||
@ -483,6 +498,8 @@ private:
|
|||||||
mutable int mButtonFontSize { -1 };
|
mutable int mButtonFontSize { -1 };
|
||||||
mutable wxFont mButtonFont;
|
mutable wxFont mButtonFont;
|
||||||
|
|
||||||
|
bool mDoubleClick {};
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user