Audacity  2.2.2
TrackControls.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 TrackControls.cpp
6 
7 Paul Licameli split from TrackPanel.cpp
8 
9 **********************************************************************/
10 
11 #include "../../Audacity.h"
12 #include "TrackControls.h"
13 #include "TrackButtonHandles.h"
14 #include "TrackSelectHandle.h"
15 #include "../../HitTestResult.h"
16 #include "../../RefreshCode.h"
17 #include "../../MixerBoard.h"
18 #include "../../Project.h"
19 #include "../../TrackPanel.h" // for TrackInfo
20 #include "../../TrackPanelMouseEvent.h"
21 #include "../../Track.h"
22 #include <wx/textdlg.h>
23 
24 TrackControls::TrackControls( std::shared_ptr<Track> pTrack )
25  : mwTrack{ pTrack }
26 {
27 }
28 
30 {
31 }
32 
33 std::shared_ptr<Track> TrackControls::FindTrack()
34 {
35  return mwTrack.lock();
36 }
37 
38 std::vector<UIHandlePtr> TrackControls::HitTest
40  const AudacityProject *WXUNUSED(project))
41 {
42  // Hits are mutually exclusive, results single
43 
44  const wxMouseState &state = st.state;
45  const wxRect &rect = st.rect;
46  UIHandlePtr result;
47  std::vector<UIHandlePtr> results;
48 
49  auto pTrack = FindTrack();
50  // shared pointer to this:
51  auto sThis = pTrack->GetTrackControl();
52 
53  if (NULL != (result = CloseButtonHandle::HitTest(
54  mCloseHandle, state, rect, this)))
55  results.push_back(result);
56 
57  if (NULL != (result = MenuButtonHandle::HitTest(
58  mMenuHandle, state, rect, sThis)))
59  results.push_back(result);
60 
61  if (NULL != (result = MinimizeButtonHandle::HitTest(
62  mMinimizeHandle, state, rect, this)))
63  results.push_back(result);
64 
65  if (results.empty()) {
66  if (NULL != (result = TrackSelectHandle::HitAnywhere(
67  mSelectHandle, pTrack)))
68  results.push_back(result);
69  }
70 
71  return results;
72 }
73 
74 enum
75 {
76  OnSetNameID = 2000,
81 };
82 
84 {
85  TrackMenuTable() : mpData(NULL) {}
87 
88 public:
89  static TrackMenuTable &Instance();
90 
91 private:
92  void OnSetName(wxCommandEvent &);
93  void OnMoveTrack(wxCommandEvent &event);
94 
95  void InitMenu(Menu *pMenu, void *pUserData) override;
96 
97  void DestroyMenu() override
98  {
99  mpData = nullptr;
100  }
101 
103 };
104 
106 {
107  static TrackMenuTable instance;
108  return instance;
109 }
110 
111 void TrackMenuTable::InitMenu(Menu *pMenu, void *pUserData)
112 {
113  mpData = static_cast<TrackControls::InitMenuData*>(pUserData);
114  Track *const pTrack = mpData->pTrack;
115 
116  TrackList *const tracks = GetActiveProject()->GetTracks();
117 
118  pMenu->Enable(OnMoveUpID, tracks->CanMoveUp(pTrack));
119  pMenu->Enable(OnMoveDownID, tracks->CanMoveDown(pTrack));
120  pMenu->Enable(OnMoveTopID, tracks->CanMoveUp(pTrack));
121  pMenu->Enable(OnMoveBottomID, tracks->CanMoveDown(pTrack));
122 }
123 
125  POPUP_MENU_ITEM(OnSetNameID, _("&Name..."), OnSetName)
128  // It is not correct to use KeyStringDisplay here -- wxWidgets will apply
129  // its equivalent to the key names passed to menu functions.
130  OnMoveUpID,
131  _("Move Track &Up") + wxT("\t") +
132  (GetActiveProject()->GetCommandManager()->
133  GetKeyFromName(wxT("TrackMoveUp"))),
134  OnMoveTrack)
136  OnMoveDownID,
137  _("Move Track &Down") + wxT("\t") +
138  (GetActiveProject()->GetCommandManager()->
139  GetKeyFromName(wxT("TrackMoveDown"))),
140  OnMoveTrack)
142  OnMoveTopID,
143  _("Move Track to &Top") + wxT("\t") +
144  (GetActiveProject()->GetCommandManager()->
145  GetKeyFromName(wxT("TrackMoveTop"))),
146  OnMoveTrack)
149  _("Move Track to &Bottom") + wxT("\t") +
150  (GetActiveProject()->GetCommandManager()->
151  GetKeyFromName(wxT("TrackMoveBottom"))),
152  OnMoveTrack)
154 
155 void TrackMenuTable::OnSetName(wxCommandEvent &)
156 {
157  Track *const pTrack = mpData->pTrack;
158  if (pTrack)
159  {
160  AudacityProject *const proj = ::GetActiveProject();
161  const wxString oldName = pTrack->GetName();
162  const wxString newName =
163  wxGetTextFromUser(_("Change track name to:"),
164  _("Track Name"), oldName);
165  if (newName != wxT("")) // wxGetTextFromUser returns empty string on Cancel.
166  {
167  pTrack->SetName(newName);
168  // if we have a linked channel this name should change as well
169  // (otherwise sort by name and time will crash).
170  if (pTrack->GetLinked())
171  pTrack->GetLink()->SetName(newName);
172 
173  MixerBoard *const pMixerBoard = proj->GetMixerBoard();
174  auto pt = dynamic_cast<PlayableTrack*>(pTrack);
175  if (pt && pMixerBoard)
176  pMixerBoard->UpdateName(pt);
177 
178  proj->PushState(wxString::Format(_("Renamed '%s' to '%s'"),
179  oldName,
180  newName),
181  _("Name Change"));
182 
183  mpData->result = RefreshCode::RefreshAll;
184  }
185  }
186 }
187 
188 void TrackMenuTable::OnMoveTrack(wxCommandEvent &event)
189 {
190  AudacityProject *const project = GetActiveProject();
192  switch (event.GetId()) {
193  default:
194  wxASSERT(false);
195  case OnMoveUpID:
196  choice = AudacityProject::OnMoveUpID; break;
197  case OnMoveDownID:
198  choice = AudacityProject::OnMoveDownID; break;
199  case OnMoveTopID:
200  choice = AudacityProject::OnMoveTopID; break;
201  case OnMoveBottomID:
202  choice = AudacityProject::OnMoveBottomID; break;
203  }
204 
205  project->MoveTrack(mpData->pTrack, choice);
206 
207  // MoveTrack already refreshed TrackPanel, which means repaint will happen.
208  // This is a harmless redundancy:
210 }
211 
213  (const wxRect &rect, wxWindow *pParent, wxPoint *)
214 {
215  wxRect buttonRect;
216  TrackInfo::GetTitleBarRect(rect, buttonRect);
217 
218  auto track = FindTrack();
219  if (!track)
221 
222  InitMenuData data{ track.get(), pParent, RefreshCode::RefreshNone };
223 
224  const auto pTable = &TrackMenuTable::Instance();
225  auto pMenu = PopupMenuTable::BuildMenu(pParent, pTable, &data);
226 
227  PopupMenuTable *const pExtension = GetMenuExtension(track.get());
228  if (pExtension)
229  pMenu->Extend(pExtension);
230 
231  pParent->PopupMenu
232  (pMenu.get(), buttonRect.x + 1, buttonRect.y + buttonRect.height + 1);
233 
234  return data.result;
235 }
#define POPUP_MENU_SEPARATOR()
void OnSetName(wxCommandEvent &)
A list of TrackListNode items.
Definition: Track.h:553
bool CanMoveDown(Track *t) const
Definition: Track.cpp:1041
void InitMenu(Menu *pMenu, void *pUserData) override
TrackControls::InitMenuData * mpData
virtual std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *) override=0
virtual ~TrackControls()=0
bool GetLinked() const
Definition: Track.h:218
void DestroyMenu() override
#define END_POPUP_MENU()
void MoveTrack(Track *target, MoveChoice choice)
Move a track up, down, to top or to bottom.
Definition: Menus.cpp:4046
static UIHandlePtr HitTest(std::weak_ptr< MenuButtonHandle > &holder, const wxMouseState &state, const wxRect &rect, const std::shared_ptr< TrackPanelCell > &pCell)
std::shared_ptr< Track > FindTrack() override
MixerBoard * GetMixerBoard()
Definition: Project.h:503
unsigned DoContextMenu(const wxRect &rect, wxWindow *pParent, wxPoint *pPosition) override
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:161
bool CanMoveUp(Track *t) const
Definition: Track.cpp:1036
static UIHandlePtr HitTest(std::weak_ptr< CloseButtonHandle > &holder, const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell)
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:67
TrackControls(std::shared_ptr< Track > pTrack)
static std::unique_ptr< Menu > BuildMenu(wxEvtHandler *pParent, PopupMenuTable *pTable, void *pUserData=NULL)
wxString GetName() const
Definition: Track.h:212
An AudioTrack that can be played and stopped.
Definition: Track.h:313
std::shared_ptr< UIHandle > UIHandlePtr
Definition: TrackPanel.h:59
static UIHandlePtr HitTest(std::weak_ptr< MinimizeButtonHandle > &holder, const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell)
static void GetTitleBarRect(const wxRect &rect, wxRect &dest)
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
void UpdateName(const PlayableTrack *pTrack)
DECLARE_POPUP_MENU(TrackMenuTable)
void PushState(const wxString &desc, const wxString &shortDesc)
Definition: Project.cpp:4486
void SetName(const wxString &n)
Definition: Track.h:213
Track * GetLink() const
Definition: Track.cpp:204
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:302
void OnMoveTrack(wxCommandEvent &event)
POPUP_MENU_ITEM(OnMoveUpID, _("Move Track &Up")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveUp"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveDownID
static UIHandlePtr HitAnywhere(std::weak_ptr< TrackSelectHandle > &holder, const std::shared_ptr< Track > &pTrack)
TrackList * GetTracks()
Definition: Project.h:177
std::weak_ptr< Track > mwTrack
Definition: TrackControls.h:58
static TrackMenuTable & Instance()
BEGIN_POPUP_MENU(SpectrumVRulerMenuTable)