1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-18 17:10:55 +02:00

Further regularize the odd case of hit-test on the resizer region

This commit is contained in:
Paul Licameli 2017-06-16 16:49:49 -04:00
parent 34026d19fd
commit a94eb75b4e
4 changed files with 74 additions and 55 deletions

View File

@ -854,11 +854,10 @@ void TrackPanel::HandleCursor( wxMouseEvent *pEvent )
auto &pCell = foundCell.pCell; auto &pCell = foundCell.pCell;
const auto size = GetSize(); const auto size = GetSize();
const TrackPanelMouseEvent tpmEvent{ event, rect, size, pCell }; const TrackPanelMouseEvent tpmEvent{ event, rect, size, pCell };
HandleCursor( tpmEvent, foundCell.type ); HandleCursor( tpmEvent );
} }
void TrackPanel::HandleCursor void TrackPanel::HandleCursor( const TrackPanelMouseEvent &tpmEvent )
( const TrackPanelMouseEvent &tpmEvent, CellType cellType )
{ {
if ( mUIHandle ) { if ( mUIHandle ) {
// UIHANDLE PREVIEW // UIHANDLE PREVIEW
@ -875,22 +874,8 @@ void TrackPanel::HandleCursor
// Are we within the vertical resize area? // Are we within the vertical resize area?
// (Add margin back to bottom of the rectangle) // (Add margin back to bottom of the rectangle)
auto &event = tpmEvent.event;
auto pCell = tpmEvent.pCell; auto pCell = tpmEvent.pCell;
auto track = static_cast<CommonTrackPanelCell*>( pCell )->FindTrack(); auto track = static_cast<CommonTrackPanelCell*>( pCell )->FindTrack();
auto &rect = tpmEvent.rect;
if (track &&
within(event.m_y, rect.GetBottom() + kBorderThickness, TRACK_RESIZE_REGION))
{
HitTestPreview preview
( TrackPanelResizeHandle::HitPreview(
( cellType != CellType::Label) && track->GetLinked() ) );
tip = preview.message;
wxCursor *const pCursor = preview.cursor;
if (pCursor)
SetCursor(*pCursor);
}
if (pCell && pCursor == NULL && tip == wxString()) { if (pCell && pCursor == NULL && tip == wxString()) {
const auto size = GetSize(); const auto size = GetSize();
HitTestResult hitTest( pCell->HitTest(tpmEvent, GetProject()) ); HitTestResult hitTest( pCell->HitTest(tpmEvent, GetProject()) );
@ -1524,9 +1509,7 @@ try
const auto foundCell = FindCell(event.m_x, event.m_y); const auto foundCell = FindCell(event.m_x, event.m_y);
auto t = foundCell.pTrack; auto t = foundCell.pTrack;
if (t if ( t )
&& foundCell.type == CellType::Track
)
EnsureVisible(t); EnsureVisible(t);
} }
} }
@ -1549,19 +1532,6 @@ void TrackPanel::HandleClick( const TrackPanelMouseEvent &tpmEvent )
const auto &rect = tpmEvent.rect; const auto &rect = tpmEvent.rect;
auto pTrack = static_cast<CommonTrackPanelCell *>( pCell )->FindTrack(); auto pTrack = static_cast<CommonTrackPanelCell *>( pCell )->FindTrack();
// see if I'm over the border area.
// TrackPanelResizeHandle is the UIHandle subclass that TrackPanel knows
// and uses directly, because allocating area to cells is TrackPanel's business,
// and we implement a "hit test" directly here.
if (mUIHandle == NULL &&
event.LeftDown()) {
if (pCell &&
(within(event.m_y,
(rect.GetBottom() + (kBottomMargin + kTopMargin) / 2),
TRACK_RESIZE_REGION)))
mUIHandle = &TrackPanelResizeHandle::Instance();
}
if ( !mUIHandle && pCell ) if ( !mUIHandle && pCell )
mUIHandle = mUIHandle =
pCell->HitTest( tpmEvent, GetProject() ).handle; pCell->HitTest( tpmEvent, GetProject() ).handle;
@ -2518,9 +2488,11 @@ void TrackPanel::DrawShadow(Track * /* t */ , wxDC * dc, const wxRect & rect)
/// @param mouseY - mouse Y position. /// @param mouseY - mouse Y position.
TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY) TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
{ {
enum class CellType { Label, Track, VRuler, Background };
auto size = GetSize(); auto size = GetSize();
size.x -= kRightMargin; size.x -= kRightMargin;
wxRect rect { 0, 0, 0, 0 }; wxRect rect { 0, 0, 0, 0 };
bool betweenTracks = false;
// The type of cell that may be found is determined by the x coordinate. // The type of cell that may be found is determined by the x coordinate.
CellType type = CellType::Track; CellType type = CellType::Track;
@ -2540,9 +2512,25 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
rect.width = size.x - GetLeftOffset(); rect.width = size.x - GetLeftOffset();
auto output = [&](Track *pTrack) -> FoundCell { auto output = [&](Track *pTrack) -> FoundCell {
TrackPanelCell *pCell {};
// Did we actually hit in the resizer region, which encompasses the
// bottom margin proper to "this" track, plus the top margin of the
// "next" track (or, an equally wide zone below, in case there is no
// next track)?
const auto margin = kBottomMargin + kTopMargin;
if ( rect.y + rect.height - mouseY <= margin ) {
auto instance = &TrackPanelResizerCell::Instance();
instance->mpTrack = pTrack;
instance->mBetweenTracks = betweenTracks;
pCell = instance;
rect.y = rect.y + rect.height - kTopMargin;
rect.height = margin;
return { pTrack, pCell, rect };
}
// Undo the bias mentioned below. // Undo the bias mentioned below.
rect.y -= kTopMargin; rect.y -= kTopMargin;
TrackPanelCell *pCell {};
if (pTrack) switch (type) { if (pTrack) switch (type) {
case CellType::Label: case CellType::Label:
pCell = pTrack->GetTrackControl(); break; pCell = pTrack->GetTrackControl(); break;
@ -2552,9 +2540,9 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
pCell = pTrack; break; pCell = pTrack; break;
} }
if (pTrack) if (pTrack)
return { pTrack, pCell, type, rect }; return { pTrack, pCell, rect };
else else
return { nullptr, nullptr, type, {} }; return { nullptr, nullptr, {} };
}; };
VisibleTrackIterator iter(GetProject()); VisibleTrackIterator iter(GetProject());
@ -2569,10 +2557,10 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
if (t->GetLink()) { if (t->GetLink()) {
Track *l = t->GetLink(); Track *l = t->GetLink();
int h = l->GetHeight(); int h = l->GetHeight();
if (!t->GetLinked()) { if (!t->GetLinked())
rect.y = l->GetY() - mViewInfo->vpos + kTopMargin;
else
t = l; t = l;
rect.y = t->GetY() - mViewInfo->vpos + kTopMargin;
}
rect.height += h; rect.height += h;
} }
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY #ifdef EXPERIMENTAL_OUTPUT_DISPLAY
@ -2580,6 +2568,14 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
rect.height += t->GetHeight(true); rect.height += t->GetHeight(true);
#endif #endif
} }
else {
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
if( MONO_WAVE_PAN(t) )
betweenTracks = true;
else
#endif
betweenTracks = t->GetLinked();
}
//Determine whether the mouse is inside //Determine whether the mouse is inside
//the current rectangle. If so, return. //the current rectangle. If so, return.
@ -2592,6 +2588,7 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
} }
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY #ifdef EXPERIMENTAL_OUTPUT_DISPLAY
if(type != CellType::Label && MONO_WAVE_PAN(t)){ if(type != CellType::Label && MONO_WAVE_PAN(t)){
betweenTracks = false;
rect.y = t->GetY(true) - mViewInfo->vpos + kTopMargin; rect.y = t->GetY(true) - mViewInfo->vpos + kTopMargin;
rect.height = t->GetHeight(true); rect.height = t->GetHeight(true);
if (rect.Contains(mouseX, mouseY)) { if (rect.Contains(mouseX, mouseY)) {
@ -2612,15 +2609,12 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
rect.y = rect.y =
std::min( size.y, std::min( size.y,
std::max( 0, std::max( 0,
rect.y - kTopMargin + rect.height ) ); rect.y + rect.height ) );
rect.height = size.y - rect.y; rect.height = size.y - rect.y;
return { return { nullptr, mpBackground.get(), rect };
nullptr, mpBackground.get(),
CellType::Background, rect
};
} }
else else
return { nullptr, nullptr, type, {} }; return { nullptr, nullptr, {} };
} }
/// This finds the rectangle of a given track, either the /// This finds the rectangle of a given track, either the

