Audacity  2.3.1
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 "../../Menus.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 #include "../../commands/CommandType.h"
24 #include "../../commands/Command.h"
25 #include "../../commands/CommandManager.h"
26 #include "../../ShuttleGui.h"
27 
28 
29 TrackControls::TrackControls( std::shared_ptr<Track> pTrack )
30  : mwTrack{ pTrack }
31 {
32 }
33 
35 {
36 }
37 
38 std::shared_ptr<Track> TrackControls::FindTrack()
39 {
40  return mwTrack.lock();
41 }
42 
43 std::vector<UIHandlePtr> TrackControls::HitTest
45  const AudacityProject *WXUNUSED(project))
46 {
47  // Hits are mutually exclusive, results single
48 
49  const wxMouseState &state = st.state;
50  const wxRect &rect = st.rect;
51  UIHandlePtr result;
52  std::vector<UIHandlePtr> results;
53 
54  auto pTrack = FindTrack();
55  // shared pointer to this:
56  auto sThis = pTrack->GetTrackControl();
57 
58  if (NULL != (result = CloseButtonHandle::HitTest(
59  mCloseHandle, state, rect, this)))
60  results.push_back(result);
61 
62  if (NULL != (result = MenuButtonHandle::HitTest(
63  mMenuHandle, state, rect, sThis)))
64  results.push_back(result);
65 
66  if (NULL != (result = MinimizeButtonHandle::HitTest(
67  mMinimizeHandle, state, rect, this)))
68  results.push_back(result);
69 
70  if (results.empty()) {
71  if (NULL != (result = TrackSelectHandle::HitAnywhere(
72  mSelectHandle, pTrack)))
73  results.push_back(result);
74  }
75 
76  return results;
77 }
78 
79 enum
80 {
81  OnSetNameID = 2000,
86 };
87 
89 {
90  TrackMenuTable() : mpData(NULL) {}
92 
93 public:
94  static TrackMenuTable &Instance();
95 
96 private:
97  void OnSetName(wxCommandEvent &);
98  void OnMoveTrack(wxCommandEvent &event);
99 
100  void InitMenu(Menu *pMenu, void *pUserData) override;
101 
102  void DestroyMenu() override
103  {
104  mpData = nullptr;
105  }
106 
108 };
109 
111 {
112  static TrackMenuTable instance;
113  return instance;
114 }
115 
116 void TrackMenuTable::InitMenu(Menu *pMenu, void *pUserData)
117 {
118  mpData = static_cast<TrackControls::InitMenuData*>(pUserData);
119  Track *const pTrack = mpData->pTrack;
120 
121  TrackList *const tracks = GetActiveProject()->GetTracks();
122 
123  pMenu->Enable(OnMoveUpID, tracks->CanMoveUp(pTrack));
124  pMenu->Enable(OnMoveDownID, tracks->CanMoveDown(pTrack));
125  pMenu->Enable(OnMoveTopID, tracks->CanMoveUp(pTrack));
126  pMenu->Enable(OnMoveBottomID, tracks->CanMoveDown(pTrack));
127 }
128 
130  POPUP_MENU_ITEM(OnSetNameID, _("&Name..."), OnSetName)
133  // It is not correct to use NormalizedKeyString::Display here --
134  // wxWidgets will apply its equivalent to the key names passed to menu
135  // functions.
136  OnMoveUpID,
137  _("Move Track &Up") + wxT("\t") +
138  (GetActiveProject()->GetCommandManager()->
139  GetKeyFromName(wxT("TrackMoveUp")).Raw()),
140  OnMoveTrack)
142  OnMoveDownID,
143  _("Move Track &Down") + wxT("\t") +
144  (GetActiveProject()->GetCommandManager()->
145  GetKeyFromName(wxT("TrackMoveDown")).Raw()),
146  OnMoveTrack)
148  OnMoveTopID,
149  _("Move Track to &Top") + wxT("\t") +
150  (GetActiveProject()->GetCommandManager()->
151  GetKeyFromName(wxT("TrackMoveTop")).Raw()),
152  OnMoveTrack)
155  _("Move Track to &Bottom") + wxT("\t") +
156  (GetActiveProject()->GetCommandManager()->
157  GetKeyFromName(wxT("TrackMoveBottom")).Raw()),
158  OnMoveTrack)
160 
161 
162 
163 
164 #define SET_TRACK_NAME_PLUGIN_SYMBOL ComponentInterfaceSymbol{ XO("Set Track Name") }
165 
166 // An example of using an AudacityCommand simply to create a dialog.
167 // We can add additional functions later, if we want to make it
168 // available to scripting.
169 // However there is no reason to, as SetTrackStatus is already provided.
170 class SetTrackNameCommand : public AudacityCommand
171 {
172 public:
173  // ComponentInterface overrides
176  //wxString GetDescription() override {return _("Sets the track name.");};
177  //bool DefineParams( ShuttleParams & S ) override;
178  void PopulateOrExchange(ShuttleGui & S) override;
179  //bool Apply(const CommandContext & context) override;
180 
181  // Provide an override, if we want the help button.
182  // wxString ManualPage() override {return wxT("");};
183 public:
184  wxString mName;
185 };
186 
187 void SetTrackNameCommand::PopulateOrExchange(ShuttleGui & S)
188 {
189  S.AddSpace(0, 5);
190 
191  S.StartMultiColumn(2, wxALIGN_CENTER);
192  {
193  S.TieTextBox(_("Name:"),mName);
194  }
195  S.EndMultiColumn();
196 }
197 
198 void TrackMenuTable::OnSetName(wxCommandEvent &)
199 {
200  Track *const pTrack = mpData->pTrack;
201  if (pTrack)
202  {
203  AudacityProject *const proj = ::GetActiveProject();
204  const wxString oldName = pTrack->GetName();
205 
206  SetTrackNameCommand Command;
207  Command.mName = oldName;
208  // Bug 1837 : We need an OK/Cancel result if we are to enter a blank string.
209  bool bResult = Command.PromptUser( proj );
210  if (bResult)
211  {
212  wxString newName = Command.mName;
213  for (auto channel : TrackList::Channels(pTrack))
214  channel->SetName(newName);
215 
216  proj->PushState(wxString::Format(_("Renamed '%s' to '%s'"),
217  oldName,
218  newName),
219  _("Name Change"));
220 
222  }
223  }
224 }
225 
226 void TrackMenuTable::OnMoveTrack(wxCommandEvent &event)
227 {
228  AudacityProject *const project = GetActiveProject();
230  switch (event.GetId()) {
231  default:
232  wxASSERT(false);
233  case OnMoveUpID:
234  choice = TrackActions::OnMoveUpID; break;
235  case OnMoveDownID:
236  choice = TrackActions::OnMoveDownID; break;
237  case OnMoveTopID:
238  choice = TrackActions::OnMoveTopID; break;
239  case OnMoveBottomID:
240  choice = TrackActions::OnMoveBottomID; break;
241  }
242 
243  TrackActions::DoMoveTrack(*project, mpData->pTrack, choice);
244 
245  // MoveTrack already refreshed TrackPanel, which means repaint will happen.
246  // This is a harmless redundancy:
248 }
249 
251  (const wxRect &rect, wxWindow *pParent, wxPoint *)
252 {
253  wxRect buttonRect;
254  TrackInfo::GetTitleBarRect(rect, buttonRect);
255 
256  auto track = FindTrack();
257  if (!track)
259 
260  InitMenuData data{ track.get(), pParent, RefreshCode::RefreshNone };
261 
262  const auto pTable = &TrackMenuTable::Instance();
263  auto pMenu = PopupMenuTable::BuildMenu(pParent, pTable, &data);
264 
265  PopupMenuTable *const pExtension = GetMenuExtension(track.get());
266  if (pExtension)
267  pMenu->Extend(pExtension);
268 
269  pParent->PopupMenu
270  (pMenu.get(), buttonRect.x + 1, buttonRect.y + buttonRect.height + 1);
271 
272  return data.result;
273 }
#define POPUP_MENU_SEPARATOR()
void OnSetName(wxCommandEvent &)
virtual void PopulateOrExchange(ShuttleGui &WXUNUSED(S))
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:27
void GetTitleBarRect(const wxRect &rect, wxRect &dest)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
bool CanMoveDown(Track *t) const
Definition: Track.cpp:973
void InitMenu(Menu *pMenu, void *pUserData) override
TrackControls::InitMenuData * mpData
BaseItemPtr Menu(const wxString &title, Args &&...args)
virtual std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *) override=0
void EndMultiColumn()
virtual ~TrackControls()=0
#define SET_TRACK_NAME_PLUGIN_SYMBOL
void DestroyMenu() override
#define END_POPUP_MENU()
std::unique_ptr< CommandItem > Command(const wxString &name, const wxString &label_in, bool hasDialog, CommandHandlerFinder finder, CommandFunctorPointer callback, CommandFlag flags, const CommandManager::Options &options={})
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
void DoMoveTrack(AudacityProject &project, Track *target, MoveChoice choice)
Move a track up, down, to top or to bottom.
Definition: TrackMenus.cpp:719
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional...
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:174
bool CanMoveUp(Track *t) const
Definition: Track.cpp:968
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
ComponentInterfaceSymbol GetSymbol() override=0
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:191
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:376
Base class for command in Audacity.
static UIHandlePtr HitTest(std::weak_ptr< MinimizeButtonHandle > &holder, const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell)
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
DECLARE_POPUP_MENU(TrackMenuTable)
void PushState(const wxString &desc, const wxString &shortDesc)
Definition: Project.cpp:4611
POPUP_MENU_ITEM(OnMoveUpID, _("Move Track &Up")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveUp")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveDownID
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:311
void OnMoveTrack(wxCommandEvent &event)
wxSizerItem * AddSpace(int width, int height)
static UIHandlePtr HitAnywhere(std::weak_ptr< TrackSelectHandle > &holder, const std::shared_ptr< Track > &pTrack)
TrackList * GetTracks()
Definition: Project.h:209
std::weak_ptr< Track > mwTrack
Definition: TrackControls.h:58
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1356
wxTextCtrl * TieTextBox(const wxString &Prompt, WrappedType &WrappedRef, const int nChars)
static TrackMenuTable & Instance()
BEGIN_POPUP_MENU(SpectrumVRulerMenuTable)