From a94eb75b4ec75c8cf8931cf1c8383dd44271de4f Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Fri, 16 Jun 2017 16:49:49 -0400 Subject: [PATCH] Further regularize the odd case of hit-test on the resizer region --- src/TrackPanel.cpp | 84 ++++++++++++++++------------------ src/TrackPanel.h | 11 +---- src/TrackPanelResizeHandle.cpp | 14 ++++++ src/TrackPanelResizeHandle.h | 20 ++++++++ 4 files changed, 74 insertions(+), 55 deletions(-) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 8928c6467..4e9fa3490 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -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( 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( 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 diff --git a/src/TrackPanel.h b/src/TrackPanel.h index d39a35113..b454c79a3 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -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 diff --git a/src/TrackPanelResizeHandle.cpp b/src/TrackPanelResizeHandle.cpp index 90aab974e..c42350dd5 100644 --- a/src/TrackPanelResizeHandle.cpp +++ b/src/TrackPanelResizeHandle.cpp @@ -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() + }; +} diff --git a/src/TrackPanelResizeHandle.h b/src/TrackPanelResizeHandle.h index aa5cb5906..8f44685ec 100644 --- a/src/TrackPanelResizeHandle.h +++ b/src/TrackPanelResizeHandle.h @@ -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