View File

@ -362,19 +362,15 @@ protected:
// a crash, as it can take many seconds for large (eg. 10 track-hours) projects // a crash, as it can take many seconds for large (eg. 10 track-hours) projects
// Find track info by coordinate // Find track info by coordinate
enum class CellType { Label, Track, VRuler, Background };
struct FoundCell { struct FoundCell {
Track *pTrack; Track *pTrack;
TrackPanelCell *pCell; TrackPanelCell *pCell;
CellType type;
wxRect rect; wxRect rect;
}; };
FoundCell FindCell(int mouseX, int mouseY); FoundCell FindCell(int mouseX, int mouseY);
void HandleCursor( wxMouseEvent *pEvent ); void HandleCursor( wxMouseEvent *pEvent );
void HandleCursor void HandleCursor( const TrackPanelMouseEvent &tpmEvent );
( const TrackPanelMouseEvent &tpmEvent,
CellType cellType = CellType::Background );
// If label, rectangle includes track control panel only. // If label, rectangle includes track control panel only.
// If !label, rectangle includes all of that, and the vertical ruler, and // If !label, rectangle includes all of that, and the vertical ruler, and
@ -569,9 +565,4 @@ enum : int {
#pragma warning( pop ) #pragma warning( pop )
#endif #endif
//This constant determines the size of the vertical region (in pixels) around
//the bottom of a track that can be used for vertical track resizing.
#define TRACK_RESIZE_REGION 5
#endif #endif

View File

@ -391,3 +391,17 @@ void TrackPanelResizeHandle::OnProjectChange(AudacityProject *pProject)
UIHandle::OnProjectChange(pProject); UIHandle::OnProjectChange(pProject);
} }
TrackPanelResizerCell &TrackPanelResizerCell::Instance()
{
static TrackPanelResizerCell instance;
return instance;
}
HitTestResult TrackPanelResizerCell::HitTest
(const TrackPanelMouseEvent &event, const AudacityProject *pProject)
{
return {
TrackPanelResizeHandle::HitPreview( mBetweenTracks ),
&TrackPanelResizeHandle::Instance()
};
}

