diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 4e5b3497e..ddd2f0d6b 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1133,7 +1133,6 @@ void TrackPanel::HandleInterruptedDrag() case IsResizing: case IsResizingBetweenLinkedTracks: case IsResizingBelowLinkedTracks: - case IsPopping: sendEvent = false; default: @@ -3482,36 +3481,6 @@ void TrackPanel::UpdateViewIfNoTracks() } } -void TrackPanel::HandlePopping(wxMouseEvent & event) -{ - Track *t = mCapturedTrack; - wxRect rect = mCapturedRect; - - if( t==NULL ){ - SetCapturedTrack( NULL ); - return; - } - - wxRect titleRect; - mTrackInfo.GetTitleBarRect(rect, titleRect); - - wxClientDC dc(this); - - if (event.Dragging()) { - mTrackInfo.DrawTitleBar(&dc, rect, t, titleRect.Contains(event.m_x, event.m_y)); - } - else if (event.LeftUp()) { - if (titleRect.Contains(event.m_x, event.m_y)) - { - OnTrackMenu(t); - } - - SetCapturedTrack( NULL ); - - mTrackInfo.DrawTitleBar(&dc, rect, t, false); - } -} - // The tracks positions within the list have changed, so update the vertical // ruler size for the track that triggered the event. void TrackPanel::OnTrackListResized(wxCommandEvent & e) @@ -3768,10 +3737,6 @@ void TrackPanel::HandleLabelClick(wxMouseEvent & event) auto &t = foundCell.pTrack; auto &rect = foundCell.rect; - // LL: Check title bar for popup - if (isleft && PopupFunc(t, rect, event.m_x, event.m_y)) - return; - { #ifdef USE_MIDI // DM: If it's a NoteTrack, it has special controls @@ -3889,21 +3854,6 @@ void TrackPanel::CalculateRearrangingThresholds(wxMouseEvent & event) mMoveDownThreshold = INT_MAX; } -bool TrackPanel::PopupFunc(Track * t, wxRect rect, int x, int y) -{ - wxRect titleRect; - mTrackInfo.GetTitleBarRect(rect, titleRect); - if (!titleRect.Contains(x, y)) - return false; - - wxClientDC dc(this); - SetCapturedTrack( t, IsPopping ); - mCapturedRect = rect; - - mTrackInfo.DrawTitleBar(&dc, rect, t, true); - return true; -} - /// ButtonDown means they just clicked and haven't released yet. /// We use this opportunity to save which track they clicked on, /// and the initial height of the track, so as they drag we can @@ -4764,9 +4714,6 @@ try case IsVZooming: HandleVZoom(event); break; - case IsPopping: - HandlePopping(event); - break; case IsResizing: case IsResizingBetweenLinkedTracks: case IsResizingBelowLinkedTracks: @@ -6021,7 +5968,17 @@ void TrackPanel::OnTrackMenu(Track *t) if(!t) { t = GetFocusedTrack(); - if(!t) return; + if(!t) + return; + } + + { + TrackPanelCell *const pCell = t->GetTrackControl(); + const wxRect rect(FindTrackRect(t, true)); + const UIHandle::Result refreshResult = + pCell->DoContextMenu(rect, this, NULL); + ProcessUIHandleResult(this, mRuler, t, t, refreshResult); + // TODO: Hide following lines inside the above. } mPopupMenuTarget = t; diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 833cebb17..c502be563 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -491,13 +491,6 @@ protected: virtual void HandleRearrange(wxMouseEvent & event); virtual void CalculateRearrangingThresholds(wxMouseEvent & event); - virtual void HandlePopping(wxMouseEvent & event); - - // These *Func methods are used in TrackPanel::HandleLabelClick to set up - // for actual handling in methods called by TrackPanel::OnMouseEvent, and - // to draw button-down states, etc. - virtual bool PopupFunc(Track * t, wxRect rect, int x, int y); - public: virtual void MakeParentRedrawScrollbars(); diff --git a/src/tracks/labeltrack/ui/LabelTrackControls.cpp b/src/tracks/labeltrack/ui/LabelTrackControls.cpp index 75d972049..f2a6a162b 100644 --- a/src/tracks/labeltrack/ui/LabelTrackControls.cpp +++ b/src/tracks/labeltrack/ui/LabelTrackControls.cpp @@ -11,6 +11,8 @@ Paul Licameli split from TrackPanel.cpp #include "../../../Audacity.h" #include "LabelTrackControls.h" #include "../../../HitTestResult.h" +#include "../../../LabelTrack.h" +#include "../../../widgets/PopupMenuTable.h" LabelTrackControls::LabelTrackControls() { @@ -32,3 +34,38 @@ HitTestResult LabelTrackControls::HitTest { return TrackControls::HitTest(event, pProject); } + +class LabelTrackMenuTable : public PopupMenuTable +{ + LabelTrackMenuTable() : mpData(NULL) {} + DECLARE_POPUP_MENU(LabelTrackMenuTable); + +public: + static LabelTrackMenuTable &Instance(); + + void InitMenu(Menu*, void *pUserData) override + { + mpData = static_cast(pUserData); + } + + void DestroyMenu() override + { + mpData = nullptr; + } + + TrackControls::InitMenuData *mpData; +}; + +LabelTrackMenuTable &LabelTrackMenuTable::Instance() +{ + static LabelTrackMenuTable instance; + return instance; +} + +BEGIN_POPUP_MENU(LabelTrackMenuTable) +END_POPUP_MENU() + +PopupMenuTable *LabelTrackControls::GetMenuExtension(Track *) +{ + return &LabelTrackMenuTable::Instance(); +} diff --git a/src/tracks/labeltrack/ui/LabelTrackControls.h b/src/tracks/labeltrack/ui/LabelTrackControls.h index b16d04aa8..4a880f9cb 100644 --- a/src/tracks/labeltrack/ui/LabelTrackControls.h +++ b/src/tracks/labeltrack/ui/LabelTrackControls.h @@ -26,6 +26,8 @@ public: HitTestResult HitTest (const TrackPanelMouseEvent &event, const AudacityProject *pProject) override; + + PopupMenuTable *GetMenuExtension(Track *pTrack) override; }; #endif diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp index 9d5fd5f1a..3063261db 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp @@ -19,6 +19,8 @@ Paul Licameli split from TrackPanel.cpp #include "../../../../HitTestResult.h" #include "../../../../Track.h" #include "../../../../TrackPanelMouseEvent.h" +#include "../../../../NoteTrack.h" +#include "../../../../widgets/PopupMenuTable.h" NoteTrackControls::NoteTrackControls() { @@ -64,4 +66,39 @@ HitTestResult NoteTrackControls::HitTest return TrackControls::HitTest(evt, pProject); } +class NoteTrackMenuTable : public PopupMenuTable +{ + NoteTrackMenuTable() : mpData(NULL) {} + DECLARE_POPUP_MENU(NoteTrackMenuTable); + +public: + static NoteTrackMenuTable &Instance(); + + void InitMenu(Menu*, void *pUserData) override + { + mpData = static_cast(pUserData); + } + + void DestroyMenu() override + { + mpData = nullptr; + } + + TrackControls::InitMenuData *mpData; +}; + +NoteTrackMenuTable &NoteTrackMenuTable::Instance() +{ + static NoteTrackMenuTable instance; + return instance; +} + +BEGIN_POPUP_MENU(NoteTrackMenuTable) +END_POPUP_MENU() + +PopupMenuTable *NoteTrackControls::GetMenuExtension(Track *) +{ + return &NoteTrackMenuTable::Instance(); +} + #endif \ No newline at end of file diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.h b/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.h index 2c208b7e6..c5f0b7129 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.h +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.h @@ -26,6 +26,8 @@ public: HitTestResult HitTest (const TrackPanelMouseEvent &event, const AudacityProject *pProject) override; + + PopupMenuTable *GetMenuExtension(Track *pTrack) override; }; #endif diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp index 192896fd5..a51466d3d 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp @@ -14,9 +14,10 @@ Paul Licameli split from TrackPanel.cpp #include "WaveTrackSliderHandles.h" #include "../../../../HitTestResult.h" -#include "../../../../Track.h" +#include "../../../../WaveTrack.h" #include "../../../../TrackPanel.h" #include "../../../../TrackPanelMouseEvent.h" +#include "../../../../widgets/PopupMenuTable.h" WaveTrackControls::WaveTrackControls() { @@ -65,3 +66,38 @@ HitTestResult WaveTrackControls::HitTest return TrackControls::HitTest(evt, pProject); } + +class WaveTrackMenuTable : public PopupMenuTable +{ + WaveTrackMenuTable() : mpData(NULL) {} + DECLARE_POPUP_MENU(WaveTrackMenuTable); + +public: + static WaveTrackMenuTable &Instance(); + + void InitMenu(Menu*, void *pUserData) override + { + mpData = static_cast(pUserData); + } + + void DestroyMenu() override + { + mpData = nullptr; + } + + TrackControls::InitMenuData *mpData; +}; + +WaveTrackMenuTable &WaveTrackMenuTable::Instance() +{ + static WaveTrackMenuTable instance; + return instance; +} + +BEGIN_POPUP_MENU(WaveTrackMenuTable) +END_POPUP_MENU() + +PopupMenuTable *WaveTrackControls::GetMenuExtension(Track*) +{ + return &WaveTrackMenuTable::Instance(); +} diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.h b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.h index 29d8a3c14..d0db9581a 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.h +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.h @@ -26,6 +26,8 @@ public: HitTestResult HitTest (const TrackPanelMouseEvent &event, const AudacityProject *pProject) override; + + PopupMenuTable *GetMenuExtension(Track *pTrack) override; }; #endif diff --git a/src/tracks/timetrack/ui/TimeTrackControls.cpp b/src/tracks/timetrack/ui/TimeTrackControls.cpp index f09fa8120..3116c9e9d 100644 --- a/src/tracks/timetrack/ui/TimeTrackControls.cpp +++ b/src/tracks/timetrack/ui/TimeTrackControls.cpp @@ -11,6 +11,8 @@ Paul Licameli split from TrackPanel.cpp #include "../../../Audacity.h" #include "TimeTrackControls.h" #include "../../../HitTestResult.h" +#include "../../../TimeTrack.h" +#include "../../../widgets/PopupMenuTable.h" TimeTrackControls::TimeTrackControls() { @@ -32,3 +34,39 @@ HitTestResult TimeTrackControls::HitTest { return TrackControls::HitTest(event, pProject); } + +class TimeTrackMenuTable : public PopupMenuTable +{ + TimeTrackMenuTable() : mpData(NULL) {} + DECLARE_POPUP_MENU(TimeTrackMenuTable); + +public: + static TimeTrackMenuTable &Instance(); + +private: + void InitMenu(Menu *pMenu, void *pUserData) override + { + mpData = static_cast(pUserData); + } + + void DestroyMenu() override + { + mpData = nullptr; + } + + TrackControls::InitMenuData *mpData; +}; + +TimeTrackMenuTable &TimeTrackMenuTable::Instance() +{ + static TimeTrackMenuTable instance; + return instance; +} + +BEGIN_POPUP_MENU(TimeTrackMenuTable) +END_POPUP_MENU() + +PopupMenuTable *TimeTrackControls::GetMenuExtension(Track *) +{ + return &TimeTrackMenuTable::Instance(); +} diff --git a/src/tracks/timetrack/ui/TimeTrackControls.h b/src/tracks/timetrack/ui/TimeTrackControls.h index 374a50e91..de3e4708d 100644 --- a/src/tracks/timetrack/ui/TimeTrackControls.h +++ b/src/tracks/timetrack/ui/TimeTrackControls.h @@ -26,6 +26,8 @@ public: HitTestResult HitTest (const TrackPanelMouseEvent &event, const AudacityProject *pProject) override; + + PopupMenuTable *GetMenuExtension(Track *pTrack) override; }; #endif diff --git a/src/tracks/ui/TrackButtonHandles.cpp b/src/tracks/ui/TrackButtonHandles.cpp index b6916f498..3bc6e8709 100644 --- a/src/tracks/ui/TrackButtonHandles.cpp +++ b/src/tracks/ui/TrackButtonHandles.cpp @@ -8,6 +8,7 @@ Paul Licameli split from TrackPanel.cpp **********************************************************************/ +#include "../../Audacity.h" #include "TrackButtonHandles.h" #include "../../HitTestResult.h" @@ -124,3 +125,44 @@ HitTestResult CloseButtonHandle::HitTest else return {}; } + +//////////////////////////////////////////////////////////////////////////////// + +MenuButtonHandle::MenuButtonHandle() + : ButtonHandle{ TrackPanel::IsPopping } +{ +} + +MenuButtonHandle::~MenuButtonHandle() +{ +} + +MenuButtonHandle &MenuButtonHandle::Instance() +{ + static MenuButtonHandle instance; + return instance; +} + +UIHandle::Result MenuButtonHandle::CommitChanges +(const wxMouseEvent &, AudacityProject *, wxWindow *pParent) +{ + return mpCell->DoContextMenu(mRect, pParent, NULL); +} + +HitTestResult MenuButtonHandle::HitTest +(const wxMouseEvent &event, const wxRect &rect, TrackPanelCell *pCell) +{ + wxRect buttonRect; + TrackInfo::GetTitleBarRect(rect, buttonRect); + + if (buttonRect.Contains(event.m_x, event.m_y)) { + Instance().mpCell = pCell; + Instance().mRect = buttonRect; + return { + HitPreview(), + &Instance() + }; + } + else + return {}; +} diff --git a/src/tracks/ui/TrackButtonHandles.h b/src/tracks/ui/TrackButtonHandles.h index a03edee7e..6c4149194 100644 --- a/src/tracks/ui/TrackButtonHandles.h +++ b/src/tracks/ui/TrackButtonHandles.h @@ -55,4 +55,31 @@ public: static HitTestResult HitTest(const wxMouseEvent &event, const wxRect &rect); }; +//////////////////////////////////////////////////////////////////////////////// + +#include +#include "../../widgets/PopupMenuTable.h" + +class MenuButtonHandle final : public ButtonHandle +{ + MenuButtonHandle(const MenuButtonHandle&) = delete; + MenuButtonHandle &operator=(const MenuButtonHandle&) = delete; + + MenuButtonHandle(); + virtual ~MenuButtonHandle(); + static MenuButtonHandle& Instance(); + +protected: + Result CommitChanges + (const wxMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) + override; + +public: + static HitTestResult HitTest + (const wxMouseEvent &event, const wxRect &rect, TrackPanelCell *pCell); + +private: + TrackPanelCell *mpCell{}; +}; + #endif diff --git a/src/tracks/ui/TrackControls.cpp b/src/tracks/ui/TrackControls.cpp index ca6c32e84..076ac6482 100644 --- a/src/tracks/ui/TrackControls.cpp +++ b/src/tracks/ui/TrackControls.cpp @@ -12,6 +12,7 @@ Paul Licameli split from TrackPanel.cpp #include "TrackControls.h" #include "TrackButtonHandles.h" #include "../../HitTestResult.h" +#include "../../RefreshCode.h" #include "../../TrackPanel.h" #include "../../TrackPanelMouseEvent.h" @@ -32,6 +33,9 @@ HitTestResult TrackControls::HitTest if (NULL != (result = CloseButtonHandle::HitTest(event, rect)).handle) return result; + if (NULL != (result = MenuButtonHandle::HitTest(event, rect, this)).handle) + return result; + if (NULL != (result = MinimizeButtonHandle::HitTest(event, rect)).handle) return result; @@ -42,3 +46,56 @@ Track *TrackControls::FindTrack() { return GetTrack(); } + +class TrackMenuTable : public PopupMenuTable +{ + TrackMenuTable() : mpData(NULL) {} + DECLARE_POPUP_MENU(TrackMenuTable); + +public: + static TrackMenuTable &Instance(); + +private: + + void InitMenu(Menu*, void *pUserData) override + { + mpData = static_cast(pUserData); + } + + void DestroyMenu() override + { + mpData = nullptr; + } + + TrackControls::InitMenuData *mpData; +}; + +TrackMenuTable &TrackMenuTable::Instance() +{ + static TrackMenuTable instance; + return instance; +} + +BEGIN_POPUP_MENU(TrackMenuTable) +END_POPUP_MENU() + +unsigned TrackControls::DoContextMenu + (const wxRect &rect, wxWindow *pParent, wxPoint *) +{ + wxRect buttonRect; + TrackInfo::GetTitleBarRect(rect, buttonRect); + + InitMenuData data{ mpTrack, pParent, RefreshCode::RefreshNone }; + + const auto pTable = &TrackMenuTable::Instance(); + auto pMenu = PopupMenuTable::BuildMenu(pParent, pTable, &data); + + PopupMenuTable *const pExtension = GetMenuExtension(mpTrack); + if (pExtension) + pMenu->Extend(pExtension); + + pParent->PopupMenu + (pMenu.get(), buttonRect.x + 1, buttonRect.y + buttonRect.height + 1); + + return data.result; +} diff --git a/src/tracks/ui/TrackControls.h b/src/tracks/ui/TrackControls.h index 398ffe11d..c14ffd3dc 100644 --- a/src/tracks/ui/TrackControls.h +++ b/src/tracks/ui/TrackControls.h @@ -13,6 +13,7 @@ Paul Licameli split from TrackPanel.cpp #include "CommonTrackPanelCell.h" +class PopupMenuTable; class Track; class TrackControls /* not final */ : public CommonTrackPanelCell @@ -24,6 +25,16 @@ public: Track *GetTrack() const { return mpTrack; } + // This is passed to the InitMenu() methods of the PopupMenuTable + // objects returned by GetMenuExtension: + struct InitMenuData + { + public: + Track *pTrack; + wxWindow *pParent; + unsigned result; + }; + // Make this hack go away! See TrackPanel::DrawOutside static int gCaptureState; @@ -36,6 +47,10 @@ protected: Track *FindTrack() override; + unsigned DoContextMenu + (const wxRect &rect, wxWindow *pParent, wxPoint *pPosition) override; + virtual PopupMenuTable *GetMenuExtension(Track *pTrack) = 0; + friend class Track; Track *mpTrack; };