1 /**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 EditToolBar.cpp
6
7 Dominic Mazzoni
8 Shane T. Mueller
9 Leland Lucius
10
11 See EditToolBar.h for details
12
13 *******************************************************************//*!
14
15 \class EditToolBar
16 \brief A ToolBar that has the edit buttons on it.
17
18 This class, which is a child of Toolbar, creates the
19 window containing interfaces to commonly-used edit
20 functions that are otherwise only available through
21 menus. The window can be embedded within a normal project
22 window, or within a ToolBarFrame.
23
24 All of the controls in this window were custom-written for
25 Audacity - they are not native controls on any platform -
26 however, it is intended that the images could be easily
27 replaced to allow "skinning" or just customization to
28 match the look and feel of each platform.
29
30 *//*******************************************************************/
31
32
33
34 #include "EditToolBar.h"
35
36 // For compilers that support precompilation, includes "wx/wx.h".
37 #include <wx/wxprec.h>
38
39 #include <wx/setup.h> // for wxUSE_* macros
40
41 #ifndef WX_PRECOMP
42 #include <wx/app.h>
43 #include <wx/event.h>
44 #include <wx/image.h>
45 #include <wx/intl.h>
46 #include <wx/sizer.h>
47 #include <wx/tooltip.h>
48 #endif
49
50 #include "AllThemeResources.h"
51 #include "../BatchCommands.h"
52 #include "ImageManipulation.h"
53 #include "../Menus.h"
54 #include "Prefs.h"
55 #include "Project.h"
56 #include "../UndoManager.h"
57 #include "../widgets/AButton.h"
58
59 #include "../commands/CommandContext.h"
60 #include "../commands/CommandManager.h"
61
62 IMPLEMENT_CLASS(EditToolBar, ToolBar);
63
64 const int BUTTON_WIDTH = 27;
65 const int SEPARATOR_WIDTH = 14;
66
67 ////////////////////////////////////////////////////////////
68 /// Methods for EditToolBar
69 ////////////////////////////////////////////////////////////
70
BEGIN_EVENT_TABLE(EditToolBar,ToolBar)71 BEGIN_EVENT_TABLE( EditToolBar, ToolBar )
72 EVT_COMMAND_RANGE( ETBCutID+first_ETB_ID,
73 ETBCutID+first_ETB_ID + ETBNumButtons - 1,
74 wxEVT_COMMAND_BUTTON_CLICKED,
75 EditToolBar::OnButton )
76 END_EVENT_TABLE()
77
78 //Standard constructor
79 EditToolBar::EditToolBar( AudacityProject &project )
80 : ToolBar(project, EditBarID, XO("Edit"), wxT("Edit"))
81 {
82 }
83
~EditToolBar()84 EditToolBar::~EditToolBar()
85 {
86 }
87
Create(wxWindow * parent)88 void EditToolBar::Create(wxWindow * parent)
89 {
90 ToolBar::Create(parent);
91 UpdatePrefs();
92 }
93
AddSeparator()94 void EditToolBar::AddSeparator()
95 {
96 AddSpacer();
97 }
98
99 /// This is a convenience function that allows for button creation in
100 /// MakeButtons() with fewer arguments
101 /// Very similar to code in ControlToolBar...
AddButton(EditToolBar * pBar,teBmps eEnabledUp,teBmps eEnabledDown,teBmps eDisabled,int id,const TranslatableString & label,bool toggle)102 AButton *EditToolBar::AddButton(
103 EditToolBar *pBar,
104 teBmps eEnabledUp, teBmps eEnabledDown, teBmps eDisabled,
105 int id,
106 const TranslatableString &label,
107 bool toggle)
108 {
109 AButton *&r = pBar->mButtons[id];
110
111 r = ToolBar::MakeButton(pBar,
112 bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredUpHiliteSmall, bmpRecoloredHiliteSmall,
113 eEnabledUp, eEnabledDown, eDisabled,
114 wxWindowID(id+first_ETB_ID),
115 wxDefaultPosition,
116 toggle,
117 theTheme.ImageSize( bmpRecoloredUpSmall ));
118
119 r->SetLabel(label);
120 // JKC: Unlike ControlToolBar, does not have a focus rect. Shouldn't it?
121 // r->SetFocusRect( r->GetRect().Deflate( 4, 4 ) );
122
123 pBar->Add( r, 0, wxALIGN_CENTER );
124
125 return r;
126 }
127
Populate()128 void EditToolBar::Populate()
129 {
130 SetBackgroundColour( theTheme.Colour( clrMedium ) );
131 MakeButtonBackgroundsSmall();
132
133 /* Buttons */
134 // Tooltips slightly more verbose than the menu entries are.
135 AddButton(this, bmpCut, bmpCut, bmpCutDisabled, ETBCutID,
136 XO("Cut selection"));
137 AddButton(this, bmpCopy, bmpCopy, bmpCopyDisabled, ETBCopyID,
138 XO("Copy selection"));
139 AddButton(this, bmpPaste, bmpPaste, bmpPasteDisabled, ETBPasteID,
140 XO("Paste"));
141 AddButton(this, bmpTrim, bmpTrim, bmpTrimDisabled, ETBTrimID,
142 XO("Trim audio outside selection"));
143 AddButton(this, bmpSilence, bmpSilence, bmpSilenceDisabled, ETBSilenceID,
144 XO("Silence audio selection"));
145
146 AddSeparator();
147
148 AddButton(this, bmpUndo, bmpUndo, bmpUndoDisabled, ETBUndoID,
149 XO("Undo"));
150 AddButton(this, bmpRedo, bmpRedo, bmpRedoDisabled, ETBRedoID,
151 XO("Redo"));
152
153 AddSeparator();
154
155 #ifdef OPTION_SYNC_LOCK_BUTTON
156 AddButton(this, bmpSyncLockTracksUp, bmpSyncLockTracksDown, bmpSyncLockTracksUp, ETBSyncLockID,
157 XO("Sync-Lock Tracks"), true);
158
159 AddSeparator();
160 #endif
161
162 // Tooltips match menu entries.
163 // We previously had longer tooltips which were not more clear.
164 AddButton(this, bmpZoomIn, bmpZoomIn, bmpZoomInDisabled, ETBZoomInID,
165 XO("Zoom In"));
166 AddButton(this, bmpZoomOut, bmpZoomOut, bmpZoomOutDisabled, ETBZoomOutID,
167 XO("Zoom Out"));
168 AddButton(this, bmpZoomSel, bmpZoomSel, bmpZoomSelDisabled, ETBZoomSelID,
169 XO("Zoom to Selection"));
170 AddButton(this, bmpZoomFit, bmpZoomFit, bmpZoomFitDisabled, ETBZoomFitID,
171 XO("Fit to Width"));
172
173 #ifdef EXPERIMENTAL_ZOOM_TOGGLE_BUTTON
174 AddButton(this, bmpZoomToggle, bmpZoomToggle, bmpZoomToggleDisabled, ETBZoomToggleID,
175 XO("Zoom Toggle"));
176 #endif
177
178
179
180 mButtons[ETBZoomInID]->SetEnabled(false);
181 mButtons[ETBZoomOutID]->SetEnabled(false);
182 #ifdef EXPERIMENTAL_ZOOM_TOGGLE_BUTTON
183 mButtons[ETBZoomToggleID]->SetEnabled(false);
184 #endif
185
186 mButtons[ETBZoomSelID]->SetEnabled(false);
187 mButtons[ETBZoomFitID]->SetEnabled(false);
188 mButtons[ETBPasteID]->SetEnabled(false);
189
190 #ifdef OPTION_SYNC_LOCK_BUTTON
191 mButtons[ETBSyncLockID]->PushDown();
192 #endif
193
194 #if defined(EXPERIMENTAL_EFFECTS_RACK)
195 AddSeparator();
196 AddButton(this, bmpEditEffects, bmpEditEffects, bmpEditEffects, ETBEffectsID,
197 XO("Show Effects Rack"), true);
198 #endif
199
200 RegenerateTooltips();
201 }
202
UpdatePrefs()203 void EditToolBar::UpdatePrefs()
204 {
205 RegenerateTooltips();
206
207 // Set label to pull in language change
208 SetLabel(XO("Edit"));
209
210 // Give base class a chance
211 ToolBar::UpdatePrefs();
212 }
213
RegenerateTooltips()214 void EditToolBar::RegenerateTooltips()
215 {
216 ForAllButtons( ETBActTooltips );
217 }
218
EnableDisableButtons()219 void EditToolBar::EnableDisableButtons()
220 {
221 ForAllButtons( ETBActEnableDisable );
222 }
223
224
225 static const struct Entry {
226 int tool;
227 CommandID commandName;
228 TranslatableString untranslatedLabel;
229 } EditToolbarButtonList[] = {
230 { ETBCutID, wxT("Cut"), XO("Cut") },
231 { ETBCopyID, wxT("Copy"), XO("Copy") },
232 { ETBPasteID, wxT("Paste"), XO("Paste") },
233 { ETBTrimID, wxT("Trim"), XO("Trim audio outside selection") },
234 { ETBSilenceID, wxT("Silence"), XO("Silence audio selection") },
235 { ETBUndoID, wxT("Undo"), XO("Undo") },
236 { ETBRedoID, wxT("Redo"), XO("Redo") },
237
238 #ifdef OPTION_SYNC_LOCK_BUTTON
239 { ETBSyncLockID, wxT("SyncLock"), XO("Sync-Lock Tracks") },
240 #endif
241
242 { ETBZoomInID, wxT("ZoomIn"), XO("Zoom In") },
243 { ETBZoomOutID, wxT("ZoomOut"), XO("Zoom Out") },
244 #ifdef EXPERIMENTAL_ZOOM_TOGGLE_BUTTON
245 { ETBZoomToggleID, wxT("ZoomToggle"), XO("Zoom Toggle") },
246 #endif
247 { ETBZoomSelID, wxT("ZoomSel"), XO("Fit selection to width") },
248 { ETBZoomFitID, wxT("FitInWindow"), XO("Fit project to width") },
249
250 #if defined(EXPERIMENTAL_EFFECTS_RACK)
251 { ETBEffectsID, wxT("ShowEffectsRack"), XO("Open Effects Rack") },
252 #endif
253 };
254
255
ForAllButtons(int Action)256 void EditToolBar::ForAllButtons(int Action)
257 {
258 AudacityProject *p;
259 CommandManager* cm = nullptr;
260
261 if( Action & ETBActEnableDisable ){
262 p = &mProject;
263 cm = &CommandManager::Get( *p );
264 #ifdef OPTION_SYNC_LOCK_BUTTON
265 bool bSyncLockTracks;
266 gPrefs->Read(wxT("/GUI/SyncLockTracks"), &bSyncLockTracks, false);
267
268 if (bSyncLockTracks)
269 mButtons[ETBSyncLockID]->PushDown();
270 else
271 mButtons[ETBSyncLockID]->PopUp();
272 #endif
273 }
274
275
276 for (const auto &entry : EditToolbarButtonList) {
277 #if wxUSE_TOOLTIPS
278 if( Action & ETBActTooltips ){
279 ComponentInterfaceSymbol command{
280 entry.commandName, entry.untranslatedLabel };
281 ToolBar::SetButtonToolTip( mProject,
282 *mButtons[entry.tool], &command, 1u );
283 }
284 #endif
285 if (cm) {
286 mButtons[entry.tool]->SetEnabled(cm->GetEnabled(entry.commandName));
287 }
288 }
289 }
290
OnButton(wxCommandEvent & event)291 void EditToolBar::OnButton(wxCommandEvent &event)
292 {
293 int id = event.GetId()-first_ETB_ID;
294 // Be sure the pop-up happens even if there are exceptions, except for buttons which toggle.
295 auto cleanup = finally( [&] { mButtons[id]->InteractionOver();});
296
297 AudacityProject *p = &mProject;
298 auto &cm = CommandManager::Get( *p );
299
300 auto flags = MenuManager::Get(*p).GetUpdateFlags();
301 const CommandContext context( *p );
302 MacroCommands::HandleTextualCommand( cm,
303 EditToolbarButtonList[id].commandName, context, flags, false);
304
305 #if defined(__WXMAC__)
306 // Bug 2402
307 // LLL: It seems that on the Mac the IDLE events are processed
308 // differently than on Windows/GTK and the AdornedRulerPanel's
309 // OnPaint() method gets called sooner that expected. This is
310 // evident when zooming from this toolbar only. When zooming from
311 // the Menu or from keyboard ommand, the zooming works correctly.
312 wxTheApp->ProcessIdle();
313 #endif
314 }
315
316 static RegisteredToolbarFactory factory{ EditBarID,
__anonc8995de80202( )317 []( AudacityProject &project ){
318 return ToolBar::Holder{ safenew EditToolBar{ project } }; }
319 };
320
321 #include "ToolManager.h"
322
323 namespace {
324 AttachedToolBarMenuItem sAttachment{
325 /* i18n-hint: Clicking this menu item shows the toolbar for editing */
326 EditBarID, wxT("ShowEditTB"), XXO("&Edit Toolbar")
327 };
328 }
329
330