View File

@ -11,6 +11,7 @@ Paul Licameli split from TrackPanel.cpp
#ifndef __AUDACITY_TRACK_PANEL_RESIZE_HANDLE__ #ifndef __AUDACITY_TRACK_PANEL_RESIZE_HANDLE__
#define __AUDACITY_TRACK_PANEL_RESIZE_HANDLE__ #define __AUDACITY_TRACK_PANEL_RESIZE_HANDLE__
#include "CommonTrackPanelCell.h"
#include "UIHandle.h" #include "UIHandle.h"
struct HitTestResult; struct HitTestResult;
@ -65,4 +66,23 @@ private:
int mMouseClickY{}; int mMouseClickY{};
}; };
class TrackPanelResizerCell : public CommonTrackPanelCell
{
TrackPanelResizerCell() {}
TrackPanelResizerCell(const TrackPanelResizerCell&) = delete;
TrackPanelResizerCell &operator= (const TrackPanelResizerCell&) = delete;
public:
static TrackPanelResizerCell &Instance();
HitTestResult HitTest
(const TrackPanelMouseEvent &event,
const AudacityProject *pProject) override;
Track *FindTrack() override { return mpTrack; };
private:
friend class TrackPanel;
Track *mpTrack {};
bool mBetweenTracks {};
};
#endif #endif