1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-18 09:00:52 +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;
const auto size = GetSize();
const TrackPanelMouseEvent tpmEvent{ event, rect, size, pCell };
HandleCursor( tpmEvent, foundCell.type );
HandleCursor( tpmEvent );
}
void TrackPanel::HandleCursor
( const TrackPanelMouseEvent &tpmEvent, CellType cellType )
void TrackPanel::HandleCursor( const TrackPanelMouseEvent &tpmEvent )
{
if ( mUIHandle ) {
// UIHANDLE PREVIEW
@ -875,22 +874,8 @@ void TrackPanel::HandleCursor
// Are we within the vertical resize area?
// (Add margin back to bottom of the rectangle)
auto &event = tpmEvent.event;
auto pCell = tpmEvent.pCell;
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()) {
const auto size = GetSize();
HitTestResult hitTest( pCell->HitTest(tpmEvent, GetProject()) );
@ -1524,9 +1509,7 @@ try
const auto foundCell = FindCell(event.m_x, event.m_y);
auto t = foundCell.pTrack;
if (t
&& foundCell.type == CellType::Track
)
if ( t )
EnsureVisible(t);
}
}
@ -1549,19 +1532,6 @@ void TrackPanel::HandleClick( const TrackPanelMouseEvent &tpmEvent )
const auto &rect = tpmEvent.rect;
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 )
mUIHandle =
pCell->HitTest( tpmEvent, GetProject() ).handle;
@ -2518,9 +2488,11 @@ void TrackPanel::DrawShadow(Track * /* t */ , wxDC * dc, const wxRect & rect)
/// @param mouseY - mouse Y position.
TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
{
enum class CellType { Label, Track, VRuler, Background };
auto size = GetSize();
size.x -= kRightMargin;
wxRect rect { 0, 0, 0, 0 };
bool betweenTracks = false;
// The type of cell that may be found is determined by the x coordinate.
CellType type = CellType::Track;
@ -2540,9 +2512,25 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
rect.width = size.x - GetLeftOffset();
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.
rect.y -= kTopMargin;
TrackPanelCell *pCell {};
if (pTrack) switch (type) {
case CellType::Label:
pCell = pTrack->GetTrackControl(); break;
@ -2552,9 +2540,9 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
pCell = pTrack; break;
}
if (pTrack)
return { pTrack, pCell, type, rect };
return { pTrack, pCell, rect };
else
return { nullptr, nullptr, type, {} };
return { nullptr, nullptr, {} };
};
VisibleTrackIterator iter(GetProject());
@ -2569,10 +2557,10 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
if (t->GetLink()) {
Track *l = t->GetLink();
int h = l->GetHeight();
if (!t->GetLinked()) {
if (!t->GetLinked())
rect.y = l->GetY() - mViewInfo->vpos + kTopMargin;
else
t = l;
rect.y = t->GetY() - mViewInfo->vpos + kTopMargin;
}
rect.height += h;
}
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
@ -2580,6 +2568,14 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
rect.height += t->GetHeight(true);
#endif
}
else {
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
if( MONO_WAVE_PAN(t) )
betweenTracks = true;
else
#endif
betweenTracks = t->GetLinked();
}
//Determine whether the mouse is inside
//the current rectangle. If so, return.
@ -2592,6 +2588,7 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
}
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
if(type != CellType::Label && MONO_WAVE_PAN(t)){
betweenTracks = false;
rect.y = t->GetY(true) - mViewInfo->vpos + kTopMargin;
rect.height = t->GetHeight(true);
if (rect.Contains(mouseX, mouseY)) {
@ -2612,15 +2609,12 @@ TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
rect.y =
std::min( size.y,
std::max( 0,
rect.y - kTopMargin + rect.height ) );
rect.y + rect.height ) );
rect.height = size.y - rect.y;
return {
nullptr, mpBackground.get(),
CellType::Background, rect
};
return { nullptr, mpBackground.get(), rect };
}
else
return { nullptr, nullptr, type, {} };
return { nullptr, nullptr, {} };
}
/// 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
// Find track info by coordinate
enum class CellType { Label, Track, VRuler, Background };
struct FoundCell {
Track *pTrack;
TrackPanelCell *pCell;
CellType type;
wxRect rect;
};
FoundCell FindCell(int mouseX, int mouseY);
void HandleCursor( wxMouseEvent *pEvent );
void HandleCursor
( const TrackPanelMouseEvent &tpmEvent,
CellType cellType = CellType::Background );
void HandleCursor( const TrackPanelMouseEvent &tpmEvent );
// If label, rectangle includes track control panel only.
// If !label, rectangle includes all of that, and the vertical ruler, and
@ -569,9 +565,4 @@ enum : int {
#pragma warning( pop )
#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

View File

@ -391,3 +391,17 @@ void TrackPanelResizeHandle::OnProjectChange(AudacityProject *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__
#define __AUDACITY_TRACK_PANEL_RESIZE_HANDLE__
#include "CommonTrackPanelCell.h"
#include "UIHandle.h"
struct HitTestResult;
@ -65,4 +66,23 @@ private:
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