1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-04 22:49:07 +02:00

All UIHandle::Preview() return same cursors, messages as HitTest...

... except TrackSelectHandle.  Cursor changes to a hand only after button-down.

HitTests give a UIHandle, whenever they also give any cursor or status, even
when it's unsafe to click and drag; Click override is reponsible for cancelling.

SelectHandle::Preview introduces much duplication, but the original in the hit
test will later be deleted.
This commit is contained in:
Paul Licameli 2017-06-18 00:32:30 -04:00
parent 3a8280c562
commit d2fbca83b2
8 changed files with 159 additions and 69 deletions

View File

@ -155,10 +155,12 @@ UIHandle::Result StretchHandle::Click
{ {
using namespace RefreshCode; using namespace RefreshCode;
const bool unsafe = pProject->IsAudioActive(); const bool unsafe = pProject->IsAudioActive();
if ( unsafe )
return Cancelled;
const wxMouseEvent &event = evt.event; const wxMouseEvent &event = evt.event;
if (unsafe || if (event.LeftDClick() ||
event.LeftDClick() ||
!event.LeftDown() || !event.LeftDown() ||
evt.pCell == NULL) evt.pCell == NULL)
return Cancelled; return Cancelled;

View File

@ -50,12 +50,7 @@ HitTestPreview CutlineHandle::HitPreview(bool cutline, bool unsafe)
HitTestResult CutlineHandle::HitAnywhere(const AudacityProject *pProject, bool cutline) HitTestResult CutlineHandle::HitAnywhere(const AudacityProject *pProject, bool cutline)
{ {
const bool unsafe = pProject->IsAudioActive(); const bool unsafe = pProject->IsAudioActive();
return { return { HitPreview(cutline, unsafe), &Instance() };
HitPreview(cutline, unsafe),
(unsafe
? NULL
: &Instance())
};
} }
namespace namespace
@ -131,6 +126,11 @@ CutlineHandle::~CutlineHandle()
UIHandle::Result CutlineHandle::Click UIHandle::Result CutlineHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *pProject) (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
{ {
using namespace RefreshCode;
const bool unsafe = pProject->IsAudioActive();
if ( unsafe )
return Cancelled;
const wxMouseEvent &event = evt.event; const wxMouseEvent &event = evt.event;
ViewInfo &viewInfo = pProject->GetViewInfo(); ViewInfo &viewInfo = pProject->GetViewInfo();
const auto pTrack = static_cast<Track*>(evt.pCell.get()); const auto pTrack = static_cast<Track*>(evt.pCell.get());
@ -138,12 +138,8 @@ UIHandle::Result CutlineHandle::Click
// Can affect the track by merging clips, expanding a cutline, or // Can affect the track by merging clips, expanding a cutline, or
// deleting a cutline. // deleting a cutline.
// All the change is done at button-down. Button-up just commits the undo item. // All the change is done at button-down. Button-up just commits the undo item.
using namespace RefreshCode;
/// Someone has just clicked the mouse. What do we do? /// Someone has just clicked the mouse. What do we do?
const bool unsafe = pProject->IsAudioActive();
if (unsafe)
return Cancelled;
WaveTrackLocation capturedTrackLocation; WaveTrackLocation capturedTrackLocation;
@ -222,9 +218,10 @@ UIHandle::Result CutlineHandle::Drag
} }
HitTestPreview CutlineHandle::Preview HitTestPreview CutlineHandle::Preview
(const TrackPanelMouseState &, const AudacityProject *) (const TrackPanelMouseState &, const AudacityProject *pProject)
{ {
return HitPreview(mbCutline, false); const bool unsafe = pProject->IsAudioActive();
return HitPreview( mbCutline, unsafe );
} }
UIHandle::Result CutlineHandle::Release UIHandle::Result CutlineHandle::Release

View File

@ -67,12 +67,7 @@ HitTestResult SampleHandle::HitAnywhere
(const wxMouseState &state, const AudacityProject *pProject) (const wxMouseState &state, const AudacityProject *pProject)
{ {
const bool unsafe = pProject->IsAudioActive(); const bool unsafe = pProject->IsAudioActive();
return { return { HitPreview(state, pProject, unsafe), &Instance() };
HitPreview(state, pProject, unsafe),
(unsafe
? NULL
: &Instance())
};
} }
namespace { namespace {
@ -206,17 +201,17 @@ namespace {
UIHandle::Result SampleHandle::Click UIHandle::Result SampleHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *pProject) (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
{ {
using namespace RefreshCode;
const bool unsafe = pProject->IsAudioActive();
if ( unsafe )
return Cancelled;
const wxMouseEvent &event = evt.event; const wxMouseEvent &event = evt.event;
const wxRect &rect = evt.rect; const wxRect &rect = evt.rect;
const ViewInfo &viewInfo = pProject->GetViewInfo(); const ViewInfo &viewInfo = pProject->GetViewInfo();
const auto pTrack = std::static_pointer_cast<WaveTrack>(evt.pCell); const auto pTrack = std::static_pointer_cast<WaveTrack>(evt.pCell);
using namespace RefreshCode;
/// Someone has just clicked the mouse. What do we do? /// Someone has just clicked the mouse. What do we do?
const bool unsafe = pProject->IsAudioActive();
if (unsafe)
return Cancelled;
if (!IsSampleEditingPossible( if (!IsSampleEditingPossible(
event, rect, viewInfo, pTrack.get(), rect.width)) event, rect, viewInfo, pTrack.get(), rect.width))
return Cancelled; return Cancelled;
@ -419,7 +414,8 @@ UIHandle::Result SampleHandle::Drag
HitTestPreview SampleHandle::Preview HitTestPreview SampleHandle::Preview
(const TrackPanelMouseState &st, const AudacityProject *pProject) (const TrackPanelMouseState &st, const AudacityProject *pProject)
{ {
return HitPreview(st.state, pProject, false); const bool unsafe = pProject->IsAudioActive();
return HitPreview(st.state, pProject, unsafe);
} }
UIHandle::Result SampleHandle::Release UIHandle::Result SampleHandle::Release

View File

@ -54,12 +54,7 @@ HitTestPreview EnvelopeHandle::HitPreview(const AudacityProject *pProject, bool
HitTestResult EnvelopeHandle::HitAnywhere(const AudacityProject *pProject) HitTestResult EnvelopeHandle::HitAnywhere(const AudacityProject *pProject)
{ {
const bool unsafe = pProject->IsAudioActive(); const bool unsafe = pProject->IsAudioActive();
return { return { HitPreview(pProject, unsafe), &Instance() };
HitPreview(pProject, unsafe),
(unsafe
? NULL
: &Instance())
};
} }
namespace { namespace {
@ -182,15 +177,15 @@ EnvelopeHandle::~EnvelopeHandle()
UIHandle::Result EnvelopeHandle::Click UIHandle::Result EnvelopeHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *pProject) (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
{ {
using namespace RefreshCode;
const bool unsafe = pProject->IsAudioActive();
if ( unsafe )
return Cancelled;
const wxMouseEvent &event = evt.event; const wxMouseEvent &event = evt.event;
const ViewInfo &viewInfo = pProject->GetViewInfo(); const ViewInfo &viewInfo = pProject->GetViewInfo();
const auto pTrack = static_cast<Track*>(evt.pCell.get()); const auto pTrack = static_cast<Track*>(evt.pCell.get());
using namespace RefreshCode;
const bool unsafe = pProject->IsAudioActive();
if (unsafe)
return Cancelled;
if (pTrack->GetKind() == Track::Wave) { if (pTrack->GetKind() == Track::Wave) {
WaveTrack *const wt = static_cast<WaveTrack*>(pTrack); WaveTrack *const wt = static_cast<WaveTrack*>(pTrack);
if (wt->GetDisplay() != WaveTrack::Waveform) if (wt->GetDisplay() != WaveTrack::Waveform)
@ -257,7 +252,8 @@ UIHandle::Result EnvelopeHandle::Drag
HitTestPreview EnvelopeHandle::Preview HitTestPreview EnvelopeHandle::Preview
(const TrackPanelMouseState &, const AudacityProject *pProject) (const TrackPanelMouseState &, const AudacityProject *pProject)
{ {
return HitPreview(pProject, false); const bool unsafe = pProject->IsAudioActive();
return HitPreview(pProject, unsafe);
} }
UIHandle::Result EnvelopeHandle::Release UIHandle::Result EnvelopeHandle::Release

View File

@ -49,6 +49,11 @@ enum {
// #define SPECTRAL_EDITING_ESC_KEY // #define SPECTRAL_EDITING_ESC_KEY
bool SelectHandle::IsClicked() const
{
return mSelectionStateChanger.get();
}
SelectHandle::SelectHandle() SelectHandle::SelectHandle()
{ {
} }
@ -888,14 +893,95 @@ UIHandle::Result SelectHandle::Drag
} }
HitTestPreview SelectHandle::Preview HitTestPreview SelectHandle::Preview
(const TrackPanelMouseState &, const AudacityProject *pProject) (const TrackPanelMouseState &st, const AudacityProject *pProject)
{ {
auto pTrack = mpTrack.lock();
if (!pTrack)
return {};
wxString tip; wxString tip;
wxCursor *pCursor; wxCursor *pCursor = SelectCursor();
SetTipAndCursorForBoundary if ( IsClicked() )
(SelectionBoundary(mSelectionBoundary), // Use same cursor as at the clck
(mFreqSelMode == FREQ_SEL_SNAPPING_CENTER), SetTipAndCursorForBoundary
tip, pCursor); (SelectionBoundary(mSelectionBoundary),
(mFreqSelMode == FREQ_SEL_SNAPPING_CENTER),
tip, pCursor);
else {
// Choose one of many cursors for mouse-over
const ViewInfo &viewInfo = pProject->GetViewInfo();
const bool bMultiToolMode =
pProject->GetToolsToolBar()->IsDown(multiTool);
//In Multi-tool mode, give multitool prompt if no-special-hit.
if (bMultiToolMode) {
// Look up the current key binding for Preferences.
// (Don't assume it's the default!)
wxString keyStr
(pProject->GetCommandManager()->GetKeyFromName(wxT("Preferences")));
if (keyStr.IsEmpty())
// No keyboard preference defined for opening Preferences dialog
/* i18n-hint: These are the names of a menu and a command in that menu */
keyStr = _("Edit, Preferences...");
else
keyStr = KeyStringDisplay(keyStr);
/* i18n-hint: %s is usually replaced by "Ctrl+P" for Windows/Linux, "Command+," for Mac */
tip = wxString::Format(
_("Multi-Tool Mode: %s for Mouse and Keyboard Preferences."),
keyStr.c_str());
// Later in this function we may point to some other string instead.
if (!pTrack->GetSelected() ||
!viewInfo.bAdjustSelectionEdges)
;
else {
const auto &state = st.state;
const wxRect &rect = st.rect;
const bool bShiftDown = state.ShiftDown();
const bool bCtrlDown = state.ControlDown();
const bool bModifierDown = bShiftDown || bCtrlDown;
// If not shift-down and not snapping center, then
// choose boundaries only in snapping tolerance,
// and may choose center.
SelectionBoundary boundary =
ChooseBoundary(viewInfo, state, pTrack.get(), rect, !bModifierDown, !bModifierDown);
SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
}
}
#if 0
// This is a vestige of an idea in the prototype version.
// Center would snap without mouse button down, click would pin the center
// and drag width.
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
if ((mFreqSelMode == FREQ_SEL_SNAPPING_CENTER) &&
isSpectralSelectionTrack(pTrack)) {
// Not shift-down, but center frequency snapping toggle is on
tip = _("Click and drag to set frequency bandwidth.");
pCursor = &*envelopeCursor;
return {};
}
#endif
#endif
if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
;
else {
const auto &state = st.state;
const wxRect &rect = st.rect;
const bool bShiftDown = state.ShiftDown();
const bool bCtrlDown = state.ControlDown();
const bool bModifierDown = bShiftDown || bCtrlDown;
SelectionBoundary boundary = ChooseBoundary(
viewInfo, state, pTrack.get(), rect, !bModifierDown, !bModifierDown);
SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
}
MaySetOnDemandTip(pTrack.get(), tip);
}
if (tip == "") { if (tip == "") {
const auto ttb = pProject->GetToolsToolBar(); const auto ttb = pProject->GetToolsToolBar();
if (ttb) if (ttb)

View File

@ -45,6 +45,8 @@ public:
virtual ~SelectHandle(); virtual ~SelectHandle();
bool IsClicked() const;
virtual Result Click virtual Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject); (const TrackPanelMouseEvent &event, AudacityProject *pProject);

View File

@ -54,12 +54,7 @@ HitTestResult TimeShiftHandle::HitAnywhere(const AudacityProject *pProject)
// After all that, it still may be unsafe to drag. // After all that, it still may be unsafe to drag.
// Even if so, make an informative cursor change from default to "banned." // Even if so, make an informative cursor change from default to "banned."
const bool unsafe = pProject->IsAudioActive(); const bool unsafe = pProject->IsAudioActive();
return { return { HitPreview(pProject, unsafe), &Instance() };
HitPreview(pProject, unsafe),
(unsafe
? NULL
: &Instance())
};
} }
HitTestResult TimeShiftHandle::HitTest HitTestResult TimeShiftHandle::HitTest
@ -413,18 +408,17 @@ void TimeShiftHandle::DoSlideHorizontal
UIHandle::Result TimeShiftHandle::Click UIHandle::Result TimeShiftHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *pProject) (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
{ {
using namespace RefreshCode;
const bool unsafe = pProject->IsAudioActive();
if ( unsafe )
return Cancelled;
const wxMouseEvent &event = evt.event; const wxMouseEvent &event = evt.event;
const wxRect &rect = evt.rect; const wxRect &rect = evt.rect;
const ViewInfo &viewInfo = pProject->GetViewInfo(); const ViewInfo &viewInfo = pProject->GetViewInfo();
const auto pTrack = std::static_pointer_cast<Track>(evt.pCell); const auto pTrack = std::static_pointer_cast<Track>(evt.pCell);
using namespace RefreshCode;
const bool unsafe = pProject->IsAudioActive();
if (unsafe)
return Cancelled;
TrackList *const trackList = pProject->GetTracks(); TrackList *const trackList = pProject->GetTracks();
mClipMoveState.clear(); mClipMoveState.clear();
@ -771,7 +765,10 @@ UIHandle::Result TimeShiftHandle::Drag
HitTestPreview TimeShiftHandle::Preview HitTestPreview TimeShiftHandle::Preview
(const TrackPanelMouseState &, const AudacityProject *pProject) (const TrackPanelMouseState &, const AudacityProject *pProject)
{ {
return HitPreview(pProject, false); // After all that, it still may be unsafe to drag.
// Even if so, make an informative cursor change from default to "banned."
const bool unsafe = pProject->IsAudioActive();
return HitPreview(pProject, unsafe);
} }
UIHandle::Result TimeShiftHandle::Release UIHandle::Result TimeShiftHandle::Release

View File

@ -83,6 +83,9 @@ TrackSelectHandle::~TrackSelectHandle()
UIHandle::Result TrackSelectHandle::Click UIHandle::Result TrackSelectHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *pProject) (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
{ {
// If unsafe to drag, still, it does harmlessly change the selected track
// set on button down.
using namespace RefreshCode; using namespace RefreshCode;
Result result = RefreshNone; Result result = RefreshNone;
@ -165,19 +168,30 @@ UIHandle::Result TrackSelectHandle::Drag
HitTestPreview TrackSelectHandle::Preview HitTestPreview TrackSelectHandle::Preview
(const TrackPanelMouseState &, const AudacityProject *project) (const TrackPanelMouseState &, const AudacityProject *project)
{ {
// Note that this differs from HitPreview. const auto trackCount = project->GetTrackPanel()->GetTrackCount();
if (mpTrack) {
// Has been clicked
static auto disabledCursor =
::MakeCursor(wxCURSOR_NO_ENTRY, DisabledCursorXpm, 16, 16);
static wxCursor rearrangeCursor{ wxCURSOR_HAND };
static auto disabledCursor = const bool unsafe = GetActiveProject()->IsAudioActive();
::MakeCursor(wxCURSOR_NO_ENTRY, DisabledCursorXpm, 16, 16); return {
static wxCursor rearrangeCursor{ wxCURSOR_HAND }; Message(trackCount),
(unsafe
const bool unsafe = GetActiveProject()->IsAudioActive(); ? &*disabledCursor
return { : &rearrangeCursor)
Message(project->GetTrackPanel()->GetTrackCount()), };
(unsafe }
? &*disabledCursor else {
: &rearrangeCursor) // Only mouse-over
}; // Don't test safety, because the click to change selection is allowed
static wxCursor arrowCursor{ wxCURSOR_ARROW };
return {
Message(trackCount),
&arrowCursor
};
}
} }
UIHandle::Result TrackSelectHandle::Release UIHandle::Result TrackSelectHandle::Release