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:
parent
34026d19fd
commit
a94eb75b4e
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user