mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-02 17:23:18 +02:00
Merge branch 'master' into scrubbing2
This commit is contained in:
commit
3347f2af70
@ -243,10 +243,31 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SetScrollbar(int position, int thumbSize,
|
||||
int range, int pageSize,
|
||||
bool refresh = true) override;
|
||||
|
||||
private:
|
||||
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)
|
||||
EVT_SET_FOCUS(ScrollBar::OnSetFocus)
|
||||
END_EVENT_TABLE()
|
||||
@ -933,14 +954,18 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
|
||||
mCursorOverlay = std::make_unique<EditCursorOverlay>(this);
|
||||
|
||||
#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);
|
||||
mScrubber = std::make_unique<Scrubber>(this);
|
||||
#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
|
||||
// earlier)
|
||||
this->Connect(EVT_TRACK_PANEL_TIMER,
|
||||
@ -1771,7 +1796,6 @@ void AudacityProject::FixScrollbars()
|
||||
|
||||
mHsbar->SetScrollbar(scaledSbarH + offset, scaledSbarScreen, scaledSbarTotal,
|
||||
scaledSbarScreen, TRUE);
|
||||
mHsbar->Refresh();
|
||||
}
|
||||
|
||||
// Vertical scrollbar
|
||||
@ -1779,7 +1803,6 @@ void AudacityProject::FixScrollbars()
|
||||
panelHeight / mViewInfo.scrollStep,
|
||||
totalHeight / mViewInfo.scrollStep,
|
||||
panelHeight / mViewInfo.scrollStep, TRUE);
|
||||
mVsbar->Refresh();
|
||||
|
||||
if (refresh || (rescroll &&
|
||||
(GetScreenEndTime() - mViewInfo.h) < mViewInfo.total)) {
|
||||
@ -5315,3 +5338,46 @@ int AudacityProject::GetEstimatedRecordingMinsLeftOnDisk() {
|
||||
int iRecMins = (int)(dRecTime / 60.0);
|
||||
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
|
||||
}
|
||||
|
@ -720,6 +720,28 @@ public:
|
||||
const Scrubber &GetScrubber() const { return *mScrubber; }
|
||||
#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()
|
||||
};
|
||||
|
||||
|
@ -5901,16 +5901,26 @@ void TrackPanel::OnMouseEvent(wxMouseEvent & event)
|
||||
ReleaseMouse();
|
||||
}
|
||||
|
||||
if (event.Leaving() && !event.ButtonIsDown(wxMOUSE_BTN_ANY))
|
||||
if (event.Leaving())
|
||||
{
|
||||
|
||||
// PRL: was this test really needed? It interfered with my refactoring
|
||||
// that tried to eliminate those enum values.
|
||||
// I think it was never true, that mouse capture was pan or gain sliding,
|
||||
// but no mouse button was down.
|
||||
// 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);
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
|
||||
// We must install the cursor ourselves since the window under
|
||||
// the mouse is no longer this one and wx2.8.12 makes that check.
|
||||
// Should re-evaluate with wx3.
|
||||
|
@ -738,16 +738,24 @@ void ControlToolBar::OnKeyEvent(wxKeyEvent & event)
|
||||
|
||||
void ControlToolBar::OnPlay(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
if (!CanStopAudioStream())
|
||||
return;
|
||||
auto doubleClicked = mPlay->IsDoubleClicked();
|
||||
mPlay->ClearDoubleClicked();
|
||||
|
||||
StopPlaying();
|
||||
auto p = GetActiveProject();
|
||||
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if (p) p->TP_DisplaySelection();
|
||||
if (doubleClicked)
|
||||
p->GetPlaybackScroller().Activate(true);
|
||||
else {
|
||||
if (!CanStopAudioStream())
|
||||
return;
|
||||
|
||||
PlayDefault();
|
||||
UpdateStatusBar(GetActiveProject());
|
||||
StopPlaying();
|
||||
|
||||
if (p) p->TP_DisplaySelection();
|
||||
|
||||
PlayDefault();
|
||||
UpdateStatusBar(p);
|
||||
}
|
||||
}
|
||||
|
||||
void ControlToolBar::OnStop(wxCommandEvent & WXUNUSED(evt))
|
||||
@ -778,9 +786,11 @@ void ControlToolBar::StopPlaying(bool stopStream /* = true*/)
|
||||
{
|
||||
AudacityProject *project = GetActiveProject();
|
||||
|
||||
if(project)
|
||||
if(project) {
|
||||
project->GetPlaybackScroller().Activate(false);
|
||||
// Let scrubbing code do some appearance change
|
||||
project->GetScrubber().StopScrubbing();
|
||||
}
|
||||
|
||||
if (!CanStopAudioStream())
|
||||
return;
|
||||
|
@ -474,11 +474,24 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview)
|
||||
// Come here from button clicks only
|
||||
void TranscriptionToolBar::OnPlaySpeed(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
// Let control have precedence over shift
|
||||
const bool cutPreview = mButtons[TTB_PlaySpeed]->WasControlDown();
|
||||
const bool looped = !cutPreview &&
|
||||
mButtons[TTB_PlaySpeed]->WasShiftDown();
|
||||
PlayAtSpeed(looped, cutPreview);
|
||||
auto button = mButtons[TTB_PlaySpeed];
|
||||
|
||||
auto doubleClicked = button->IsDoubleClicked();
|
||||
button->ClearDoubleClicked();
|
||||
|
||||
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))
|
||||
|
@ -200,7 +200,7 @@ void Scrubber::MarkScrubStart(
|
||||
// needed for the decision to start scrubbing later when handling
|
||||
// drag events.
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
mSmoothScrollingScrub = smoothScrolling;
|
||||
SetScrollScrubbing (smoothScrolling);
|
||||
#endif
|
||||
mAlwaysSeeking = alwaysSeeking;
|
||||
mScrubStartPosition = xx;
|
||||
@ -356,25 +356,6 @@ void Scrubber::ContinueScrubbing()
|
||||
if (mScrubSpeedDisplayCountdown > 0)
|
||||
--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()
|
||||
@ -382,7 +363,7 @@ void Scrubber::StopScrubbing()
|
||||
UncheckAllMenuItems();
|
||||
|
||||
mScrubStartPosition = -1;
|
||||
mSmoothScrollingScrub = false;
|
||||
SetScrollScrubbing (false);
|
||||
|
||||
if (!IsScrubbing())
|
||||
{
|
||||
@ -393,6 +374,12 @@ void Scrubber::StopScrubbing()
|
||||
}
|
||||
}
|
||||
|
||||
void Scrubber::SetScrollScrubbing(bool scrollScrubbing)
|
||||
{
|
||||
mSmoothScrollingScrub = scrollScrubbing;
|
||||
mProject->GetPlaybackScroller().Activate(scrollScrubbing);
|
||||
}
|
||||
|
||||
bool Scrubber::IsScrubbing() const
|
||||
{
|
||||
if (mScrubToken <= 0)
|
||||
@ -403,6 +390,7 @@ bool Scrubber::IsScrubbing() const
|
||||
const_cast<Scrubber&>(*this).mScrubToken = -1;
|
||||
const_cast<Scrubber&>(*this).mScrubStartPosition = -1;
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
// Don't call SetScrollScrubbing
|
||||
const_cast<Scrubber&>(*this).mSmoothScrollingScrub = false;
|
||||
#endif
|
||||
return false;
|
||||
@ -557,7 +545,6 @@ void ScrubbingOverlay::Draw
|
||||
dc.DrawText(mLastScrubSpeedText, mLastScrubRect.GetX(), mLastScrubRect.GetY());
|
||||
}
|
||||
|
||||
|
||||
void ScrubbingOverlay::OnTimer(wxCommandEvent &event)
|
||||
{
|
||||
// Let other listeners get the notification
|
||||
@ -666,7 +653,7 @@ void Scrubber::DoScrub(bool scroll, bool seek)
|
||||
MarkScrubStart(xx, scroll, seek);
|
||||
}
|
||||
else if(!match) {
|
||||
mSmoothScrollingScrub = scroll;
|
||||
SetScrollScrubbing(scroll);
|
||||
mAlwaysSeeking = seek;
|
||||
UncheckAllMenuItems();
|
||||
CheckMenuItem();
|
||||
|
@ -54,8 +54,11 @@ public:
|
||||
bool HasStartedScrubbing() const
|
||||
{ return GetScrubStartPosition() >= 0; }
|
||||
bool IsScrubbing() const;
|
||||
|
||||
bool IsScrollScrubbing() const // If true, implies HasStartedScrubbing()
|
||||
{ return mSmoothScrollingScrub; }
|
||||
void SetScrollScrubbing(bool scrollScrubbing);
|
||||
|
||||
bool IsAlwaysSeeking() const
|
||||
{ return mAlwaysSeeking; }
|
||||
|
||||
|
@ -407,6 +407,8 @@ void AButton::OnMouseEvent(wxMouseEvent & event)
|
||||
if (mEnabled && event.IsButton()) {
|
||||
if (event.ButtonIsDown(wxMOUSE_BTN_ANY)) {
|
||||
mIsClicking = true;
|
||||
if (event.ButtonDClick())
|
||||
mIsDoubleClicked = true;
|
||||
if( !HasCapture() )
|
||||
CaptureMouse();
|
||||
}
|
||||
|
@ -109,6 +109,11 @@ class AButton final : public wxWindow {
|
||||
bool WasControlDown(); // returns true if control was held down
|
||||
// the last time the button was clicked
|
||||
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 Toggle(){ mButtonIsDown ? PopUp() : PushDown();}
|
||||
void Click();
|
||||
@ -157,6 +162,7 @@ class AButton final : public wxWindow {
|
||||
bool mIsClicking;
|
||||
bool mEnabled;
|
||||
bool mUseDisabledAsDownHiliteImage;
|
||||
bool mIsDoubleClicked {};
|
||||
|
||||
struct ImageArr { ImageRoll mArr[4]; };
|
||||
std::vector<ImageArr> mImages;
|
||||
|
@ -85,6 +85,7 @@ array of Ruler::Label.
|
||||
#include "../tracks/ui/Scrubbing.h"
|
||||
|
||||
//#define SCRUB_ABOVE
|
||||
#define RULER_DOUBLE_CLICK
|
||||
|
||||
using std::min;
|
||||
using std::max;
|
||||
@ -2024,6 +2025,9 @@ void AdornedRulerPanel::OnCapture(wxCommandEvent & evt)
|
||||
// if recording is initiated by a modal window (Timer Record).
|
||||
SetCursor(mCursorDefault);
|
||||
mIsRecording = true;
|
||||
|
||||
// The quick play indicator is useless during recording
|
||||
HideQuickPlayIndicator();
|
||||
}
|
||||
else {
|
||||
SetCursor(mCursorHand);
|
||||
@ -2364,7 +2368,15 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RULER_DOUBLE_CLICK
|
||||
if (evt.LeftDClick()) {
|
||||
mDoubleClick = true;
|
||||
HandleQPDoubleClick(evt, mousePosX);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (evt.LeftDown()) {
|
||||
mDoubleClick = false;
|
||||
HandleQPClick(evt, mousePosX);
|
||||
HandleQPDrag(evt, mousePosX);
|
||||
}
|
||||
@ -2379,6 +2391,11 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
||||
}
|
||||
}
|
||||
|
||||
void AdornedRulerPanel::HandleQPDoubleClick(wxMouseEvent &evt, wxCoord mousePosX)
|
||||
{
|
||||
mProject->GetPlaybackScroller().Activate(true);
|
||||
}
|
||||
|
||||
void AdornedRulerPanel::HandleQPClick(wxMouseEvent &evt, wxCoord mousePosX)
|
||||
{
|
||||
// Temporarily unlock locked play region
|
||||
@ -2512,6 +2529,9 @@ void AdornedRulerPanel::HandleQPDrag(wxMouseEvent &event, wxCoord mousePosX)
|
||||
|
||||
void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
||||
{
|
||||
if (mDoubleClick)
|
||||
return;
|
||||
|
||||
HideQuickPlayIndicator();
|
||||
|
||||
if (HasCapture())
|
||||
@ -2552,6 +2572,28 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
||||
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.
|
||||
bool startPlaying = (mPlayRegionStart >= 0);
|
||||
|
||||
@ -2562,7 +2604,7 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
||||
bool loopEnabled = true;
|
||||
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.
|
||||
if ((mPlayRegionStart > sel0) && (mPlayRegionStart < sel1)) {
|
||||
// we are in a selection, so use the selection
|
||||
@ -2582,15 +2624,15 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
||||
loopEnabled = ((end - start) > 0.001)? true : false;
|
||||
|
||||
AudioIOStartStreamOptions options(mProject->GetDefaultPlayOptions());
|
||||
options.playLooped = (loopEnabled && evt.ShiftDown());
|
||||
options.playLooped = (loopEnabled && looped);
|
||||
|
||||
if (!evt.ControlDown())
|
||||
if (!cutPreview)
|
||||
options.pStartTime = &mPlayRegionStart;
|
||||
else
|
||||
options.timeTrack = NULL;
|
||||
|
||||
ControlToolBar::PlayAppearance appearance =
|
||||
evt.ControlDown() ? ControlToolBar::PlayAppearance::CutPreview
|
||||
cutPreview ? ControlToolBar::PlayAppearance::CutPreview
|
||||
: options.playLooped ? ControlToolBar::PlayAppearance::Looped
|
||||
: ControlToolBar::PlayAppearance::Straight;
|
||||
ctb->PlayPlayRegion((SelectedRegion(start, end)),
|
||||
@ -2603,18 +2645,6 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
|
||||
mPlayRegionEnd = end;
|
||||
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)
|
||||
|
@ -342,9 +342,11 @@ private:
|
||||
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)
|
||||
{
|
||||
@ -488,6 +490,8 @@ private:
|
||||
mutable int mButtonFontSize { -1 };
|
||||
mutable wxFont mButtonFont;
|
||||
|
||||
bool mDoubleClick {};
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user