mirror of
https://github.com/cookiengineer/audacity
synced 2025-11-14 17:14:07 +01:00
Rename TrackPanel::HandleCursor as HandleMotion...
Call HitTest in just one place Can now preserve repeatedly hit UIHandle objects during pre-click motion Fields of HitTestResult besides the handle pointer are now unused The need to repaint a track during mouse movement can be indicated when constructing a UIHandle or when updating it for move; HitPreview no longer does this And the last allows simplifications of LabelTrack glyph highlighting Also move the temporary state for label glyph dragging out of LabelTrack
This commit is contained in:
@@ -24,23 +24,32 @@ Paul Licameli split from TrackPanel.cpp
|
||||
#include <wx/translation.h>
|
||||
|
||||
LabelGlyphHandle::LabelGlyphHandle
|
||||
(const std::shared_ptr<LabelTrack> &pLT, const wxRect &rect)
|
||||
(const std::shared_ptr<LabelTrack> &pLT,
|
||||
const wxRect &rect, const LabelTrackHit &hit)
|
||||
: mpLT{ pLT }
|
||||
, mRect{ rect }
|
||||
{}
|
||||
, mHit{ hit }
|
||||
{
|
||||
mChangeHighlight = RefreshCode::RefreshCell;
|
||||
}
|
||||
|
||||
HitTestPreview LabelGlyphHandle::HitPreview
|
||||
(bool hitCenter, unsigned refreshResult)
|
||||
UIHandle::Result LabelGlyphHandle::NeedChangeHighlight
|
||||
(const LabelGlyphHandle &oldState, const LabelGlyphHandle &newState)
|
||||
{
|
||||
if (oldState.mHit.mEdge != newState.mHit.mEdge)
|
||||
// pointer moves between the circle and the chevron
|
||||
return RefreshCode::RefreshCell;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HitTestPreview LabelGlyphHandle::HitPreview(bool hitCenter)
|
||||
{
|
||||
static wxCursor arrowCursor{ wxCURSOR_ARROW };
|
||||
return {
|
||||
(hitCenter
|
||||
? _("Drag one or more label boundaries.")
|
||||
: _("Drag label boundary.")),
|
||||
&arrowCursor,
|
||||
// Unusually, can have a non-zero third member of HitTestPreview, so that
|
||||
// mouse-over highlights it.
|
||||
refreshResult
|
||||
&arrowCursor
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,39 +58,22 @@ HitTestResult LabelGlyphHandle::HitTest
|
||||
const wxMouseState &state,
|
||||
const std::shared_ptr<LabelTrack> &pLT, const wxRect &rect)
|
||||
{
|
||||
using namespace RefreshCode;
|
||||
unsigned refreshResult = RefreshNone;
|
||||
|
||||
// Note: this has side effects on pLT!
|
||||
int edge = pLT->OverGlyph(state.m_x, state.m_y);
|
||||
|
||||
//KLUDGE: We refresh the whole Label track when the icon hovered over
|
||||
//changes colouration. Inefficient.
|
||||
edge += pLT->mbHitCenter ? 4 : 0;
|
||||
if (edge != pLT->mOldEdge)
|
||||
{
|
||||
pLT->mOldEdge = edge;
|
||||
refreshResult |= RefreshCell;
|
||||
}
|
||||
LabelTrackHit hit{};
|
||||
pLT->OverGlyph(hit, state.m_x, state.m_y);
|
||||
|
||||
// IF edge!=0 THEN we've set the cursor and we're done.
|
||||
// signal this by setting the tip.
|
||||
if (edge != 0)
|
||||
if ( hit.mEdge & 3 )
|
||||
{
|
||||
auto result = std::make_shared<LabelGlyphHandle>( pLT, rect );
|
||||
auto result = std::make_shared<LabelGlyphHandle>( pLT, rect, hit );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return {
|
||||
HitPreview(pLT->mbHitCenter, refreshResult),
|
||||
HitPreview( hit.mEdge & 4 ),
|
||||
result
|
||||
};
|
||||
}
|
||||
else {
|
||||
// An empty result, except maybe, unusually, the refresh
|
||||
return {
|
||||
{ wxString{}, nullptr, refreshResult },
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
LabelGlyphHandle::~LabelGlyphHandle()
|
||||
@@ -96,9 +88,10 @@ UIHandle::Result LabelGlyphHandle::Click
|
||||
const wxMouseEvent &event = evt.event;
|
||||
|
||||
ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
mpLT->HandleGlyphClick(event, mRect, viewInfo, &viewInfo.selectedRegion);
|
||||
mpLT->HandleGlyphClick
|
||||
(mHit, event, mRect, viewInfo, &viewInfo.selectedRegion);
|
||||
|
||||
if (! mpLT->IsAdjustingLabel() )
|
||||
if (! mHit.mIsAdjustingLabel )
|
||||
{
|
||||
// The positive hit test should have ensured otherwise
|
||||
//wxASSERT(false);
|
||||
@@ -125,7 +118,8 @@ UIHandle::Result LabelGlyphHandle::Drag
|
||||
|
||||
const wxMouseEvent &event = evt.event;
|
||||
ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
mpLT->HandleGlyphDragRelease(event, mRect, viewInfo, &viewInfo.selectedRegion);
|
||||
mpLT->HandleGlyphDragRelease
|
||||
(mHit, event, mRect, viewInfo, &viewInfo.selectedRegion);
|
||||
|
||||
// Refresh all so that the change of selection is redrawn in all tracks
|
||||
return result | RefreshCode::RefreshAll | RefreshCode::DrawOverlays;
|
||||
@@ -134,7 +128,7 @@ UIHandle::Result LabelGlyphHandle::Drag
|
||||
HitTestPreview LabelGlyphHandle::Preview
|
||||
(const TrackPanelMouseState &, const AudacityProject *)
|
||||
{
|
||||
return HitPreview(mpLT->mbHitCenter, 0);
|
||||
return HitPreview( mHit.mEdge & 4 );
|
||||
}
|
||||
|
||||
UIHandle::Result LabelGlyphHandle::Release
|
||||
@@ -142,11 +136,11 @@ UIHandle::Result LabelGlyphHandle::Release
|
||||
wxWindow *pParent)
|
||||
{
|
||||
auto result = LabelDefaultClickHandle::Release( evt, pProject, pParent );
|
||||
mpLT->mOldEdge = 0;
|
||||
|
||||
const wxMouseEvent &event = evt.event;
|
||||
ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
if (mpLT->HandleGlyphDragRelease(event, mRect, viewInfo, &viewInfo.selectedRegion)) {
|
||||
if (mpLT->HandleGlyphDragRelease
|
||||
(mHit, event, mRect, viewInfo, &viewInfo.selectedRegion)) {
|
||||
pProject->PushState(_("Modified Label"),
|
||||
_("Label Edit"),
|
||||
UndoPush::CONSOLIDATE);
|
||||
@@ -158,7 +152,6 @@ UIHandle::Result LabelGlyphHandle::Release
|
||||
|
||||
UIHandle::Result LabelGlyphHandle::Cancel(AudacityProject *pProject)
|
||||
{
|
||||
mpLT->mOldEdge = 0;
|
||||
pProject->RollbackState();
|
||||
auto result = LabelDefaultClickHandle::Cancel( pProject );
|
||||
return result | RefreshCode::RefreshAll;
|
||||
|
||||
@@ -19,14 +19,33 @@ class wxMouseState;
|
||||
struct HitTestResult;
|
||||
class LabelTrack;
|
||||
|
||||
/// mEdge:
|
||||
/// 0 if not over a glyph,
|
||||
/// else a bitwise or of :
|
||||
/// 1 if over the left-hand glyph,
|
||||
/// 2 if over the right-hand glyph on a label,
|
||||
/// 4 if over center.
|
||||
///
|
||||
/// mMouseLabelLeft - index of any left label hit
|
||||
/// mMouseLabelRight - index of any right label hit
|
||||
///
|
||||
struct LabelTrackHit {
|
||||
int mEdge{};
|
||||
int mMouseOverLabelLeft{ -1 }; /// Keeps track of which left label the mouse is currently over.
|
||||
int mMouseOverLabelRight{ -1 }; /// Keeps track of which right label the mouse is currently over.
|
||||
bool mbIsMoving {};
|
||||
bool mIsAdjustingLabel {};
|
||||
};
|
||||
|
||||
class LabelGlyphHandle final : public LabelDefaultClickHandle
|
||||
{
|
||||
LabelGlyphHandle(const LabelGlyphHandle&) = delete;
|
||||
static HitTestPreview HitPreview(bool hitCenter, unsigned refreshResult);
|
||||
static HitTestPreview HitPreview(bool hitCenter);
|
||||
|
||||
public:
|
||||
explicit LabelGlyphHandle
|
||||
(const std::shared_ptr<LabelTrack> &pLT, const wxRect &rect);
|
||||
(const std::shared_ptr<LabelTrack> &pLT,
|
||||
const wxRect &rect, const LabelTrackHit &hit);
|
||||
|
||||
LabelGlyphHandle &operator=(LabelGlyphHandle&&) = default;
|
||||
|
||||
@@ -55,6 +74,11 @@ public:
|
||||
|
||||
bool StopsOnKeystroke() override { return true; }
|
||||
|
||||
LabelTrackHit mHit{};
|
||||
|
||||
static UIHandle::Result NeedChangeHighlight
|
||||
(const LabelGlyphHandle &oldState, const LabelGlyphHandle &newState);
|
||||
|
||||
private:
|
||||
std::shared_ptr<LabelTrack> mpLT {};
|
||||
wxRect mRect {};
|
||||
|
||||
@@ -31,13 +31,11 @@ HitTestResult LabelTrack::DetailedHitTest
|
||||
// Try label movement handles first
|
||||
result = LabelGlyphHandle::HitTest(
|
||||
mGlyphHandle, state, Pointer<LabelTrack>(this), st.rect);
|
||||
auto refresh = result.preview.refreshCode; // kludge
|
||||
|
||||
if ( !result.handle ) {
|
||||
// Missed glyph, try text box
|
||||
result = LabelTextHandle::HitTest(
|
||||
mTextHandle, state, Pointer<LabelTrack>(this));
|
||||
result.preview.refreshCode |= refresh; // kludge
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -46,9 +46,6 @@ HitTestResult Track::HitTest
|
||||
// If there is no detailed hit for the subclass, there are still some
|
||||
// general cases.
|
||||
|
||||
// Label track kludge!
|
||||
auto refresh = result.preview.refreshCode;
|
||||
|
||||
// Sliding applies in more than one track type.
|
||||
if ( !result.handle && !isMultiTool && currentTool == slideTool )
|
||||
result = TimeShiftHandle::HitAnywhere(
|
||||
@@ -65,7 +62,6 @@ HitTestResult Track::HitTest
|
||||
result = SelectHandle::HitTest(
|
||||
mSelectHandle, st, pProject, Pointer(this));
|
||||
|
||||
result.preview.refreshCode |= refresh;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user