diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index 3e2bba6b41a0..830ac3dd8b5f 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -130,6 +130,9 @@ class AdornedRulerPanel::CommonRulerHandle : public UIHandle , mChoice( menuChoice ) {} + std::shared_ptr FindChannel() const override + { return nullptr; } + bool Clicked() const { return mClicked != Button::None; } static UIHandle::Result NeedChangeHighlight( @@ -922,6 +925,9 @@ class PlayheadHandle : public UIHandle , mX( xx ) {} + std::shared_ptr FindChannel() const override + { return nullptr; } + static UIHandle::Result NeedChangeHighlight( const PlayheadHandle &oldState, const PlayheadHandle &newState) { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 91ad4dd5c933..6b2047c81a3c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -811,6 +811,8 @@ list( APPEND SOURCES tracks/ui/CommonChannelView.h tracks/ui/CommonTrackControls.cpp tracks/ui/CommonTrackControls.h + tracks/ui/CommonTrackInfo.cpp + tracks/ui/CommonTrackInfo.h tracks/ui/CommonTrackPanelCell.cpp tracks/ui/CommonTrackPanelCell.h tracks/ui/EditCursorOverlay.cpp diff --git a/src/CellularPanel.cpp b/src/CellularPanel.cpp index b6c72e07eb9d..e91f93276911 100644 --- a/src/CellularPanel.cpp +++ b/src/CellularPanel.cpp @@ -861,6 +861,9 @@ class DefaultRightButtonHandler : public UIHandle { ~DefaultRightButtonHandler() override; + std::shared_ptr FindChannel() const override + { return nullptr; } + virtual Result Click (const TrackPanelMouseEvent &event, AudacityProject *pProject) override { diff --git a/src/EnvelopeEditor.cpp b/src/EnvelopeEditor.cpp index 7d1a2d682de8..d7fcca4e8a84 100644 --- a/src/EnvelopeEditor.cpp +++ b/src/EnvelopeEditor.cpp @@ -22,6 +22,7 @@ #include "TrackArtist.h" #include "TrackPanelDrawingContext.h" #include "ViewInfo.h" +#include "tracks/ui/EnvelopeHandle.h" namespace { void DrawPoint(wxDC & dc, const wxRect & r, int x, int y, bool top) @@ -45,7 +46,7 @@ void EnvelopeEditor::DrawPoints(const Envelope &env, bool highlight = false; #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING auto target = dynamic_cast(context.target.get()); - highlight = target && target->GetEnvelope() == this; + highlight = target && target->GetEnvelope() == &env; #endif wxPen &pen = highlight ? AColor::uglyPen : AColor::envelopePen; dc.SetPen( pen ); diff --git a/src/TrackInfo.cpp b/src/TrackInfo.cpp index d4d52dce4c79..f60d4d4c98a3 100644 --- a/src/TrackInfo.cpp +++ b/src/TrackInfo.cpp @@ -6,22 +6,6 @@ TrackInfo.cpp Paul Licameli split from TrackPanel.cpp -********************************************************************//*! - -\namespace TrackInfo -\brief - Functions for drawing the track control panel, which is shown to the side - of a track - It has the menus, pan and gain controls displayed in it. - So "Info" is somewhat a misnomer. Should possibly be "TrackControls". - - It maintains global slider widget instances that are reparented and - repositioned as needed for drawing and interaction with the user, - interoperating with the custom panel subdivision implemented in CellularPanel - and avoiding wxWidgets sizers - - If we'd instead coded it as a wxWindow, we would have an instance - of this class for each track displayed. **********************************************************************/ @@ -30,7 +14,8 @@ Paul Licameli split from TrackPanel.cpp #include #include -#include +#include +#include #include "AColor.h" #include "AllThemeResources.h" @@ -40,6 +25,7 @@ Paul Licameli split from TrackPanel.cpp #include "SyncLock.h" #include "Theme.h" #include "TrackPanelDrawingContext.h" +#include "UIHandle.h" #include "ViewInfo.h" #include "tracks/ui/ChannelView.h" @@ -88,55 +74,6 @@ static Settings &settings() return theSettings; } -bool TrackInfo::HasSoloButton() -{ - return TracksBehaviorsSolo.ReadEnum() != SoloBehaviorNone; -} - -#define RANGE(array) (array), (array) + sizeof(array)/sizeof(*(array)) -using TCPLine = TrackInfo::TCPLine; -using TCPLines = TrackInfo::TCPLines; - -static const TCPLines &commonTrackTCPLines() -{ - static const TCPLines theLines{ -#ifdef EXPERIMENTAL_DA - - { TCPLine::kItemBarButtons, kTrackInfoBtnSize, 4, - &TrackInfo::CloseTitleDrawFunction }, - -#else - - { TCPLine::kItemBarButtons, kTrackInfoBtnSize, 0, - &TrackInfo::CloseTitleDrawFunction }, - -#endif - }; - return theLines; -} - -#include "tracks/ui/CommonTrackControls.h" -const TCPLines &CommonTrackControls::StaticTCPLines() -{ - return commonTrackTCPLines(); -} - -namespace { - -int totalTCPLines( const TCPLines &lines, bool omitLastExtra ) -{ - int total = 0; - int lastExtra = 0; - for ( const auto line : lines ) { - lastExtra = line.extraSpace; - total += line.height + lastExtra; - } - if (omitLastExtra) - total -= lastExtra; - return total; -} -} - // return y value and height std::pair< int, int > TrackInfo::CalcItemY( const TCPLines &lines, unsigned iItem ) @@ -154,416 +91,9 @@ TrackInfo::CalcItemY( const TCPLines &lines, unsigned iItem ) return { y, height }; } -namespace { - -// Items for the bottom of the panel, listed bottom-upwards -// As also with the top items, the extra space is below the item -const TrackInfo::TCPLine defaultCommonTrackTCPBottomLines[] = { - // The '0' avoids impinging on bottom line of TCP - // Use -1 if you do want to do so. - { TCPLine::kItemSyncLock | TCPLine::kItemMinimize, kTrackInfoBtnSize, 0, - &TrackInfo::MinimizeSyncLockDrawFunction }, -}; -TCPLines commonTrackTCPBottomLines{ RANGE(defaultCommonTrackTCPBottomLines) }; - -// return y value and height -std::pair< int, int > CalcBottomItemY - ( const TCPLines &lines, unsigned iItem, int height ) -{ - int y = height; - auto pLines = lines.begin(); - while ( pLines != lines.end() && - 0 == (pLines->items & iItem) ) { - y -= pLines->height + pLines->extraSpace; - ++pLines; - } - if (pLines != lines.end()) - y -= (pLines->height + pLines->extraSpace ); - return { y, pLines->height }; -} - -} - -const TCPLines &CommonTrackControls::GetTCPLines() const -{ - return commonTrackTCPLines(); -} - -unsigned TrackInfo::MinimumTrackHeight() -{ - unsigned height = 0; - if (!commonTrackTCPLines().empty()) - height += commonTrackTCPLines().front().height; - if (!commonTrackTCPBottomLines.empty()) - height += commonTrackTCPBottomLines.front().height; - // + 1 prevents the top item from disappearing for want of enough space, - // according to the rules in HideTopItem. - return height + kVerticalPadding + 1; -} - -bool TrackInfo::HideTopItem( const wxRect &rect, const wxRect &subRect, - int allowance ) { - auto limit = CalcBottomItemY - ( commonTrackTCPBottomLines, TCPLine::kHighestBottomItem, rect.height).first; - // Return true if the rectangle is even touching the limit - // without an overlap. That was the behavior as of 2.1.3. - return subRect.y + subRect.height - allowance >= rect.y + limit; -} - -void TrackInfo::DrawItems -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track &track ) -{ - auto &trackControl = static_cast( - TrackControls::Get( track ) ); - const auto &topLines = trackControl.GetTCPLines(); - const auto &bottomLines = commonTrackTCPBottomLines; - DrawItems - ( context, rect, &track, topLines, bottomLines ); -} - -void TrackInfo::DrawItems -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack, - const std::vector &topLines, const std::vector &bottomLines ) -{ - auto dc = &context.dc; - TrackInfo::SetTrackInfoFont(dc); - dc->SetTextForeground(theTheme.Colour(clrTrackPanelText)); - - { - int yy = 0; - for ( const auto &line : topLines ) { - wxRect itemRect{ - rect.x, rect.y + yy, - rect.width, line.height - }; - if ( !TrackInfo::HideTopItem( rect, itemRect ) && - line.drawFunction ) - line.drawFunction( context, itemRect, pTrack ); - yy += line.height + line.extraSpace; - } - } - { - int yy = rect.height; - for ( const auto &line : bottomLines ) { - yy -= line.height + line.extraSpace; - if ( line.drawFunction ) { - wxRect itemRect{ - rect.x, rect.y + yy, - rect.width, line.height - }; - line.drawFunction( context, itemRect, pTrack ); - } - } - } -} - -#include "tracks/ui/TrackButtonHandles.h" -void TrackInfo::DrawCloseButton( - TrackPanelDrawingContext &context, const wxRect &bev, - const Track *pTrack, ButtonHandle *target ) -{ - auto dc = &context.dc; - bool selected = pTrack ? pTrack->GetSelected() : true; - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - AColor::Bevel2(*dc, !down, bev, selected, hit ); - -#ifdef EXPERIMENTAL_THEMING - wxPen pen( theTheme.Colour( clrTrackPanelText )); - dc->SetPen( pen ); -#else - dc->SetPen(*wxBLACK_PEN); -#endif - bev.Inflate( -1, -1 ); - // Draw the "X" - const int s = 6; - - int ls = bev.x + ((bev.width - s) / 2); - int ts = bev.y + ((bev.height - s) / 2); - int rs = ls + s; - int bs = ts + s; - - AColor::Line(*dc, ls, ts, rs, bs); - AColor::Line(*dc, ls + 1, ts, rs + 1, bs); - AColor::Line(*dc, rs, ts, ls, bs); - AColor::Line(*dc, rs + 1, ts, ls + 1, bs); - // bev.Inflate(-1, -1); -} - -void TrackInfo::CloseTitleDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - bool selected = pTrack ? pTrack->GetSelected() : true; - { - wxRect bev = rect; - GetCloseBoxHorizontalBounds( rect, bev ); - auto target = dynamic_cast( context.target.get() ); - DrawCloseButton( context, bev, pTrack, target ); - } - - { - wxRect bev = rect; - GetTitleBarHorizontalBounds( rect, bev ); - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - wxString titleStr = - pTrack ? pTrack->GetName() : _("Name"); - - //bev.Inflate(-1, -1); - AColor::Bevel2(*dc, !down, bev, selected, hit); - - // Draw title text - SetTrackInfoFont(dc); - - // Bug 1660 The 'k' of 'Audio Track' was being truncated. - // Constant of 32 found by counting pixels on a windows machine. - // I believe it's the size of the X close button + the size of the - // drop down arrow. - int allowableWidth = rect.width - 32; - - wxCoord textWidth, textHeight; - dc->GetTextExtent(titleStr, &textWidth, &textHeight); - while (textWidth > allowableWidth) { - titleStr = titleStr.Left(titleStr.length() - 1); - dc->GetTextExtent(titleStr, &textWidth, &textHeight); - } - - // Pop-up triangle - #ifdef EXPERIMENTAL_THEMING - wxColour c = theTheme.Colour( clrTrackPanelText ); - #else - wxColour c = *wxBLACK; - #endif - - // wxGTK leaves little scraps (antialiasing?) of the - // characters if they are repeatedly drawn. This - // happens when holding down mouse button and moving - // in and out of the title bar. So clear it first. - // AColor::MediumTrackInfo(dc, t->GetSelected()); - // dc->DrawRectangle(bev); - - dc->SetTextForeground( c ); - dc->SetTextBackground( wxTRANSPARENT ); - dc->DrawText(titleStr, bev.x + 2, bev.y + (bev.height - textHeight) / 2); - - - - dc->SetPen(c); - dc->SetBrush(c); - - int s = 10; // Width of dropdown arrow...height is half of width - AColor::Arrow(*dc, - bev.GetRight() - s - 3, // 3 to offset from right border - bev.y + ((bev.height - (s / 2)) / 2), - s); - - } -} - -void TrackInfo::MinimizeSyncLockDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - bool selected = pTrack ? pTrack->GetSelected() : true; - bool syncLockSelected = pTrack ? SyncLock::IsSyncLockSelected(pTrack) : true; - bool minimized = - pTrack ? ChannelView::Get(*pTrack->GetChannel(0)).GetMinimized() : false; - { - wxRect bev = rect; - GetMinimizeHorizontalBounds(rect, bev); - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - - // Clear background to get rid of previous arrow - //AColor::MediumTrackInfo(dc, t->GetSelected()); - //dc->DrawRectangle(bev); - - AColor::Bevel2(*dc, !down, bev, selected, hit); - -#ifdef EXPERIMENTAL_THEMING - wxColour c = theTheme.Colour(clrTrackPanelText); - dc->SetBrush(c); - dc->SetPen(c); -#else - AColor::Dark(dc, selected); -#endif - - AColor::Arrow(*dc, - bev.x - 5 + bev.width / 2, - bev.y - 2 + bev.height / 2, - 10, - minimized); - } - - { - wxRect bev = rect; - GetSelectButtonHorizontalBounds(rect, bev); - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - - AColor::Bevel2(*dc, !down, bev, selected, hit); - -#ifdef EXPERIMENTAL_THEMING - wxColour c = theTheme.Colour(clrTrackPanelText); - dc->SetBrush(c); - dc->SetPen(c); -#else - AColor::Dark(dc, selected); -#endif - - wxString str = _("Select"); - wxCoord textWidth; - wxCoord textHeight; - SetTrackInfoFont(dc); - dc->GetTextExtent(str, &textWidth, &textHeight); - - dc->SetTextForeground( c ); - dc->SetTextBackground( wxTRANSPARENT ); - dc->DrawText(str, bev.x + 2 + (bev.width-textWidth)/2, bev.y + (bev.height - textHeight) / 2); - } - - - // Draw the sync-lock indicator if this track is in a sync-lock selected group. - if (syncLockSelected) - { - wxRect syncLockIconRect = rect; - - GetSyncLockHorizontalBounds( rect, syncLockIconRect ); - wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockIcon)); - // Icon is 12x12 and syncLockIconRect is 16x16. - dc->DrawBitmap(syncLockBitmap, - syncLockIconRect.x + 3, - syncLockIconRect.y + 2, - true); - } -} - -void TrackInfo::GetCloseBoxHorizontalBounds( const wxRect & rect, wxRect &dest ) -{ - dest.x = rect.x; - dest.width = kTrackInfoBtnSize; -} - -void TrackInfo::GetCloseBoxRect(const wxRect & rect, wxRect & dest) -{ - GetCloseBoxHorizontalBounds( rect, dest ); - auto results = CalcItemY( commonTrackTCPLines(), TCPLine::kItemBarButtons ); - dest.y = rect.y + results.first; - dest.height = results.second; -} - -void TrackInfo::GetTitleBarHorizontalBounds( const wxRect & rect, wxRect &dest ) -{ - // to right of CloseBoxRect, plus a little more - wxRect closeRect; - GetCloseBoxHorizontalBounds( rect, closeRect ); - dest.x = rect.x + closeRect.width + 1; - dest.width = rect.x + rect.width - dest.x + TitleSoloBorderOverlap; -} - -void TrackInfo::GetTitleBarRect(const wxRect & rect, wxRect & dest) -{ - GetTitleBarHorizontalBounds( rect, dest ); - auto results = CalcItemY( commonTrackTCPLines(), TCPLine::kItemBarButtons ); - dest.y = rect.y + results.first; - dest.height = results.second; -} - -void TrackInfo::GetSliderHorizontalBounds( const wxPoint &topleft, wxRect &dest ) -{ - dest.x = topleft.x + 6; - dest.width = kTrackInfoSliderWidth; -} - -void TrackInfo::GetMinimizeHorizontalBounds( const wxRect &rect, wxRect &dest ) -{ - const int space = 0;// was 3. - dest.x = rect.x + space; - - wxRect syncLockRect; - GetSyncLockHorizontalBounds( rect, syncLockRect ); - - // Width is rect.width less space on left for track select - // and on right for sync-lock icon. - dest.width = kTrackInfoBtnSize; -// rect.width - (space + syncLockRect.width); -} - -void TrackInfo::GetMinimizeRect(const wxRect & rect, wxRect &dest) -{ - GetMinimizeHorizontalBounds( rect, dest ); - auto results = CalcBottomItemY - ( commonTrackTCPBottomLines, TCPLine::kItemMinimize, rect.height); - dest.y = rect.y + results.first; - dest.height = results.second; -} - -void TrackInfo::GetSelectButtonHorizontalBounds( const wxRect &rect, wxRect &dest ) -{ - const int space = 0;// was 3. - dest.x = rect.x + space; - - wxRect syncLockRect; - GetSyncLockHorizontalBounds( rect, syncLockRect ); - wxRect minimizeRect; - GetMinimizeHorizontalBounds( rect, minimizeRect ); - - dest.x = dest.x + space + minimizeRect.width; - // Width is rect.width less space on left for track select - // and on right for sync-lock icon. - dest.width = rect.width - (space + syncLockRect.width) - (space + minimizeRect.width); -} - - -void TrackInfo::GetSelectButtonRect(const wxRect & rect, wxRect &dest) -{ - GetSelectButtonHorizontalBounds( rect, dest ); - auto results = CalcBottomItemY - ( commonTrackTCPBottomLines, TCPLine::kItemMinimize, rect.height); - dest.y = rect.y + results.first; - dest.height = results.second; -} - -void TrackInfo::GetSyncLockHorizontalBounds( const wxRect &rect, wxRect &dest ) -{ - dest.width = kTrackInfoBtnSize; - dest.x = rect.x + rect.width - dest.width; -} - -void TrackInfo::GetSyncLockIconRect(const wxRect & rect, wxRect &dest) -{ - GetSyncLockHorizontalBounds( rect, dest ); - auto results = CalcBottomItemY - ( commonTrackTCPBottomLines, TCPLine::kItemSyncLock, rect.height); - dest.y = rect.y + results.first; - dest.height = results.second; -} - /// \todo Probably should move to 'Utils.cpp'. void TrackInfo::SetTrackInfoFont(wxDC * dc) { dc->SetFont(settings().gFont); } -//#define USE_BEVELS - -unsigned TrackInfo::DefaultTrackHeight( const TCPLines &topLines ) -{ - int needed = - kVerticalPadding + - totalTCPLines( topLines, true ) + - totalTCPLines( commonTrackTCPBottomLines, false ) + 1; - return (unsigned) std::max(needed, (int) ChannelView::DefaultHeight); -} diff --git a/src/TrackInfo.h b/src/TrackInfo.h index 05e02c1795e2..e7ca319860c5 100644 --- a/src/TrackInfo.h +++ b/src/TrackInfo.h @@ -17,22 +17,14 @@ Paul Licameli split from TrackPanel.cpp #include class wxDC; -class wxPoint; class wxRect; class wxWindow; - -class ButtonHandle; -class LWSlider; class Track; struct TrackPanelDrawingContext; - -static const int TitleSoloBorderOverlap = 1; +class UIHandle; namespace TrackInfo { - AUDACITY_DLL_API - unsigned MinimumTrackHeight(); - struct TCPLine { enum : unsigned { // The sequence is not significant, just keep bits distinct @@ -70,79 +62,8 @@ namespace TrackInfo AUDACITY_DLL_API std::pair< int, int > CalcItemY( const TCPLines &lines, unsigned iItem ); - AUDACITY_DLL_API - unsigned DefaultTrackHeight( const TCPLines &topLines ); - - AUDACITY_DLL_API - void DrawItems - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track &track ); - - AUDACITY_DLL_API - void DrawItems - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack, - const std::vector &topLines, - const std::vector &bottomLines ); - - AUDACITY_DLL_API - void DrawCloseButton( - TrackPanelDrawingContext &context, const wxRect &bev, - const Track *pTrack, ButtonHandle *target ); - - AUDACITY_DLL_API - void CloseTitleDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - AUDACITY_DLL_API - void MinimizeSyncLockDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - AUDACITY_DLL_API void SetTrackInfoFont(wxDC *dc); - - - AUDACITY_DLL_API - void GetCloseBoxHorizontalBounds( const wxRect & rect, wxRect &dest ); - AUDACITY_DLL_API - void GetCloseBoxRect(const wxRect & rect, wxRect &dest); - - AUDACITY_DLL_API - void GetTitleBarHorizontalBounds( const wxRect & rect, wxRect &dest ); - AUDACITY_DLL_API - void GetTitleBarRect(const wxRect & rect, wxRect &dest); - - AUDACITY_DLL_API - void GetSliderHorizontalBounds( const wxPoint &topleft, wxRect &dest ); - - AUDACITY_DLL_API - void GetMinimizeHorizontalBounds( const wxRect &rect, wxRect &dest ); - AUDACITY_DLL_API - void GetMinimizeRect(const wxRect & rect, wxRect &dest); - - AUDACITY_DLL_API - void GetSelectButtonHorizontalBounds( const wxRect &rect, wxRect &dest ); - AUDACITY_DLL_API - void GetSelectButtonRect(const wxRect & rect, wxRect &dest); - - AUDACITY_DLL_API - void GetSyncLockHorizontalBounds( const wxRect &rect, wxRect &dest ); - AUDACITY_DLL_API - void GetSyncLockIconRect(const wxRect & rect, wxRect &dest); - - AUDACITY_DLL_API - bool HideTopItem( const wxRect &rect, const wxRect &subRect, - int allowance = 0 ); - - // Non-member, namespace function relying on TrackPanel to invoke it - // when it handles preference update events - AUDACITY_DLL_API - void UpdatePrefs( wxWindow *pParent ); - - AUDACITY_DLL_API - bool HasSoloButton(); }; #endif diff --git a/src/TrackPanelResizeHandle.cpp b/src/TrackPanelResizeHandle.cpp index 3e8d7035ab97..d88c764abd2b 100644 --- a/src/TrackPanelResizeHandle.cpp +++ b/src/TrackPanelResizeHandle.cpp @@ -53,6 +53,16 @@ TrackPanelResizeHandle::~TrackPanelResizeHandle() { } +std::shared_ptr TrackPanelResizeHandle::FindChannel() const +{ + return mwChannel.lock(); +} + +std::shared_ptr TrackPanelResizeHandle::FindChannel() +{ + return mwChannel.lock(); +} + UIHandle::Result TrackPanelResizeHandle::Click( const TrackPanelMouseEvent &evt, AudacityProject *pProject ) { diff --git a/src/TrackPanelResizeHandle.h b/src/TrackPanelResizeHandle.h index e48a5d22efc4..bd72d8c2565a 100644 --- a/src/TrackPanelResizeHandle.h +++ b/src/TrackPanelResizeHandle.h @@ -33,7 +33,8 @@ class TrackPanelResizeHandle final : public UIHandle virtual ~TrackPanelResizeHandle(); - std::shared_ptr FindChannel() const { return mwChannel.lock(); } + std::shared_ptr FindChannel() const override; + std::shared_ptr FindChannel(); Result Click (const TrackPanelMouseEvent &event, AudacityProject *pProject) override; diff --git a/src/UIHandle.cpp b/src/UIHandle.cpp index 9c354af0a683..d4ac50939a23 100644 --- a/src/UIHandle.cpp +++ b/src/UIHandle.cpp @@ -54,3 +54,8 @@ bool UIHandle::StopsOnKeystroke() void UIHandle::OnProjectChange(AudacityProject *) { } + +bool UIHandle::IsDragging() const +{ + return false; +} diff --git a/src/UIHandle.h b/src/UIHandle.h index d2a0509838b1..7e83a9b24985 100644 --- a/src/UIHandle.h +++ b/src/UIHandle.h @@ -23,6 +23,7 @@ class wxWindow; class AudacityProject; struct HitTestPreview; +class Channel; class TrackPanelCell; struct TrackPanelMouseEvent; struct TrackPanelMouseState; @@ -118,6 +119,13 @@ class AUDACITY_DLL_API UIHandle /* not final */ : public TrackPanelDrawable // use? virtual void OnProjectChange(AudacityProject *pProject); + //! @return pointer to associated channel, if any + virtual std::shared_ptr FindChannel() const = 0; + + //! Whether the handle is dragging, affecting other panel painting; + //! default returns false + virtual bool IsDragging() const; + public: Result GetChangeHighlight() const { return mChangeHighlight; } void SetChangeHighlight(Result val) { mChangeHighlight = val; } diff --git a/src/menus/ViewMenus.cpp b/src/menus/ViewMenus.cpp index f406b6dd655d..d3600594436e 100644 --- a/src/menus/ViewMenus.cpp +++ b/src/menus/ViewMenus.cpp @@ -6,7 +6,7 @@ #include "ProjectHistory.h" #include "../ProjectSettings.h" #include "../ProjectWindow.h" -#include "../TrackInfo.h" +#include "../tracks/ui/CommonTrackInfo.h" #include "../TrackPanel.h" #include "UndoManager.h" #include "ViewInfo.h" @@ -150,7 +150,7 @@ void DoZoomFitV(AudacityProject &project) height = height / (int)count; // Use max() so that we don't set a negative height when there is // not enough room. - height = std::max( (int)TrackInfo::MinimumTrackHeight(), height ); + height = std::max( (int)CommonTrackInfo::MinimumTrackHeight(), height ); for (auto t : range) for (auto pChannel : t->Channels()) diff --git a/src/tracks/labeltrack/ui/LabelGlyphHandle.cpp b/src/tracks/labeltrack/ui/LabelGlyphHandle.cpp index deadc3d65916..4094e2e99de9 100644 --- a/src/tracks/labeltrack/ui/LabelGlyphHandle.cpp +++ b/src/tracks/labeltrack/ui/LabelGlyphHandle.cpp @@ -114,6 +114,11 @@ LabelGlyphHandle::~LabelGlyphHandle() { } +std::shared_ptr LabelGlyphHandle::FindChannel() const +{ + return mpLT; +} + void LabelGlyphHandle::HandleGlyphClick (LabelTrackHit &hit, const wxMouseEvent & evt, const wxRect & r, const ZoomInfo &zoomInfo, diff --git a/src/tracks/labeltrack/ui/LabelGlyphHandle.h b/src/tracks/labeltrack/ui/LabelGlyphHandle.h index 758d0b768bf3..5b54f2e5e6bf 100644 --- a/src/tracks/labeltrack/ui/LabelGlyphHandle.h +++ b/src/tracks/labeltrack/ui/LabelGlyphHandle.h @@ -64,6 +64,8 @@ class LabelGlyphHandle final : public LabelDefaultClickHandle virtual ~LabelGlyphHandle(); + std::shared_ptr FindChannel() const override; + void Enter(bool forward, AudacityProject *) override; Result Click diff --git a/src/tracks/labeltrack/ui/LabelTextHandle.cpp b/src/tracks/labeltrack/ui/LabelTextHandle.cpp index 6630257630ba..afba5f8e3c93 100644 --- a/src/tracks/labeltrack/ui/LabelTextHandle.cpp +++ b/src/tracks/labeltrack/ui/LabelTextHandle.cpp @@ -70,6 +70,11 @@ LabelTextHandle::~LabelTextHandle() { } +std::shared_ptr LabelTextHandle::FindChannel() const +{ + return mpLT.lock(); +} + void LabelTextHandle::HandleTextClick(AudacityProject &project, const wxMouseEvent & evt) { auto pTrack = mpLT.lock(); diff --git a/src/tracks/labeltrack/ui/LabelTextHandle.h b/src/tracks/labeltrack/ui/LabelTextHandle.h index 48af3a1a61d5..f457adb74389 100644 --- a/src/tracks/labeltrack/ui/LabelTextHandle.h +++ b/src/tracks/labeltrack/ui/LabelTextHandle.h @@ -34,7 +34,7 @@ class LabelTextHandle final : public LabelDefaultClickHandle ( const std::shared_ptr &pLT, int labelNum ); virtual ~LabelTextHandle(); - std::shared_ptr GetTrack() const { return mpLT.lock(); } + std::shared_ptr FindChannel() const override; int GetLabelNum() const { return mLabelNum; } void Enter(bool forward, AudacityProject *) override; diff --git a/src/tracks/labeltrack/ui/LabelTrackView.cpp b/src/tracks/labeltrack/ui/LabelTrackView.cpp index 8c7a4f7a8d5f..1963ddfc04f2 100644 --- a/src/tracks/labeltrack/ui/LabelTrackView.cpp +++ b/src/tracks/labeltrack/ui/LabelTrackView.cpp @@ -850,7 +850,9 @@ void LabelTrackView::Draw #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING bool highlightTrack = false; auto target = dynamic_cast(context.target.get()); - highlightTrack = target && target->GetTrack().get() == this; + highlightTrack = target && + target->FindChannel().get() == + static_cast(FindTrack().get()); #endif int i = -1; for (const auto &labelStruct : mLabels) { ++i; bool highlight = false; diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp index f83df48e6726..46bb44371a1d 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp @@ -19,7 +19,7 @@ Paul Licameli split from TrackPanel.cpp #include "../../../../NoteTrack.h" #include "ProjectHistory.h" #include "../../../../RefreshCode.h" -#include "../../../../TrackInfo.h" +#include "../../../ui/CommonTrackInfo.h" #include @@ -41,6 +41,11 @@ NoteTrackButtonHandle::~NoteTrackButtonHandle() { } +std::shared_ptr NoteTrackButtonHandle::FindChannel() const +{ + return mpTrack.lock(); +} + UIHandle::Result NoteTrackButtonHandle::NeedChangeHighlight (const NoteTrackButtonHandle &oldState, const NoteTrackButtonHandle &newState) { @@ -57,7 +62,7 @@ UIHandlePtr NoteTrackButtonHandle::HitTest { wxRect midiRect; NoteTrackControls::GetMidiControlsRect(rect, midiRect); - if ( TrackInfo::HideTopItem( rect, midiRect ) ) + if ( CommonTrackInfo::HideTopItem( rect, midiRect ) ) return {}; if (midiRect.Contains(state.m_x, state.m_y)) { auto channel = pTrack->FindChannel(midiRect, state.m_x, state.m_y); diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.h b/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.h index c92a4ae3345b..343a20600508 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.h +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.h @@ -39,6 +39,7 @@ class NoteTrackButtonHandle : public UIHandle const std::shared_ptr &pTrack); std::shared_ptr GetTrack() const { return mpTrack.lock(); } + std::shared_ptr FindChannel() const override; int GetChannel() const { return mChannel; } static UIHandle::Result NeedChangeHighlight diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp index e4748acd4a5b..88bafedf7d7a 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp @@ -11,28 +11,19 @@ Paul Licameli split from TrackPanel.cpp #ifdef USE_MIDI #include "NoteTrackControls.h" - -#include "NoteTrackButtonHandle.h" -#include "Observer.h" -#include "Theme.h" - #include "../../ui/PlayableTrackButtonHandles.h" +#include "NoteTrackButtonHandle.h" #include "NoteTrackSliderHandles.h" - -#include "../../../../HitTestResult.h" #include "../../../../TrackArtist.h" #include "../../../../TrackPanel.h" +#include "../../../ui/CommonTrackInfo.h" #include "../../../../TrackPanelMouseEvent.h" #include "../../../../NoteTrack.h" #include "../../../../widgets/PopupMenuTable.h" -#include "Project.h" #include "ProjectHistory.h" #include "../../../../ProjectWindows.h" #include "../../../../RefreshCode.h" -#include "../../../../prefs/ThemePrefs.h" - -#include -#include +#include "Theme.h" #include /////////////////////////////////////////////////////////////////////////////// @@ -145,7 +136,6 @@ PopupMenuTable *NoteTrackControls::GetMenuExtension(Track *) // drawing related #include "../../../../widgets/ASlider.h" -#include "../../../../TrackInfo.h" #include "../../../../TrackPanelDrawingContext.h" #include "ViewInfo.h" @@ -180,7 +170,7 @@ void SliderDrawFunction bool captured, bool highlight ) { wxRect sliderRect = rect; - TrackInfo::GetSliderHorizontalBounds( rect.GetTopLeft(), sliderRect ); + CommonTrackInfo::GetSliderHorizontalBounds( rect.GetTopLeft(), sliderRect ); auto nt = static_cast( pTrack ); Selector( sliderRect, nt, captured, pParent )->OnPaint(*dc, highlight); } @@ -193,7 +183,7 @@ void VelocitySliderDrawFunction auto dc = &context.dc; auto target = dynamic_cast( context.target.get() ); bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); + bool captured = hit && target->IsDragging(); const auto artist = TrackArtist::Get( context ); auto pParent = FindProjectFrame( artist->parent->GetProject() ); @@ -235,7 +225,7 @@ static const struct NoteTrackTCPLines void NoteTrackControls::GetVelocityRect(const wxPoint &topleft, wxRect & dest) { - TrackInfo::GetSliderHorizontalBounds( topleft, dest ); + CommonTrackInfo::GetSliderHorizontalBounds( topleft, dest ); auto results = CalcItemY( noteTrackTCPLines, TCPLine::kItemVelocity ); dest.y = topleft.y + results.first; dest.height = results.second; @@ -252,7 +242,7 @@ void NoteTrackControls::GetMidiControlsRect(const wxRect & rect, wxRect & dest) unsigned NoteTrackControls::DefaultNoteTrackHeight() { - return TrackInfo::DefaultTrackHeight( noteTrackTCPLines ); + return CommonTrackInfo::DefaultTrackHeight( noteTrackTCPLines ); } const TCPLines &NoteTrackControls::GetTCPLines() const diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp index 39d650e642cc..ba80bc1b1fd1 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp @@ -7,8 +7,6 @@ Paul Licameli split from TrackPanel.cpp **********************************************************************/ - - #include "NoteTrackSliderHandles.h" #ifdef EXPERIMENTAL_MIDI_OUT @@ -16,9 +14,8 @@ #include "NoteTrackControls.h" #include "ProjectHistory.h" #include "../../../../RefreshCode.h" -#include "../../../../TrackInfo.h" +#include "../../../ui/CommonTrackInfo.h" #include "../../../../TrackPanel.h" -#include "TrackFocus.h" #include "UndoManager.h" #include "../../../../NoteTrack.h" #include "ViewInfo.h" @@ -102,7 +99,7 @@ UIHandlePtr VelocitySliderHandle::HitTest wxRect sliderRect; NoteTrackControls::GetVelocityRect(rect.GetTopLeft(), sliderRect); - if ( TrackInfo::HideTopItem( rect, sliderRect, kTrackInfoSliderAllowance ) ) + if (CommonTrackInfo::HideTopItem( rect, sliderRect, kTrackInfoSliderAllowance)) return {}; if (sliderRect.Contains(state.m_x, state.m_y)) { auto sliderFn = diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp index 978ddc455e89..e700a1c84a34 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp @@ -103,6 +103,11 @@ NoteTrackVZoomHandle::~NoteTrackVZoomHandle() { } +std::shared_ptr NoteTrackVZoomHandle::FindChannel() const +{ + return mpTrack.lock(); +} + bool NoteTrackVZoomHandle::HandlesRightClick() { return true; diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.h b/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.h index 7aa188ea8b28..d29a54065327 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.h +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.h @@ -34,7 +34,7 @@ class NoteTrackVZoomHandle : public UIHandle virtual ~NoteTrackVZoomHandle(); - std::shared_ptr GetTrack() const { return mpTrack.lock(); } + std::shared_ptr FindChannel() const override; void Enter(bool forward, AudacityProject *) override; diff --git a/src/tracks/playabletrack/notetrack/ui/StretchHandle.cpp b/src/tracks/playabletrack/notetrack/ui/StretchHandle.cpp index 8a6f670fbd04..1d8361e92767 100644 --- a/src/tracks/playabletrack/notetrack/ui/StretchHandle.cpp +++ b/src/tracks/playabletrack/notetrack/ui/StretchHandle.cpp @@ -156,6 +156,11 @@ StretchHandle::~StretchHandle() { } +std::shared_ptr StretchHandle::FindChannel() const +{ + return mpTrack; +} + UIHandle::Result StretchHandle::Click (const TrackPanelMouseEvent &evt, AudacityProject *pProject) { diff --git a/src/tracks/playabletrack/notetrack/ui/StretchHandle.h b/src/tracks/playabletrack/notetrack/ui/StretchHandle.h index f022b079cf4b..338e41f79f9d 100644 --- a/src/tracks/playabletrack/notetrack/ui/StretchHandle.h +++ b/src/tracks/playabletrack/notetrack/ui/StretchHandle.h @@ -68,6 +68,8 @@ class StretchHandle : public UIHandle virtual ~StretchHandle(); + std::shared_ptr FindChannel() const override; + Result Click (const TrackPanelMouseEvent &event, AudacityProject *pProject) override; diff --git a/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp b/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp index f544dc52b15c..d89cdf5a4ac9 100644 --- a/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp +++ b/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp @@ -16,7 +16,7 @@ Paul Licameli split from TrackPanel.cpp #include "../../../RealtimeEffectPanel.h" #include "SampleTrack.h" #include "TrackFocus.h" -#include "../../../TrackInfo.h" +#include "../../ui/CommonTrackInfo.h" #include "../../../TrackPanelMouseEvent.h" #include "../../../TrackUtilities.h" @@ -64,7 +64,7 @@ UIHandlePtr MuteButtonHandle::HitTest if ( pTrack ) PlayableTrackControls::GetMuteSoloRect(rect, buttonRect, false, (TracksBehaviorsSolo.ReadEnum() != SoloBehaviorNone), pTrack.get()); - if ( TrackInfo::HideTopItem( rect, buttonRect ) ) + if ( CommonTrackInfo::HideTopItem( rect, buttonRect ) ) return {}; if ( pTrack && buttonRect.Contains(state.m_x, state.m_y) ) { @@ -121,7 +121,7 @@ UIHandlePtr SoloButtonHandle::HitTest PlayableTrackControls::GetMuteSoloRect(rect, buttonRect, true, (TracksBehaviorsSolo.ReadEnum() != SoloBehaviorNone), pTrack.get()); - if ( TrackInfo::HideTopItem( rect, buttonRect ) ) + if ( CommonTrackInfo::HideTopItem( rect, buttonRect ) ) return {}; if ( pTrack && buttonRect.Contains(state.m_x, state.m_y) ) { @@ -181,7 +181,7 @@ UIHandlePtr EffectsButtonHandle::HitTest PlayableTrackControls::GetEffectsRect(rect, buttonRect, pTrack.get()); - if ( TrackInfo::HideTopItem( rect, buttonRect ) ) + if ( CommonTrackInfo::HideTopItem( rect, buttonRect ) ) return {}; if ( pTrack && buttonRect.Contains(state.m_x, state.m_y) ) { diff --git a/src/tracks/playabletrack/ui/PlayableTrackControls.cpp b/src/tracks/playabletrack/ui/PlayableTrackControls.cpp index 84ee920786aa..f05f143e9090 100644 --- a/src/tracks/playabletrack/ui/PlayableTrackControls.cpp +++ b/src/tracks/playabletrack/ui/PlayableTrackControls.cpp @@ -11,9 +11,10 @@ Paul Licameli split from TrackInfo.cpp #include "PlayableTrack.h" #include "PlayableTrackButtonHandles.h" #include "AColor.h" -#include "../../../TrackInfo.h" +#include "../../ui/CommonTrackInfo.h" #include "../../../TrackPanelDrawingContext.h" #include "ViewInfo.h" +#include "prefs/TracksBehaviorsPrefs.h" #include "RealtimeEffectManager.h" #include @@ -132,7 +133,7 @@ void WideMuteDrawFunction GetWideMuteSoloHorizontalBounds( rect, bev ); auto target = dynamic_cast( context.target.get() ); bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); + bool captured = hit && target->IsDragging(); bool down = captured && bev.Contains( context.lastState.GetPosition()); MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, false, hit ); } @@ -146,7 +147,7 @@ void WideSoloDrawFunction GetWideMuteSoloHorizontalBounds( rect, bev ); auto target = dynamic_cast( context.target.get() ); bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); + bool captured = hit && target->IsDragging(); bool down = captured && bev.Contains( context.lastState.GetPosition()); MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, true, hit ); } @@ -156,7 +157,7 @@ void MuteAndSoloDrawFunction const wxRect &rect, const Track *pTrack ) { auto dc = &context.dc; - bool bHasSoloButton = TrackInfo::HasSoloButton(); + bool bHasSoloButton = (TracksBehaviorsSolo.ReadEnum() != SoloBehaviorNone); wxRect bev = rect; if ( bHasSoloButton ) @@ -166,7 +167,7 @@ void MuteAndSoloDrawFunction { auto target = dynamic_cast( context.target.get() ); bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); + bool captured = hit && target->IsDragging(); bool down = captured && bev.Contains( context.lastState.GetPosition()); MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, false, hit ); } @@ -178,7 +179,7 @@ void MuteAndSoloDrawFunction { auto target = dynamic_cast( context.target.get() ); bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); + bool captured = hit && target->IsDragging(); bool down = captured && bev.Contains( context.lastState.GetPosition()); MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, true, hit ); } @@ -196,7 +197,7 @@ void EffectsDrawFunction { auto target = dynamic_cast( context.target.get() ); bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); + bool captured = hit && target->IsDragging(); bool down = captured && bev.Contains( context.lastState.GetPosition()); EffectsDrawFunction( dc, bev, pTrack, down, captured, hit ); } @@ -254,7 +255,7 @@ const TCPLines& PlayableTrackControls::StaticNoteTCPLines() static TCPLines playableTrackTCPLines; static std::once_flag flag; std::call_once( flag, []{ - playableTrackTCPLines = CommonTrackControls::StaticTCPLines(); + playableTrackTCPLines = CommonTrackInfo::StaticTCPLines(); playableTrackTCPLines.insert( playableTrackTCPLines.end(), { { TCPLine::kItemMute | TCPLine::kItemSolo, kTrackInfoBtnSize + 1, 0, MuteAndSoloDrawFunction }, @@ -268,7 +269,7 @@ const TCPLines& PlayableTrackControls::StaticWaveTCPLines() static TCPLines playableTrackTCPLines; static std::once_flag flag; std::call_once( flag, []{ - playableTrackTCPLines = CommonTrackControls::StaticTCPLines(); + playableTrackTCPLines = CommonTrackInfo::StaticTCPLines(); playableTrackTCPLines.insert( playableTrackTCPLines.end(), { { TCPLine::kItemMute | TCPLine::kItemSolo, kTrackInfoBtnSize + 1, 0, MuteAndSoloDrawFunction }, diff --git a/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.cpp b/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.cpp index 0d9305440032..bb85013226d1 100644 --- a/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.cpp @@ -112,6 +112,11 @@ CutlineHandle::~CutlineHandle() { } +std::shared_ptr CutlineHandle::FindChannel() const +{ + return mpTrack; +} + bool CutlineHandle::HandlesRightClick() { return true; diff --git a/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.h b/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.h index 13de2e0f66b6..d014aa540110 100644 --- a/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.h +++ b/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.h @@ -39,6 +39,8 @@ class CutlineHandle final : public UIHandle virtual ~CutlineHandle(); + std::shared_ptr FindChannel() const override; + const WaveTrackLocation &GetLocation() { return mLocation; } std::shared_ptr GetTrack() { return mpTrack; } diff --git a/src/tracks/playabletrack/wavetrack/ui/SampleHandle.cpp b/src/tracks/playabletrack/wavetrack/ui/SampleHandle.cpp index 224cb5233de1..baf1d6172924 100644 --- a/src/tracks/playabletrack/wavetrack/ui/SampleHandle.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/SampleHandle.cpp @@ -174,6 +174,11 @@ SampleHandle::~SampleHandle() { } +std::shared_ptr SampleHandle::FindChannel() const +{ + return mClickedTrack; +} + UIHandle::Result SampleHandle::Click (const TrackPanelMouseEvent &evt, AudacityProject *pProject) { diff --git a/src/tracks/playabletrack/wavetrack/ui/SampleHandle.h b/src/tracks/playabletrack/wavetrack/ui/SampleHandle.h index 42323e942e8e..e72bbc2f7ac8 100644 --- a/src/tracks/playabletrack/wavetrack/ui/SampleHandle.h +++ b/src/tracks/playabletrack/wavetrack/ui/SampleHandle.h @@ -43,7 +43,7 @@ class SampleHandle final : public UIHandle virtual ~SampleHandle(); - std::shared_ptr GetTrack() const { return mClickedTrack; } + std::shared_ptr FindChannel() const override; void Enter(bool forward, AudacityProject *) override; diff --git a/src/tracks/playabletrack/wavetrack/ui/SpectrumVZoomHandle.cpp b/src/tracks/playabletrack/wavetrack/ui/SpectrumVZoomHandle.cpp index a2f6acf86153..654db1e066bf 100644 --- a/src/tracks/playabletrack/wavetrack/ui/SpectrumVZoomHandle.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/SpectrumVZoomHandle.cpp @@ -30,6 +30,11 @@ SpectrumVZoomHandle::SpectrumVZoomHandle SpectrumVZoomHandle::~SpectrumVZoomHandle() = default; +std::shared_ptr SpectrumVZoomHandle::FindChannel() const +{ + return mpTrack.lock(); +} + void SpectrumVZoomHandle::Enter( bool, AudacityProject* ) { #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING diff --git a/src/tracks/playabletrack/wavetrack/ui/SpectrumVZoomHandle.h b/src/tracks/playabletrack/wavetrack/ui/SpectrumVZoomHandle.h index 3139772e6d5e..006e44205c38 100644 --- a/src/tracks/playabletrack/wavetrack/ui/SpectrumVZoomHandle.h +++ b/src/tracks/playabletrack/wavetrack/ui/SpectrumVZoomHandle.h @@ -34,7 +34,7 @@ class SpectrumVZoomHandle final : public UIHandle ~SpectrumVZoomHandle() override; - std::shared_ptr GetTrack() const { return mpTrack.lock(); } + std::shared_ptr FindChannel() const override; void Enter(bool forward, AudacityProject*) override; diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveChannelView.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveChannelView.cpp index 7ae05a378581..0a50018c0a2f 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveChannelView.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveChannelView.cpp @@ -41,7 +41,7 @@ Paul Licameli split from TrackPanel.cpp #include "../../../ui/TimeShiftHandle.h" #include "../../../ui/ButtonHandle.h" -#include "../../../../TrackInfo.h" +#include "../../../ui/CommonTrackInfo.h" #include "../WaveTrackUtils.h" @@ -306,6 +306,14 @@ class SubViewAdjustHandle : public UIHandle --mMySubView; } + std::shared_ptr FindChannel() const override + { + auto pView = mAdjuster.mwView.lock(); + if (pView) + return pView->FindChannel(); + return nullptr; + } + Result Click( const TrackPanelMouseEvent &event, AudacityProject *pProject ) override { @@ -532,6 +540,14 @@ class SubViewRearrangeHandle : public UIHandle { } + std::shared_ptr FindChannel() const override + { + auto pView = mAdjuster.mwView.lock(); + if (pView) + return pView->FindChannel(); + return nullptr; + } + Result Click( const TrackPanelMouseEvent &event, AudacityProject *pProject ) override { @@ -729,7 +745,7 @@ class SubViewCloseHandle : public ButtonHandle override { if ( iPass == TrackArtist::PassMargins ) { // after PassTracks - TrackInfo::DrawCloseButton( + CommonTrackInfo::DrawCloseButton( context, GetButtonRect(rect), GetTrack().get(), this ); } } diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveClipAdjustBorderHandle.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveClipAdjustBorderHandle.cpp index 40616b93603a..b896d125d7ad 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveClipAdjustBorderHandle.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveClipAdjustBorderHandle.cpp @@ -62,6 +62,8 @@ namespace { virtual void Finish(AudacityProject& project) = 0; virtual void Cancel() = 0; + virtual std::shared_ptr FindTrack() const = 0; + virtual void Draw( TrackPanelDrawingContext &context, const wxRect &rect, @@ -207,6 +209,11 @@ class AdjustClipBorder final : public WaveClipAdjustBorderHandle::AdjustPolicy } } + std::shared_ptr FindTrack() const override + { + return mTrack; + } + bool Init(const TrackPanelMouseEvent& event) override { if (event.event.LeftDown()) @@ -336,10 +343,13 @@ HitTestPreview WaveClipAdjustBorderHandle::HitPreviewStretch(const AudacityProje }; } -WaveClipAdjustBorderHandle::WaveClipAdjustBorderHandle(std::unique_ptr& adjustPolicy, - bool stretchMode, - bool leftBorder) +WaveClipAdjustBorderHandle::WaveClipAdjustBorderHandle( + std::unique_ptr& adjustPolicy, + std::shared_ptr pTrack, + bool stretchMode, + bool leftBorder) : mAdjustPolicy{ std::move(adjustPolicy) } + , mpTrack{ move(pTrack) } , mIsStretchMode{stretchMode} , mIsLeftBorder{leftBorder} { @@ -348,6 +358,11 @@ WaveClipAdjustBorderHandle::WaveClipAdjustBorderHandle(std::unique_ptr WaveClipAdjustBorderHandle::FindChannel() const +{ + return mpTrack; +} + WaveClipAdjustBorderHandle::WaveClipAdjustBorderHandle(WaveClipAdjustBorderHandle&&) noexcept = default; WaveClipAdjustBorderHandle& WaveClipAdjustBorderHandle::operator=(WaveClipAdjustBorderHandle&&) noexcept = default; @@ -440,7 +455,7 @@ UIHandlePtr WaveClipAdjustBorderHandle::HitAnywhere( return AssignUIHandlePtr( holder, - std::make_shared(policy, + std::make_shared(policy, waveTrack, isStretchMode, adjustLeftBorder)); } diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveClipAdjustBorderHandle.h b/src/tracks/playabletrack/wavetrack/ui/WaveClipAdjustBorderHandle.h index 7aa6bc25fb8d..1ada6014c0ab 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveClipAdjustBorderHandle.h +++ b/src/tracks/playabletrack/wavetrack/ui/WaveClipAdjustBorderHandle.h @@ -28,13 +28,18 @@ class WaveClipAdjustBorderHandle final : public UIHandle static HitTestPreview HitPreviewStretch(const AudacityProject*, bool unsafe, bool isLeftBorder); std::unique_ptr mAdjustPolicy{}; + std::shared_ptr mpTrack; bool mIsStretchMode; bool mIsLeftBorder; public: - WaveClipAdjustBorderHandle(std::unique_ptr& adjustPolicy, bool stretchMode, bool leftBorder); + WaveClipAdjustBorderHandle(std::unique_ptr& adjustPolicy, + std::shared_ptr pTrack, + bool stretchMode, bool leftBorder); ~WaveClipAdjustBorderHandle() override; + std::shared_ptr FindChannel() const override; + WaveClipAdjustBorderHandle(WaveClipAdjustBorderHandle&&) noexcept; WaveClipAdjustBorderHandle& operator = (WaveClipAdjustBorderHandle&&) noexcept; diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackAffordanceControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackAffordanceControls.cpp index 4bc1a307d02c..651d0856e0ab 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackAffordanceControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackAffordanceControls.cpp @@ -87,16 +87,24 @@ const ComponentInterfaceSymbol SetWaveClipNameCommand::Symbol class WaveClipTitleEditHandle final : public UIHandle { std::shared_ptr mHelper; + std::shared_ptr mpTrack; public: - WaveClipTitleEditHandle(const std::shared_ptr& helper) + WaveClipTitleEditHandle(const std::shared_ptr& helper, + const std::shared_ptr pTrack) : mHelper(helper) + , mpTrack{ move(pTrack) } { } ~WaveClipTitleEditHandle() { } + std::shared_ptr FindChannel() const override + { + return mpTrack; + } + Result Click(const TrackPanelMouseEvent& event, AudacityProject* project) override { if (mHelper->OnClick(event.event, project)) @@ -187,7 +195,8 @@ std::vector WaveTrackAffordanceControls::HitTest(const TrackPanelMo results.push_back( AssignUIHandlePtr( mTitleEditHandle, - std::make_shared(mTextEditHelper) + std::make_shared( + mTextEditHelper, track) ) ); } diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp index 3c6748dfa2ef..b7eb5e0a3fb5 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp @@ -967,7 +967,7 @@ WaveTrackPopupMenuTable &GetWaveTrackMenuTable() // drawing related #include "../../../../widgets/ASlider.h" -#include "../../../../TrackInfo.h" +#include "../../../ui/CommonTrackInfo.h" #include "../../../../TrackPanelDrawingContext.h" #include "ViewInfo.h" @@ -981,7 +981,7 @@ void SliderDrawFunction bool captured, bool highlight ) { wxRect sliderRect = rect; - TrackInfo::GetSliderHorizontalBounds( rect.GetTopLeft(), sliderRect ); + CommonTrackInfo::GetSliderHorizontalBounds( rect.GetTopLeft(), sliderRect ); auto wt = static_cast( pTrack ); Selector( sliderRect, wt, captured, pParent )->OnPaint(*dc, highlight); } @@ -993,7 +993,7 @@ void PanSliderDrawFunction auto target = dynamic_cast( context.target.get() ); auto dc = &context.dc; bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); + bool captured = hit && target->IsDragging(); const auto artist = TrackArtist::Get( context ); auto pParent = FindProjectFrame( artist->parent->GetProject() ); @@ -1012,7 +1012,7 @@ void GainSliderDrawFunction bool hit = target && target->GetTrack().get() == pTrack; if( hit ) hit=hit; - bool captured = hit && target->IsClicked(); + bool captured = hit && target->IsDragging(); const auto artist = TrackArtist::Get( context ); auto pParent = FindProjectFrame( artist->parent->GetProject() ); @@ -1092,7 +1092,7 @@ static const struct WaveTrackTCPLines void WaveTrackControls::GetGainRect(const wxPoint &topleft, wxRect & dest) { - TrackInfo::GetSliderHorizontalBounds( topleft, dest ); + CommonTrackInfo::GetSliderHorizontalBounds( topleft, dest ); auto results = CalcItemY( waveTrackTCPLines, TCPLine::kItemGain ); dest.y = topleft.y + results.first; dest.height = results.second; @@ -1107,7 +1107,7 @@ void WaveTrackControls::GetPanRect(const wxPoint &topleft, wxRect & dest) unsigned WaveTrackControls::DefaultWaveTrackHeight() { - return TrackInfo::DefaultTrackHeight( waveTrackTCPLines ); + return CommonTrackInfo::DefaultTrackHeight( waveTrackTCPLines ); } const TCPLines &WaveTrackControls::GetTCPLines() const diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp index be6fd59c2bbb..af8bfaa1927d 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp @@ -14,7 +14,7 @@ Paul Licameli split from TrackPanel.cpp #include "WaveTrackControls.h" #include "ProjectHistory.h" #include "../../../../RefreshCode.h" -#include "../../../../TrackInfo.h" +#include "../../../ui/CommonTrackInfo.h" #include "../../../../TrackPanel.h" #include "TrackFocus.h" #include "UndoManager.h" @@ -92,7 +92,7 @@ UIHandlePtr GainSliderHandle::HitTest wxRect sliderRect; WaveTrackControls::GetGainRect(rect.GetTopLeft(), sliderRect); - if ( TrackInfo::HideTopItem( rect, sliderRect)) + if ( CommonTrackInfo::HideTopItem( rect, sliderRect)) return {}; if (sliderRect.Contains(state.m_x, state.m_y)) { wxRect sliderRect2; @@ -200,7 +200,7 @@ UIHandlePtr PanSliderHandle::HitTest wxRect sliderRect; WaveTrackControls::GetPanRect(rect.GetTopLeft(), sliderRect); - if ( TrackInfo::HideTopItem( rect, sliderRect)) + if ( CommonTrackInfo::HideTopItem( rect, sliderRect)) return {}; if (sliderRect.Contains(state.m_x, state.m_y)) { auto sliderFn = diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveformVZoomHandle.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveformVZoomHandle.cpp index 96eeda365a36..b7529c168285 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveformVZoomHandle.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveformVZoomHandle.cpp @@ -30,6 +30,11 @@ WaveformVZoomHandle::WaveformVZoomHandle( WaveformVZoomHandle::~WaveformVZoomHandle() = default; +std::shared_ptr WaveformVZoomHandle::FindChannel() const +{ + return std::dynamic_pointer_cast(mpTrack.lock()); +} + void WaveformVZoomHandle::Enter( bool, AudacityProject* ) { #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveformVZoomHandle.h b/src/tracks/playabletrack/wavetrack/ui/WaveformVZoomHandle.h index 9ddfc5bbc13c..266b29055d8f 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveformVZoomHandle.h +++ b/src/tracks/playabletrack/wavetrack/ui/WaveformVZoomHandle.h @@ -34,7 +34,7 @@ class WaveformVZoomHandle final : public UIHandle ~WaveformVZoomHandle() override; - std::shared_ptr GetTrack() const { return mpTrack.lock(); } + std::shared_ptr FindChannel() const override; void Enter( bool forward, AudacityProject * ) override; diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveformView.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveformView.cpp index 8f2e872ecf6a..b387ace6e93f 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveformView.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveformView.cpp @@ -93,7 +93,9 @@ std::vector WaveformView::DetailedHitTest( viewInfo.PositionToTime(st.state.m_x, st.rect.GetX()); auto envelope = pTrack->GetEnvelopeAtTime(time); result = EnvelopeHandle::HitAnywhere( - view.mEnvelopeHandle, envelope, false); + view.mEnvelopeHandle, envelope, + std::dynamic_pointer_cast(pTrack), + false); break; } case ToolCodes::drawTool: @@ -654,7 +656,7 @@ void DrawClipWaveform(TrackPanelDrawingContext &context, bool highlightEnvelope = false; #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING auto target = dynamic_cast(context.target.get()); - highlightEnvelope = target && target->GetEnvelope() == clip.GetEnvelope(); + highlightEnvelope = target && target->GetEnvelope() == &envelope; #endif //If clip is "too small" draw a placeholder instead of @@ -848,7 +850,7 @@ void DrawClipWaveform(TrackPanelDrawingContext &context, bool highlight = false; #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING auto target = dynamic_cast(context.target.get()); - highlight = target && target->GetTrack().get() == track; + highlight = target && target->FindChannel().get() == &track; #endif DrawIndividualSamples( context, leftOffset, rectPortion, zoomMin, zoomMax, @@ -955,7 +957,7 @@ void WaveformView::DoDraw(TrackPanelDrawingContext &context, size_t channel, #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING auto target = dynamic_cast(context.target.get()); gripHit = target && target->IsGripHit(); - highlight = target && target->GetTrack().get() == track; + highlight = target && target->GetTrack().get() == &track; #endif const bool dB = !WaveformSettings::Get(track).isLinear(); diff --git a/src/tracks/timetrack/ui/TimeTrackVZoomHandle.cpp b/src/tracks/timetrack/ui/TimeTrackVZoomHandle.cpp index 1dafeb6bb61d..a091e8dce298 100644 --- a/src/tracks/timetrack/ui/TimeTrackVZoomHandle.cpp +++ b/src/tracks/timetrack/ui/TimeTrackVZoomHandle.cpp @@ -28,6 +28,11 @@ TimeTrackVZoomHandle::TimeTrackVZoomHandle( TimeTrackVZoomHandle::~TimeTrackVZoomHandle() = default; +std::shared_ptr TimeTrackVZoomHandle::FindChannel() const +{ + return std::dynamic_pointer_cast(mpTrack.lock()); +} + void TimeTrackVZoomHandle::Enter( bool, AudacityProject* ) { #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING diff --git a/src/tracks/timetrack/ui/TimeTrackVZoomHandle.h b/src/tracks/timetrack/ui/TimeTrackVZoomHandle.h index ada90f4f332b..1700b2ff9f3f 100644 --- a/src/tracks/timetrack/ui/TimeTrackVZoomHandle.h +++ b/src/tracks/timetrack/ui/TimeTrackVZoomHandle.h @@ -27,6 +27,8 @@ class TimeTrackVZoomHandle final : public UIHandle ~TimeTrackVZoomHandle() override; + std::shared_ptr FindChannel() const override; + void Enter( bool forward, AudacityProject * ) override; bool HandlesRightClick() override; diff --git a/src/tracks/timetrack/ui/TimeTrackView.cpp b/src/tracks/timetrack/ui/TimeTrackView.cpp index 97ff143bc000..5e11dec7ddac 100644 --- a/src/tracks/timetrack/ui/TimeTrackView.cpp +++ b/src/tracks/timetrack/ui/TimeTrackView.cpp @@ -81,7 +81,7 @@ void DrawHorzRulerAndCurve bool highlight = false; #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING auto target = dynamic_cast(context.target.get()); - highlight = target && target->GetEnvelope() == this->GetEnvelope(); + highlight = target && target->GetEnvelope() == track.GetEnvelope(); #endif double min = zoomInfo.PositionToTime(0); diff --git a/src/tracks/ui/BackgroundCell.cpp b/src/tracks/ui/BackgroundCell.cpp index e4a573ebc0ad..2cc796b1f420 100644 --- a/src/tracks/ui/BackgroundCell.cpp +++ b/src/tracks/ui/BackgroundCell.cpp @@ -49,6 +49,9 @@ class BackgroundHandle : public UIHandle virtual ~BackgroundHandle() {} + std::shared_ptr FindChannel() const override + { return nullptr; } + Result Click (const TrackPanelMouseEvent &evt, AudacityProject *pProject) override { diff --git a/src/tracks/ui/BrushHandle.cpp b/src/tracks/ui/BrushHandle.cpp index bd4c9039659e..7170f2a2cd09 100644 --- a/src/tracks/ui/BrushHandle.cpp +++ b/src/tracks/ui/BrushHandle.cpp @@ -54,7 +54,7 @@ enum { // #define SPECTRAL_EDITING_ESC_KEY -bool BrushHandle::IsClicked() const +bool BrushHandle::IsDragging() const { return mSelectionStateChanger.get() != NULL; } @@ -172,6 +172,11 @@ BrushHandle::~BrushHandle() { } +std::shared_ptr BrushHandle::FindChannel() const +{ + return std::dynamic_pointer_cast(FindTrack().lock()); +} + namespace { // Is the distance between A and B less than D? template < class A, class B, class DIST > bool within(A a, B b, DIST d) @@ -430,4 +435,9 @@ std::weak_ptr BrushHandle::FindTrack() return pView->FindTrack(); } +std::weak_ptr BrushHandle::FindTrack() const +{ + return const_cast(*this).FindTrack(); +} + BrushHandle::StateSaver::~StateSaver() = default; diff --git a/src/tracks/ui/BrushHandle.h b/src/tracks/ui/BrushHandle.h index 326d81e422da..a9dda8e9fabd 100644 --- a/src/tracks/ui/BrushHandle.h +++ b/src/tracks/ui/BrushHandle.h @@ -60,7 +60,9 @@ class AUDACITY_DLL_API BrushHandle : public UIHandle virtual ~BrushHandle(); - bool IsClicked() const; + std::shared_ptr FindChannel() const override; + + bool IsDragging() const override; void Enter(bool forward, AudacityProject *pProject) override; @@ -89,6 +91,7 @@ class AUDACITY_DLL_API BrushHandle : public UIHandle std::shared_ptr mpSpectralData; std::weak_ptr FindTrack(); + std::weak_ptr FindTrack() const; // TrackPanelDrawable implementation void Draw( diff --git a/src/tracks/ui/ButtonHandle.cpp b/src/tracks/ui/ButtonHandle.cpp index 64bc14881dbc..0a4a50ef8cd1 100644 --- a/src/tracks/ui/ButtonHandle.cpp +++ b/src/tracks/ui/ButtonHandle.cpp @@ -29,6 +29,16 @@ ButtonHandle::~ButtonHandle() { } +std::shared_ptr ButtonHandle::FindChannel() const +{ + return std::dynamic_pointer_cast(mpTrack.lock()); +} + +bool ButtonHandle::IsDragging() const +{ + return mIsDragging; +} + void ButtonHandle::Enter(bool, AudacityProject *) { mChangeHighlight = RefreshCode::RefreshCell; @@ -49,7 +59,7 @@ UIHandle::Result ButtonHandle::Click // Come here for left click or double click if (mRect.Contains(event.m_x, event.m_y)) { mWasIn = true; - mIsClicked = true; + mIsDragging = true; // Toggle visible button state return RefreshCell; } diff --git a/src/tracks/ui/ButtonHandle.h b/src/tracks/ui/ButtonHandle.h index e3893acf9efc..4058eb5e0142 100644 --- a/src/tracks/ui/ButtonHandle.h +++ b/src/tracks/ui/ButtonHandle.h @@ -28,7 +28,7 @@ class AUDACITY_DLL_API ButtonHandle /* not final */ : public UIHandle public: std::shared_ptr GetTrack() const { return mpTrack.lock(); } - bool IsClicked() const { return mIsClicked; } + bool IsDragging() const override; protected: explicit ButtonHandle @@ -38,6 +38,8 @@ class AUDACITY_DLL_API ButtonHandle /* not final */ : public UIHandle virtual ~ButtonHandle(); + std::shared_ptr FindChannel() const override; + // This NEW abstract virtual simplifies the duties of further subclasses. // This class will decide whether to refresh the clicked cell for button state // change. @@ -72,7 +74,7 @@ class AUDACITY_DLL_API ButtonHandle /* not final */ : public UIHandle std::weak_ptr mpTrack; wxRect mRect; bool mWasIn{ true }; - bool mIsClicked{}; + bool mIsDragging{}; }; #endif diff --git a/src/tracks/ui/CommonChannelView.cpp b/src/tracks/ui/CommonChannelView.cpp index 577613c8d429..7f1ee6d370d2 100644 --- a/src/tracks/ui/CommonChannelView.cpp +++ b/src/tracks/ui/CommonChannelView.cpp @@ -11,6 +11,7 @@ Paul Licameli split from class TrackView (now called ChannelView) #include "CommonChannelView.h" #include "BackgroundCell.h" +#include "CommonTrackInfo.h" #include "TimeShiftHandle.h" #include "TrackControls.h" #include "ZoomHandle.h" @@ -19,7 +20,6 @@ Paul Licameli split from class TrackView (now called ChannelView) #include "../../ProjectSettings.h" #include "Track.h" #include "../../TrackArtist.h" -#include "../../TrackInfo.h" #include "../../TrackPanelDrawingContext.h" #include "../../TrackPanelMouseEvent.h" @@ -80,7 +80,7 @@ std::shared_ptr CommonChannelView::ContextMenuDelegate() int CommonChannelView::GetMinimizedHeight() const { - auto height = TrackInfo::MinimumTrackHeight(); + auto height = CommonTrackInfo::MinimumTrackHeight(); const auto pTrack = FindTrack(); auto channels = TrackList::Channels(pTrack->SubstituteOriginalTrack().get()); auto nChannels = channels.size(); diff --git a/src/tracks/ui/CommonTrackControls.cpp b/src/tracks/ui/CommonTrackControls.cpp index f55b1391381f..82c13e9674be 100644 --- a/src/tracks/ui/CommonTrackControls.cpp +++ b/src/tracks/ui/CommonTrackControls.cpp @@ -18,7 +18,7 @@ Paul Licameli split from TrackControls.cpp #include "ProjectHistory.h" #include "../../ProjectWindows.h" #include "../../TrackArtist.h" -#include "../../TrackInfo.h" +#include "CommonTrackInfo.h" #include "../../TrackPanelDrawingContext.h" #include "../../TrackPanelMouseEvent.h" #include "../../TrackUtilities.h" @@ -275,7 +275,7 @@ unsigned CommonTrackControls::DoContextMenu( { using namespace RefreshCode; wxRect buttonRect; - TrackInfo::GetTitleBarRect(rect, buttonRect); + CommonTrackInfo::GetTitleBarRect(rect, buttonRect); auto track = FindTrack(); if (!track) @@ -380,7 +380,7 @@ void CommonTrackControls::Draw( if (pTrack) // Draw things within the track control panel - TrackInfo::DrawItems( context, rect, *pTrack ); + CommonTrackInfo::DrawItems( context, rect, *pTrack ); //mTrackInfo.DrawBordersWithin( dc, rect, *t ); } @@ -425,3 +425,8 @@ wxRect CommonTrackControls::DrawingArea( else return rect; } + +const TCPLines &CommonTrackControls::GetTCPLines() const +{ + return CommonTrackInfo::StaticTCPLines(); +} diff --git a/src/tracks/ui/CommonTrackControls.h b/src/tracks/ui/CommonTrackControls.h index 4df88671f11b..2a67f245a343 100644 --- a/src/tracks/ui/CommonTrackControls.h +++ b/src/tracks/ui/CommonTrackControls.h @@ -39,12 +39,7 @@ class AUDACITY_DLL_API CommonTrackControls /* not final */ : public TrackControl unsigned result; }; - // This decides what details to draw in the track control panel, besides - // those at the bottom - virtual const TCPLines& GetTCPLines() const; - - // To help subclasses define GetTCPLines - static const TCPLines& StaticTCPLines(); + const TCPLines& GetTCPLines() const override; protected: // An override is supplied for derived classes to call through but it is diff --git a/src/tracks/ui/CommonTrackInfo.cpp b/src/tracks/ui/CommonTrackInfo.cpp new file mode 100644 index 000000000000..034704394b41 --- /dev/null +++ b/src/tracks/ui/CommonTrackInfo.cpp @@ -0,0 +1,485 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +CommonTrackInfo.cpp + +Paul Licameli split from TrackInfo.cpp + +********************************************************************//*! + +\namespace CommonTrackInfo +\brief + Functions for drawing the track control panel, which is shown to the side + of a track + It has the menus, pan and gain controls displayed in it. + So "Info" is somewhat a misnomer. Should possibly be "TrackControls". + + It maintains global slider widget instances that are reparented and + repositioned as needed for drawing and interaction with the user, + interoperating with the custom panel subdivision implemented in CellularPanel + and avoiding wxWidgets sizers + + If we'd instead coded it as a wxWindow, we would have an instance + of this class for each track displayed. + +**********************************************************************/ +#include "CommonTrackInfo.h" + +#include +#include "AColor.h" +#include "AllThemeResources.h" +#include "SyncLock.h" +#include "Theme.h" +#include "Track.h" +#include "TrackControls.h" +#include "TrackPanelDrawingContext.h" +#include "UIHandle.h" +#include "ViewInfo.h" +#include "tracks/ui/ChannelView.h" + +#define RANGE(array) std::begin(array), std::end(array) +using TCPLine = TrackInfo::TCPLine; +using TCPLines = TrackInfo::TCPLines; + +static const TCPLines &commonTrackTCPLines() +{ + static const TCPLines theLines{ +#ifdef EXPERIMENTAL_DA + + { TCPLine::kItemBarButtons, kTrackInfoBtnSize, 4, + &TrackInfo::CloseTitleDrawFunction }, + +#else + + { TCPLine::kItemBarButtons, kTrackInfoBtnSize, 0, + &CommonTrackInfo::CloseTitleDrawFunction }, + +#endif + }; + return theLines; +} + +const TCPLines &CommonTrackInfo::StaticTCPLines() +{ + return commonTrackTCPLines(); +} + +namespace { + +int totalTCPLines( const TCPLines &lines, bool omitLastExtra ) +{ + int total = 0; + int lastExtra = 0; + for ( const auto line : lines ) { + lastExtra = line.extraSpace; + total += line.height + lastExtra; + } + if (omitLastExtra) + total -= lastExtra; + return total; +} +} + +namespace { + +// Items for the bottom of the panel, listed bottom-upwards +// As also with the top items, the extra space is below the item +const TrackInfo::TCPLine defaultCommonTrackTCPBottomLines[] = { + // The '0' avoids impinging on bottom line of TCP + // Use -1 if you do want to do so. + { TCPLine::kItemSyncLock | TCPLine::kItemMinimize, kTrackInfoBtnSize, 0, + &CommonTrackInfo::MinimizeSyncLockDrawFunction }, +}; +TCPLines commonTrackTCPBottomLines{ RANGE(defaultCommonTrackTCPBottomLines) }; + +// return y value and height +std::pair< int, int > CalcBottomItemY + ( const TCPLines &lines, unsigned iItem, int height ) +{ + int y = height; + auto pLines = lines.begin(); + while ( pLines != lines.end() && + 0 == (pLines->items & iItem) ) { + y -= pLines->height + pLines->extraSpace; + ++pLines; + } + if (pLines != lines.end()) + y -= (pLines->height + pLines->extraSpace ); + return { y, pLines->height }; +} + +} + +unsigned CommonTrackInfo::MinimumTrackHeight() +{ + unsigned height = 0; + if (!commonTrackTCPLines().empty()) + height += commonTrackTCPLines().front().height; + if (!commonTrackTCPBottomLines.empty()) + height += commonTrackTCPBottomLines.front().height; + // + 1 prevents the top item from disappearing for want of enough space, + // according to the rules in HideTopItem. + return height + kVerticalPadding + 1; +} + +bool CommonTrackInfo::HideTopItem( const wxRect &rect, const wxRect &subRect, + int allowance ) { + auto limit = CalcBottomItemY + ( commonTrackTCPBottomLines, TCPLine::kHighestBottomItem, rect.height).first; + // Return true if the rectangle is even touching the limit + // without an overlap. That was the behavior as of 2.1.3. + return subRect.y + subRect.height - allowance >= rect.y + limit; +} + +void CommonTrackInfo::DrawItems +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track &track ) +{ + auto &trackControl = TrackControls::Get(track); + const auto &topLines = trackControl.GetTCPLines(); + const auto &bottomLines = commonTrackTCPBottomLines; + DrawItems + ( context, rect, &track, topLines, bottomLines ); +} + +void CommonTrackInfo::DrawItems +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack, + const std::vector &topLines, const std::vector &bottomLines ) +{ + auto dc = &context.dc; + TrackInfo::SetTrackInfoFont(dc); + dc->SetTextForeground(theTheme.Colour(clrTrackPanelText)); + + { + int yy = 0; + for ( const auto &line : topLines ) { + wxRect itemRect{ + rect.x, rect.y + yy, + rect.width, line.height + }; + if ( !CommonTrackInfo::HideTopItem( rect, itemRect ) && + line.drawFunction ) + line.drawFunction( context, itemRect, pTrack ); + yy += line.height + line.extraSpace; + } + } + { + int yy = rect.height; + for ( const auto &line : bottomLines ) { + yy -= line.height + line.extraSpace; + if ( line.drawFunction ) { + wxRect itemRect{ + rect.x, rect.y + yy, + rect.width, line.height + }; + line.drawFunction( context, itemRect, pTrack ); + } + } + } +} + +void CommonTrackInfo::DrawCloseButton( + TrackPanelDrawingContext &context, const wxRect &bev, + const Track *pTrack, UIHandle *target) +{ + auto dc = &context.dc; + bool selected = pTrack ? pTrack->GetSelected() : true; + bool hit = target && + target->FindChannel().get() == dynamic_cast(pTrack); + bool captured = hit && target->IsDragging(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + AColor::Bevel2(*dc, !down, bev, selected, hit ); + +#ifdef EXPERIMENTAL_THEMING + wxPen pen( theTheme.Colour( clrTrackPanelText )); + dc->SetPen( pen ); +#else + dc->SetPen(*wxBLACK_PEN); +#endif + bev.Inflate( -1, -1 ); + // Draw the "X" + const int s = 6; + + int ls = bev.x + ((bev.width - s) / 2); + int ts = bev.y + ((bev.height - s) / 2); + int rs = ls + s; + int bs = ts + s; + + AColor::Line(*dc, ls, ts, rs, bs); + AColor::Line(*dc, ls + 1, ts, rs + 1, bs); + AColor::Line(*dc, rs, ts, ls, bs); + AColor::Line(*dc, rs + 1, ts, ls + 1, bs); + // bev.Inflate(-1, -1); +} + +void CommonTrackInfo::CloseTitleDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + bool selected = pTrack ? pTrack->GetSelected() : true; + { + wxRect bev = rect; + GetCloseBoxHorizontalBounds( rect, bev ); + auto target = context.target.get(); + DrawCloseButton( context, bev, pTrack, target ); + } + + { + wxRect bev = rect; + GetTitleBarHorizontalBounds( rect, bev ); + auto target = context.target.get(); + bool hit = target && + target->FindChannel().get() == dynamic_cast(pTrack); + bool captured = hit && target->IsDragging(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + wxString titleStr = + pTrack ? pTrack->GetName() : _("Name"); + + //bev.Inflate(-1, -1); + AColor::Bevel2(*dc, !down, bev, selected, hit); + + // Draw title text + TrackInfo::SetTrackInfoFont(dc); + + // Bug 1660 The 'k' of 'Audio Track' was being truncated. + // Constant of 32 found by counting pixels on a windows machine. + // I believe it's the size of the X close button + the size of the + // drop down arrow. + int allowableWidth = rect.width - 32; + + wxCoord textWidth, textHeight; + dc->GetTextExtent(titleStr, &textWidth, &textHeight); + while (textWidth > allowableWidth) { + titleStr = titleStr.Left(titleStr.length() - 1); + dc->GetTextExtent(titleStr, &textWidth, &textHeight); + } + + // Pop-up triangle + #ifdef EXPERIMENTAL_THEMING + wxColour c = theTheme.Colour( clrTrackPanelText ); + #else + wxColour c = *wxBLACK; + #endif + + // wxGTK leaves little scraps (antialiasing?) of the + // characters if they are repeatedly drawn. This + // happens when holding down mouse button and moving + // in and out of the title bar. So clear it first. + // AColor::MediumTrackInfo(dc, t->GetSelected()); + // dc->DrawRectangle(bev); + + dc->SetTextForeground( c ); + dc->SetTextBackground( wxTRANSPARENT ); + dc->DrawText(titleStr, bev.x + 2, bev.y + (bev.height - textHeight) / 2); + + + + dc->SetPen(c); + dc->SetBrush(c); + + int s = 10; // Width of dropdown arrow...height is half of width + AColor::Arrow(*dc, + bev.GetRight() - s - 3, // 3 to offset from right border + bev.y + ((bev.height - (s / 2)) / 2), + s); + + } +} + +void CommonTrackInfo::MinimizeSyncLockDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + bool selected = pTrack ? pTrack->GetSelected() : true; + bool syncLockSelected = pTrack ? SyncLock::IsSyncLockSelected(pTrack) : true; + bool minimized = + pTrack ? ChannelView::Get(*pTrack->GetChannel(0)).GetMinimized() : false; + { + wxRect bev = rect; + GetMinimizeHorizontalBounds(rect, bev); + auto target = context.target.get(); + bool hit = target && + target->FindChannel().get() == dynamic_cast(pTrack); + bool captured = hit && target->IsDragging(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + + // Clear background to get rid of previous arrow + //AColor::MediumTrackInfo(dc, t->GetSelected()); + //dc->DrawRectangle(bev); + + AColor::Bevel2(*dc, !down, bev, selected, hit); + +#ifdef EXPERIMENTAL_THEMING + wxColour c = theTheme.Colour(clrTrackPanelText); + dc->SetBrush(c); + dc->SetPen(c); +#else + AColor::Dark(dc, selected); +#endif + + AColor::Arrow(*dc, + bev.x - 5 + bev.width / 2, + bev.y - 2 + bev.height / 2, + 10, + minimized); + } + + { + wxRect bev = rect; + GetSelectButtonHorizontalBounds(rect, bev); + auto target = context.target.get(); + bool hit = target && + target->FindChannel().get() == dynamic_cast(pTrack); + bool captured = hit && target->IsDragging(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + + AColor::Bevel2(*dc, !down, bev, selected, hit); + +#ifdef EXPERIMENTAL_THEMING + wxColour c = theTheme.Colour(clrTrackPanelText); + dc->SetBrush(c); + dc->SetPen(c); +#else + AColor::Dark(dc, selected); +#endif + + wxString str = _("Select"); + wxCoord textWidth; + wxCoord textHeight; + TrackInfo::SetTrackInfoFont(dc); + dc->GetTextExtent(str, &textWidth, &textHeight); + + dc->SetTextForeground( c ); + dc->SetTextBackground( wxTRANSPARENT ); + dc->DrawText(str, bev.x + 2 + (bev.width-textWidth)/2, bev.y + (bev.height - textHeight) / 2); + } + + + // Draw the sync-lock indicator if this track is in a sync-lock selected group. + if (syncLockSelected) + { + wxRect syncLockIconRect = rect; + + GetSyncLockHorizontalBounds( rect, syncLockIconRect ); + wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockIcon)); + // Icon is 12x12 and syncLockIconRect is 16x16. + dc->DrawBitmap(syncLockBitmap, + syncLockIconRect.x + 3, + syncLockIconRect.y + 2, + true); + } +} + +void CommonTrackInfo::GetCloseBoxHorizontalBounds( const wxRect & rect, wxRect &dest ) +{ + dest.x = rect.x; + dest.width = kTrackInfoBtnSize; +} + +void CommonTrackInfo::GetCloseBoxRect(const wxRect & rect, wxRect & dest) +{ + GetCloseBoxHorizontalBounds( rect, dest ); + auto results = CalcItemY( commonTrackTCPLines(), TCPLine::kItemBarButtons ); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +void CommonTrackInfo::GetTitleBarHorizontalBounds( const wxRect & rect, wxRect &dest ) +{ + // to right of CloseBoxRect, plus a little more + wxRect closeRect; + GetCloseBoxHorizontalBounds( rect, closeRect ); + dest.x = rect.x + closeRect.width + 1; + dest.width = rect.x + rect.width - dest.x + TitleSoloBorderOverlap; +} + +void CommonTrackInfo::GetTitleBarRect(const wxRect & rect, wxRect & dest) +{ + GetTitleBarHorizontalBounds( rect, dest ); + auto results = CalcItemY( commonTrackTCPLines(), TCPLine::kItemBarButtons ); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +void CommonTrackInfo::GetSliderHorizontalBounds( const wxPoint &topleft, wxRect &dest ) +{ + dest.x = topleft.x + 6; + dest.width = kTrackInfoSliderWidth; +} + +void CommonTrackInfo::GetMinimizeHorizontalBounds( const wxRect &rect, wxRect &dest ) +{ + const int space = 0;// was 3. + dest.x = rect.x + space; + + wxRect syncLockRect; + GetSyncLockHorizontalBounds( rect, syncLockRect ); + + // Width is rect.width less space on left for track select + // and on right for sync-lock icon. + dest.width = kTrackInfoBtnSize; +// rect.width - (space + syncLockRect.width); +} + +void CommonTrackInfo::GetMinimizeRect(const wxRect & rect, wxRect &dest) +{ + GetMinimizeHorizontalBounds( rect, dest ); + auto results = CalcBottomItemY + ( commonTrackTCPBottomLines, TCPLine::kItemMinimize, rect.height); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +void CommonTrackInfo::GetSelectButtonHorizontalBounds( const wxRect &rect, wxRect &dest ) +{ + const int space = 0;// was 3. + dest.x = rect.x + space; + + wxRect syncLockRect; + GetSyncLockHorizontalBounds( rect, syncLockRect ); + wxRect minimizeRect; + GetMinimizeHorizontalBounds( rect, minimizeRect ); + + dest.x = dest.x + space + minimizeRect.width; + // Width is rect.width less space on left for track select + // and on right for sync-lock icon. + dest.width = rect.width - (space + syncLockRect.width) - (space + minimizeRect.width); +} + + +void CommonTrackInfo::GetSelectButtonRect(const wxRect & rect, wxRect &dest) +{ + GetSelectButtonHorizontalBounds( rect, dest ); + auto results = CalcBottomItemY + ( commonTrackTCPBottomLines, TCPLine::kItemMinimize, rect.height); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +void CommonTrackInfo::GetSyncLockHorizontalBounds( const wxRect &rect, wxRect &dest ) +{ + dest.width = kTrackInfoBtnSize; + dest.x = rect.x + rect.width - dest.width; +} + +void CommonTrackInfo::GetSyncLockIconRect(const wxRect & rect, wxRect &dest) +{ + GetSyncLockHorizontalBounds( rect, dest ); + auto results = CalcBottomItemY + ( commonTrackTCPBottomLines, TCPLine::kItemSyncLock, rect.height); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +unsigned CommonTrackInfo::DefaultTrackHeight( const TCPLines &topLines ) +{ + int needed = + kVerticalPadding + + totalTCPLines( topLines, true ) + + totalTCPLines( commonTrackTCPBottomLines, false ) + 1; + return (unsigned) std::max(needed, (int) ChannelView::DefaultHeight); +} diff --git a/src/tracks/ui/CommonTrackInfo.h b/src/tracks/ui/CommonTrackInfo.h new file mode 100644 index 000000000000..48c01fd99a64 --- /dev/null +++ b/src/tracks/ui/CommonTrackInfo.h @@ -0,0 +1,94 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +CommonTrackInfo.h + +Paul Licameli split from TrackInfo.h + +**********************************************************************/ +#ifndef __AUDACITY_COMMON_TRACK_INFO__ +#define __AUDACITY_COMMON_TRACK_INFO__ + +#include "TrackInfo.h" + +class wxPoint; + +static const int TitleSoloBorderOverlap = 1; + +namespace CommonTrackInfo +{ + using TCPLine = TrackInfo::TCPLine; + using TCPLines = TrackInfo::TCPLines; + + AUDACITY_DLL_API + unsigned MinimumTrackHeight(); + + AUDACITY_DLL_API + unsigned DefaultTrackHeight( const TCPLines &topLines ); + + AUDACITY_DLL_API + void DrawItems + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track &track ); + + AUDACITY_DLL_API + void DrawItems + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack, + const std::vector &topLines, + const std::vector &bottomLines ); + + AUDACITY_DLL_API + void DrawCloseButton(TrackPanelDrawingContext &context, const wxRect &bev, + const Track *pTrack, UIHandle *target); + + AUDACITY_DLL_API + void CloseTitleDrawFunction + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ); + + AUDACITY_DLL_API + void MinimizeSyncLockDrawFunction + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ); + + + AUDACITY_DLL_API + void GetCloseBoxHorizontalBounds( const wxRect & rect, wxRect &dest ); + AUDACITY_DLL_API + void GetCloseBoxRect(const wxRect & rect, wxRect &dest); + + AUDACITY_DLL_API + void GetTitleBarHorizontalBounds( const wxRect & rect, wxRect &dest ); + AUDACITY_DLL_API + void GetTitleBarRect(const wxRect & rect, wxRect &dest); + + AUDACITY_DLL_API + void GetSliderHorizontalBounds( const wxPoint &topleft, wxRect &dest ); + + AUDACITY_DLL_API + void GetMinimizeHorizontalBounds( const wxRect &rect, wxRect &dest ); + AUDACITY_DLL_API + void GetMinimizeRect(const wxRect & rect, wxRect &dest); + + AUDACITY_DLL_API + void GetSelectButtonHorizontalBounds( const wxRect &rect, wxRect &dest ); + AUDACITY_DLL_API + void GetSelectButtonRect(const wxRect & rect, wxRect &dest); + + AUDACITY_DLL_API + void GetSyncLockHorizontalBounds( const wxRect &rect, wxRect &dest ); + AUDACITY_DLL_API + void GetSyncLockIconRect(const wxRect & rect, wxRect &dest); + + AUDACITY_DLL_API + bool HideTopItem( const wxRect &rect, const wxRect &subRect, + int allowance = 0 ); + + // To help subclasses define GetTCPLines + AUDACITY_DLL_API + const TCPLines& StaticTCPLines(); +}; + +#endif diff --git a/src/tracks/ui/EnvelopeHandle.cpp b/src/tracks/ui/EnvelopeHandle.cpp index 4a3e13a5544d..5e5f024ae6f6 100644 --- a/src/tracks/ui/EnvelopeHandle.cpp +++ b/src/tracks/ui/EnvelopeHandle.cpp @@ -30,8 +30,10 @@ Paul Licameli split from TrackPanel.cpp #include -EnvelopeHandle::EnvelopeHandle( Envelope *pEnvelope ) - : mEnvelope{ pEnvelope } +EnvelopeHandle::EnvelopeHandle(Envelope *pEnvelope, + std::weak_ptr wChannel +) : mEnvelope{ pEnvelope } + , mwChannel{ move(wChannel) } { } @@ -45,10 +47,16 @@ void EnvelopeHandle::Enter(bool, AudacityProject *) EnvelopeHandle::~EnvelopeHandle() {} -UIHandlePtr EnvelopeHandle::HitAnywhere -(std::weak_ptr &holder, Envelope *envelope, bool timeTrack) +std::shared_ptr EnvelopeHandle::FindChannel() const { - auto result = AssignUIHandlePtr(holder, std::make_shared(envelope)); + return mwChannel.lock(); +} + +UIHandlePtr EnvelopeHandle::HitAnywhere(std::weak_ptr &holder, + Envelope *envelope, std::weak_ptr wChannel, bool timeTrack) +{ + auto result = AssignUIHandlePtr(holder, + std::make_shared(envelope, move(wChannel))); result->mTimeTrack = timeTrack; return result; } @@ -70,10 +78,10 @@ namespace { } } -UIHandlePtr EnvelopeHandle::TimeTrackHitTest -(std::weak_ptr &holder, - const wxMouseState &state, const wxRect &rect, - const AudacityProject *pProject, const std::shared_ptr &tt) +UIHandlePtr EnvelopeHandle::TimeTrackHitTest( + std::weak_ptr &holder, + const wxMouseState &state, const wxRect &rect, + const AudacityProject *pProject, const std::shared_ptr &tt) { auto envelope = tt->GetEnvelope(); if (!envelope) @@ -82,9 +90,9 @@ UIHandlePtr EnvelopeHandle::TimeTrackHitTest double dBRange; float zoomMin, zoomMax; GetTimeTrackData( *pProject, *tt, dBRange, dB, zoomMin, zoomMax); - return EnvelopeHandle::HitEnvelope - (holder, state, rect, pProject, envelope, zoomMin, zoomMax, dB, dBRange, - true); + return EnvelopeHandle::HitEnvelope(holder, state, rect, pProject, envelope, + std::dynamic_pointer_cast(tt), + zoomMin, zoomMax, dB, dBRange, true); } UIHandlePtr EnvelopeHandle::WaveTrackHitTest @@ -110,15 +118,17 @@ UIHandlePtr EnvelopeHandle::WaveTrackHitTest const float dBRange = WaveformSettings::Get(*wt).dBRange; - return EnvelopeHandle::HitEnvelope - (holder, state, rect, pProject, envelope, zoomMin, zoomMax, dB, dBRange, false); + return EnvelopeHandle::HitEnvelope(holder, state, rect, pProject, envelope, + std::dynamic_pointer_cast(wt), + zoomMin, zoomMax, dB, dBRange, false); } -UIHandlePtr EnvelopeHandle::HitEnvelope -(std::weak_ptr &holder, - const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject, - Envelope *envelope, float zoomMin, float zoomMax, - bool dB, float dBRange, bool timeTrack) +UIHandlePtr EnvelopeHandle::HitEnvelope(std::weak_ptr &holder, + const wxMouseState &state, const wxRect &rect, + const AudacityProject *pProject, + Envelope *envelope, std::weak_ptr wChannel, + float zoomMin, float zoomMax, + bool dB, float dBRange, bool timeTrack) { const auto &viewInfo = ViewInfo::Get( *pProject ); @@ -166,7 +176,7 @@ UIHandlePtr EnvelopeHandle::HitEnvelope if (distance >= yTolerance) return {}; - return HitAnywhere(holder, envelope, timeTrack); + return HitAnywhere(holder, envelope, move(wChannel), timeTrack); } UIHandle::Result EnvelopeHandle::Click diff --git a/src/tracks/ui/EnvelopeHandle.h b/src/tracks/ui/EnvelopeHandle.h index a2a0f53e6a8f..a76ea0e06101 100644 --- a/src/tracks/ui/EnvelopeHandle.h +++ b/src/tracks/ui/EnvelopeHandle.h @@ -29,24 +29,26 @@ class AUDACITY_DLL_API EnvelopeHandle final : public UIHandle EnvelopeHandle(const EnvelopeHandle&) = delete; EnvelopeHandle &operator=(const EnvelopeHandle&) = delete; - static UIHandlePtr HitEnvelope - (std::weak_ptr &holder, - const wxMouseState &state, const wxRect &rect, - const AudacityProject *pProject, - Envelope *envelope, float zoomMin, float zoomMax, - bool dB, float dBRange, bool timeTrack); + static UIHandlePtr HitEnvelope(std::weak_ptr &holder, + const wxMouseState &state, const wxRect &rect, + const AudacityProject *pProject, + Envelope *envelope, std::weak_ptr wChannel, + float zoomMin, float zoomMax, + bool dB, float dBRange, bool timeTrack); public: - explicit EnvelopeHandle( Envelope *pEnvelope ); + EnvelopeHandle(Envelope *pEnvelope, std::weak_ptr wChannel); EnvelopeHandle(EnvelopeHandle&&) = default; EnvelopeHandle& operator=(EnvelopeHandle&&) = default; virtual ~EnvelopeHandle(); - static UIHandlePtr HitAnywhere - (std::weak_ptr &holder, Envelope *envelope, - bool timeTrack); + std::shared_ptr FindChannel() const override; + + static UIHandlePtr HitAnywhere(std::weak_ptr &holder, + Envelope *envelope, std::weak_ptr wChannel, + bool timeTrack); static UIHandlePtr TimeTrackHitTest (std::weak_ptr &holder, const wxMouseState &state, const wxRect &rect, @@ -88,6 +90,7 @@ class AUDACITY_DLL_API EnvelopeHandle final : public UIHandle double mdBRange{}; Envelope *mEnvelope{}; + std::weak_ptr mwChannel; std::unique_ptr mpEnvelopeEditor; bool mTimeTrack{}; diff --git a/src/tracks/ui/SelectHandle.cpp b/src/tracks/ui/SelectHandle.cpp index 02e3b499c2bf..e4f85af05de2 100644 --- a/src/tracks/ui/SelectHandle.cpp +++ b/src/tracks/ui/SelectHandle.cpp @@ -55,7 +55,7 @@ enum { // #define SPECTRAL_EDITING_ESC_KEY -bool SelectHandle::IsClicked() const +bool SelectHandle::IsDragging() const { return mSelectionStateChanger.get() != NULL; } @@ -458,6 +458,13 @@ SelectHandle::~SelectHandle() { } +std::shared_ptr SelectHandle::FindChannel() const +{ + if (auto pView = mpView.lock()) + return pView->FindChannel(); + return nullptr; +} + namespace { // Is the distance between A and B less than D? template < class A, class B, class DIST > bool within(A a, B b, DIST d) @@ -491,7 +498,7 @@ void SelectHandle::SetUseSnap(bool use, AudacityProject *project) // Repaint to turn the snap lines on or off mChangeHighlight = RefreshCode::RefreshAll; - if (IsClicked()) { + if (IsDragging()) { // Readjust the moving selection end AssignSelection( ViewInfo::Get( *project ), @@ -503,7 +510,7 @@ void SelectHandle::SetUseSnap(bool use, AudacityProject *project) bool SelectHandle::HasSnap() const { return - (IsClicked() ? mSnapEnd : mSnapStart).snappedPoint; + (IsDragging() ? mSnapEnd : mSnapStart).snappedPoint; } bool SelectHandle::HasEscape(AudacityProject *) const @@ -898,7 +905,7 @@ HitTestPreview SelectHandle::Preview TranslatableString tip; wxCursor *pCursor = SelectCursor(); - if ( IsClicked() ) + if (IsDragging()) // Use same cursor as at the click SetTipAndCursorForBoundary (SelectionBoundary(mSelectionBoundary), @@ -1027,8 +1034,8 @@ void SelectHandle::Draw( auto &dc = context.dc; // Draw snap guidelines if we have any if ( mSnapManager ) { - auto coord1 = (mUseSnap || IsClicked()) ? mSnapStart.outCoord : -1; - auto coord2 = (!mUseSnap || !IsClicked()) ? -1 : mSnapEnd.outCoord; + auto coord1 = (mUseSnap || IsDragging()) ? mSnapStart.outCoord : -1; + auto coord2 = (!mUseSnap || !IsDragging()) ? -1 : mSnapEnd.outCoord; mSnapManager->Draw( &dc, coord1, coord2 ); } } diff --git a/src/tracks/ui/SelectHandle.h b/src/tracks/ui/SelectHandle.h index 9cc60e91e105..e96e02c93a84 100644 --- a/src/tracks/ui/SelectHandle.h +++ b/src/tracks/ui/SelectHandle.h @@ -48,7 +48,9 @@ class AUDACITY_DLL_API SelectHandle : public UIHandle virtual ~SelectHandle(); - bool IsClicked() const; + std::shared_ptr FindChannel() const override; + + bool IsDragging() const override; void SetUseSnap(bool use, AudacityProject *pProject); void Enter(bool forward, AudacityProject *pProject) override; diff --git a/src/tracks/ui/SliderHandle.cpp b/src/tracks/ui/SliderHandle.cpp index 5fed55de1dee..98422c862f1f 100644 --- a/src/tracks/ui/SliderHandle.cpp +++ b/src/tracks/ui/SliderHandle.cpp @@ -34,6 +34,16 @@ SliderHandle::~SliderHandle() { } +std::shared_ptr SliderHandle::FindChannel() const +{ + return std::dynamic_pointer_cast(mpTrack.lock()); +} + +bool SliderHandle::IsDragging() const +{ + return mIsDragging; +} + UIHandle::Result SliderHandle::Click (const TrackPanelMouseEvent &evt, AudacityProject *pProject) { @@ -56,7 +66,7 @@ UIHandle::Result SliderHandle::Click // Do not start a drag return result | RefreshCell | Cancelled; else { - mIsClicked = true; + mIsDragging = true; return result | RefreshCell; } } diff --git a/src/tracks/ui/SliderHandle.h b/src/tracks/ui/SliderHandle.h index 259ccd16b14b..18138534ea45 100644 --- a/src/tracks/ui/SliderHandle.h +++ b/src/tracks/ui/SliderHandle.h @@ -32,8 +32,9 @@ class AUDACITY_DLL_API SliderHandle /* not final */ : public UIHandle SliderHandle &operator=(const SliderHandle&) = default; + std::shared_ptr FindChannel() const override; std::shared_ptr GetTrack() const { return mpTrack.lock(); } - bool IsClicked() const { return mIsClicked; } + bool IsDragging() const override; protected: virtual ~SliderHandle(); @@ -79,7 +80,7 @@ class AUDACITY_DLL_API SliderHandle /* not final */ : public UIHandle float mStartingValue {}; - bool mIsClicked{}; + bool mIsDragging{}; }; #endif diff --git a/src/tracks/ui/TimeShiftHandle.cpp b/src/tracks/ui/TimeShiftHandle.cpp index 6340c5ea6fd6..b9e0d1a771f9 100644 --- a/src/tracks/ui/TimeShiftHandle.cpp +++ b/src/tracks/ui/TimeShiftHandle.cpp @@ -118,6 +118,11 @@ TimeShiftHandle::~TimeShiftHandle() { } +std::shared_ptr TimeShiftHandle::FindChannel() const +{ + return std::dynamic_pointer_cast(GetTrack()); +} + void ClipMoveState::DoHorizontalOffset(double offset) { if (!shifters.empty()) { diff --git a/src/tracks/ui/TimeShiftHandle.h b/src/tracks/ui/TimeShiftHandle.h index d1369dbaf1dd..61901192f24c 100644 --- a/src/tracks/ui/TimeShiftHandle.h +++ b/src/tracks/ui/TimeShiftHandle.h @@ -314,6 +314,8 @@ class AUDACITY_DLL_API TimeShiftHandle : public UIHandle virtual ~TimeShiftHandle(); + std::shared_ptr FindChannel() const override; + void Enter(bool forward, AudacityProject *) override; Result Click( @@ -336,13 +338,15 @@ class AUDACITY_DLL_API TimeShiftHandle : public UIHandle bool Clicked() const; -protected: /*! @return will point only to a leader */ std::shared_ptr GetTrack() const; + +protected: //There were attempt to move clip/track horizontally, or to move it vertically bool WasMoved() const; + private: // Try to move clips from one track to another with offset, allowing 1px tolerance, diff --git a/src/tracks/ui/TrackButtonHandles.cpp b/src/tracks/ui/TrackButtonHandles.cpp index 346ebfd3882a..181c0c70ead9 100644 --- a/src/tracks/ui/TrackButtonHandles.cpp +++ b/src/tracks/ui/TrackButtonHandles.cpp @@ -19,7 +19,7 @@ Paul Licameli split from TrackPanel.cpp #include "../../RefreshCode.h" #include "Track.h" #include "TrackFocus.h" -#include "../../TrackInfo.h" +#include "CommonTrackInfo.h" #include "../../TrackPanel.h" #include "../../TrackUtilities.h" #include "CommandManager.h" @@ -68,7 +68,7 @@ UIHandlePtr MinimizeButtonHandle::HitTest const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell) { wxRect buttonRect; - TrackInfo::GetMinimizeRect(rect, buttonRect); + CommonTrackInfo::GetMinimizeRect(rect, buttonRect); if (buttonRect.Contains(state.m_x, state.m_y)) { auto pTrack = static_cast(pCell)->FindTrack(); @@ -123,7 +123,7 @@ UIHandlePtr SelectButtonHandle::HitTest const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell) { wxRect buttonRect; - TrackInfo::GetSelectButtonRect(rect, buttonRect); + CommonTrackInfo::GetSelectButtonRect(rect, buttonRect); if (buttonRect.Contains(state.m_x, state.m_y)) { auto pTrack = static_cast(pCell)->FindTrack(); @@ -189,7 +189,7 @@ UIHandlePtr CloseButtonHandle::HitTest const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell) { wxRect buttonRect; - TrackInfo::GetCloseBoxRect(rect, buttonRect); + CommonTrackInfo::GetCloseBoxRect(rect, buttonRect); if (buttonRect.Contains(state.m_x, state.m_y)) { auto pTrack = static_cast(pCell)->FindTrack(); @@ -250,7 +250,7 @@ UIHandlePtr MenuButtonHandle::HitTest const std::shared_ptr &pCell) { wxRect buttonRect; - TrackInfo::GetTitleBarRect(rect, buttonRect); + CommonTrackInfo::GetTitleBarRect(rect, buttonRect); if (buttonRect.Contains(state.m_x, state.m_y)) { auto pTrack = static_cast(pCell.get())->FindTrack(); diff --git a/src/tracks/ui/TrackControls.h b/src/tracks/ui/TrackControls.h index 4ff2d201e3eb..035972a4c6d1 100644 --- a/src/tracks/ui/TrackControls.h +++ b/src/tracks/ui/TrackControls.h @@ -12,6 +12,7 @@ Paul Licameli split from TrackPanel.cpp #define __AUDACITY_TRACK_CONTROLS__ #include "CommonTrackPanelCell.h" +#include "TrackInfo.h" class Track; @@ -26,6 +27,10 @@ class AUDACITY_DLL_API TrackControls /* not final */ : public CommonTrackCell TrackControls( std::shared_ptr pTrack ); virtual ~TrackControls() = 0; + + // This decides what details to draw in the track control panel, besides + // those at the bottom + virtual const TrackInfo::TCPLines& GetTCPLines() const = 0; }; #include "AttachedVirtualFunction.h" diff --git a/src/tracks/ui/TrackSelectHandle.cpp b/src/tracks/ui/TrackSelectHandle.cpp index d76b95f893be..77befa87f808 100644 --- a/src/tracks/ui/TrackSelectHandle.cpp +++ b/src/tracks/ui/TrackSelectHandle.cpp @@ -65,6 +65,11 @@ TrackSelectHandle::~TrackSelectHandle() { } +std::shared_ptr TrackSelectHandle::FindChannel() const +{ + return std::dynamic_pointer_cast(mpTrack); +} + UIHandle::Result TrackSelectHandle::Click (const TrackPanelMouseEvent &evt, AudacityProject *pProject) { diff --git a/src/tracks/ui/TrackSelectHandle.h b/src/tracks/ui/TrackSelectHandle.h index 3b4226397e4b..589dbae257ca 100644 --- a/src/tracks/ui/TrackSelectHandle.h +++ b/src/tracks/ui/TrackSelectHandle.h @@ -31,6 +31,8 @@ class TrackSelectHandle final : public UIHandle virtual ~TrackSelectHandle(); + std::shared_ptr FindChannel() const override; + Result Click (const TrackPanelMouseEvent &event, AudacityProject *pProject) override; diff --git a/src/tracks/ui/ZoomHandle.cpp b/src/tracks/ui/ZoomHandle.cpp index bf34f5fb86be..e7eed0d92a16 100644 --- a/src/tracks/ui/ZoomHandle.cpp +++ b/src/tracks/ui/ZoomHandle.cpp @@ -83,6 +83,11 @@ ZoomHandle::~ZoomHandle() { } +std::shared_ptr ZoomHandle::FindChannel() const +{ + return nullptr; +} + bool ZoomHandle::HandlesRightClick() { return true; diff --git a/src/tracks/ui/ZoomHandle.h b/src/tracks/ui/ZoomHandle.h index 54726e264193..37c1bf42ff3d 100644 --- a/src/tracks/ui/ZoomHandle.h +++ b/src/tracks/ui/ZoomHandle.h @@ -34,6 +34,8 @@ class ZoomHandle final : public UIHandle virtual ~ZoomHandle(); + std::shared_ptr FindChannel() const override; + bool HandlesRightClick() override; Result Click