1 /**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ToolsToolBar.cpp
6
7 Dominic Mazzoni
8 Shane T. Mueller
9 Leland Lucius
10
11 See ToolsToolBar.h for details
12
13 *******************************************************************//*!
14
15 \class ToolsToolBar
16 \brief A kind of ToolBar with Tools on it.
17
18 This class, which is a child of Toolbar, creates the
19 window containing the tool selection (ibeam, envelope,
20 move, zoom). The window can be embedded within a
21 normal project window, or within a ToolBarFrame.
22
23 All of the controls in this window were custom-written for
24 Audacity - they are not native controls on any platform -
25 however, it is intended that the images could be easily
26 replaced to allow "skinning" or just customization to
27 match the look and feel of each platform.
28
29 \see \ref Themability
30 *//*******************************************************************/
31
32
33
34 #include "ToolsToolBar.h"
35 #include "ToolManager.h"
36
37 // For compilers that support precompilation, includes "wx/wx.h".
38 #include <wx/wxprec.h>
39
40 #include <wx/setup.h> // for wxUSE_* macros
41
42 #ifndef WX_PRECOMP
43 #include <wx/defs.h>
44 #include <wx/event.h>
45 #include <wx/intl.h>
46 #include <wx/sizer.h>
47 #endif
48 #include <wx/tooltip.h>
49
50 #include "Prefs.h"
51 #include "AllThemeResources.h"
52 #include "ImageManipulation.h"
53 #include "Project.h"
54 #include "../ProjectSettings.h"
55 #include "../ProjectWindow.h"
56 #include "../tracks/ui/Scrubbing.h"
57
58 #include "../widgets/AButton.h"
59
60
61 IMPLEMENT_CLASS(ToolsToolBar, ToolBar);
62
63 ////////////////////////////////////////////////////////////
64 /// Methods for ToolsToolBar
65 ////////////////////////////////////////////////////////////
66
BEGIN_EVENT_TABLE(ToolsToolBar,ToolBar)67 BEGIN_EVENT_TABLE(ToolsToolBar, ToolBar)
68 EVT_COMMAND_RANGE(ToolCodes::firstTool + FirstToolID,
69 ToolsToolBar::numTools - 1 + FirstToolID,
70 wxEVT_COMMAND_BUTTON_CLICKED,
71 ToolsToolBar::OnTool)
72 END_EVENT_TABLE()
73
74 //Standard constructor
75 ToolsToolBar::ToolsToolBar( AudacityProject &project )
76 : ToolBar(project, ToolsBarID, XO("Tools"), wxT("Tools"))
77 {
78 using namespace ToolCodes;
79
80 //Read the following wxASSERTs as documentating a design decision
81 wxASSERT( selectTool == selectTool - firstTool );
82 wxASSERT( envelopeTool == envelopeTool - firstTool );
83 wxASSERT( zoomTool == zoomTool - firstTool );
84 wxASSERT( drawTool == drawTool - firstTool );
85 wxASSERT( multiTool == multiTool - firstTool );
86 bool multiToolActive = false;
87 gPrefs->Read(wxT("/GUI/ToolBars/Tools/MultiToolActive"), &multiToolActive);
88
89 if (multiToolActive)
90 mCurrentTool = multiTool;
91 else
92 mCurrentTool = selectTool;
93
94 project.Bind(EVT_PROJECT_SETTINGS_CHANGE,
95 &ToolsToolBar::OnToolChanged, this);
96 }
97
~ToolsToolBar()98 ToolsToolBar::~ToolsToolBar()
99 {
100 static_assert(
101 ToolsToolBar::numTools <= ToolCodes::numTools,
102 "mismatch in number of tools" );
103 }
104
Get(AudacityProject & project)105 ToolsToolBar &ToolsToolBar::Get( AudacityProject &project )
106 {
107 auto &toolManager = ToolManager::Get( project );
108 return *static_cast<ToolsToolBar*>( toolManager.GetToolBar(ToolsBarID) );
109 }
110
Get(const AudacityProject & project)111 const ToolsToolBar &ToolsToolBar::Get( const AudacityProject &project )
112 {
113 return Get( const_cast<AudacityProject&>( project )) ;
114 }
115
RegenerateTooltips()116 void ToolsToolBar::RegenerateTooltips()
117 {
118
119 // JKC:
120 // Under Win98 Tooltips appear to be buggy, when you have a lot of
121 // tooltip messages flying around. I found that just creating a
122 // twelfth tooltip caused Audacity to crash when it tried to show
123 // any tooltip.
124 //
125 // Win98 does NOT recover from this crash - for any application which is
126 // using tooltips will also crash thereafter... so you must reboot.
127 // Rather weird.
128 //
129 // Getting windows to process more of its stacked up messages seems
130 // to workaround the problem. The problem is not fully understood though
131 // (as of April 2003).
132
133 // Vaughan, October 2003: Now we're crashing on Win2K if
134 // "Quit when closing last window" is unchecked, when we come back
135 // through here, on either of the wxSafeYield calls.
136 // James confirms that commenting them out does not cause his original problem
137 // to reappear, so they're commented out now.
138 // wxSafeYield(); //Deal with some queued up messages...
139
140 #if wxUSE_TOOLTIPS
141
142 using namespace ToolCodes;
143
144 static const struct Entry {
145 int tool;
146 CommandID commandName;
147 TranslatableString untranslatedLabel;
148 } table[] = {
149 { selectTool, wxT("SelectTool"), XO("Selection Tool") },
150 { envelopeTool, wxT("EnvelopeTool"), XO("Envelope Tool") },
151 { zoomTool, wxT("ZoomTool"), XO("Zoom Tool") },
152 { drawTool, wxT("DrawTool"), XO("Draw Tool") },
153 { multiTool, wxT("MultiTool"), XO("Multi-Tool") },
154 };
155
156 for (const auto &entry : table) {
157 ComponentInterfaceSymbol command{
158 entry.commandName, entry.untranslatedLabel };
159 ToolBar::SetButtonToolTip( mProject,
160 *mTool[entry.tool], &command, 1u );
161 }
162
163 #endif
164
165 // wxSafeYield();
166 return;
167 }
168
UpdatePrefs()169 void ToolsToolBar::UpdatePrefs()
170 {
171 RegenerateTooltips();
172 ToolBar::UpdatePrefs();
173 }
174
MakeTool(ToolsToolBar * pBar,teBmps eTool,int id,const TranslatableString & label)175 AButton * ToolsToolBar::MakeTool(
176 ToolsToolBar *pBar, teBmps eTool,
177 int id, const TranslatableString &label)
178 {
179 AButton *button = ToolBar::MakeButton(pBar,
180 bmpRecoloredUpSmall,
181 bmpRecoloredDownSmall,
182 bmpRecoloredUpHiliteSmall,
183 bmpRecoloredDownSmall, // Not bmpRecoloredHiliteSmall as down is inactive.
184 eTool, eTool, eTool,
185 wxWindowID(id + FirstToolID),
186 wxDefaultPosition, true,
187 theTheme.ImageSize( bmpRecoloredUpSmall ));
188 button->SetLabel( label );
189 pBar->mToolSizer->Add( button );
190 return button;
191 }
192
193
Populate()194 void ToolsToolBar::Populate()
195 {
196 SetBackgroundColour( theTheme.Colour( clrMedium ) );
197 MakeButtonBackgroundsSmall();
198
199 Add(mToolSizer = safenew wxGridSizer(2, 3, 1, 1));
200
201 /* Tools */
202 using namespace ToolCodes;
203 mTool[ selectTool ] = MakeTool( this, bmpIBeam, selectTool, XO("Selection Tool") );
204 mTool[ envelopeTool ] = MakeTool( this, bmpEnvelope, envelopeTool, XO("Envelope Tool") );
205 mTool[ drawTool ] = MakeTool( this, bmpDraw, drawTool, XO("Draw Tool") );
206 mTool[ zoomTool ] = MakeTool( this, bmpZoom, zoomTool, XO("Zoom Tool") );
207 mTool[ multiTool ] = MakeTool( this, bmpMulti, multiTool, XO("Multi-Tool") );
208
209 DoToolChanged();
210
211 RegenerateTooltips();
212 }
213
OnTool(wxCommandEvent & evt)214 void ToolsToolBar::OnTool(wxCommandEvent & evt)
215 {
216 // This will cause callback to OnToolChanged
217 auto iTool = evt.GetId() - ToolCodes::firstTool - FirstToolID;
218 auto pButton = mTool[iTool];
219 if (pButton->IsDown())
220 ProjectSettings::Get( mProject ).SetTool( iTool );
221 else
222 // Don't stay up
223 pButton->PushDown();
224 }
225
OnToolChanged(wxCommandEvent & evt)226 void ToolsToolBar::OnToolChanged(wxCommandEvent &evt)
227 {
228 evt.Skip(); // Let other listeners hear the event too
229 if (evt.GetInt() != ProjectSettings::ChangedTool)
230 return;
231 DoToolChanged();
232 ProjectWindow::Get( mProject ).RedrawProject();
233 }
234
DoToolChanged()235 void ToolsToolBar::DoToolChanged()
236 {
237 auto &projectSettings = ProjectSettings::Get( mProject );
238 using namespace ToolCodes;
239 mCurrentTool = projectSettings.GetTool() - firstTool;
240 for (int i = 0; i < numTools; i++)
241 if (i == mCurrentTool)
242 mTool[i]->PushDown();
243 else
244 mTool[i]->PopUp();
245
246 gPrefs->Write(wxT("/GUI/ToolBars/Tools/MultiToolActive"),
247 mTool[multiTool]->IsDown());
248 gPrefs->Flush();
249 }
250
Create(wxWindow * parent)251 void ToolsToolBar::Create(wxWindow * parent)
252 {
253 ToolBar::Create(parent);
254 UpdatePrefs();
255 }
256
257 static RegisteredToolbarFactory factory{ ToolsBarID,
__anon072cb6330102( )258 []( AudacityProject &project ){
259 return ToolBar::Holder{ safenew ToolsToolBar{ project } }; }
260 };
261
262 namespace {
263 AttachedToolBarMenuItem sAttachment{
264 /* i18n-hint: Clicking this menu item shows a toolbar
265 that has some tools in it */
266 ToolsBarID, wxT("ShowToolsTB"), XXO("T&ools Toolbar"),
267 };
268 }
269
270 // Following code injects menu items for changing the current tool
271
272 #include "../TrackPanel.h"
273
274 // private helper classes and functions
275 namespace {
276
277 /// Called by handlers that set tools.
SetTool(AudacityProject & project,int tool)278 void SetTool(AudacityProject &project, int tool)
279 {
280 auto toolbar = &ToolsToolBar::Get( project );
281 if (toolbar) {
282 ProjectSettings::Get(project).SetTool(tool);
283 TrackPanel::Get( project ).Refresh(false);
284 }
285 }
286
287 }
288
289 /// Namespace for functions for View Toolbar menu
290 namespace ToolActions {
291
292 // exported helper functions
293 // none
294
295 // Menu handler functions
296
297 struct Handler : CommandHandlerObject {
298 /// Handler to set the select tool active
OnSelectToolToolActions::Handler299 void OnSelectTool(const CommandContext &context)
300 {
301 SetTool(context.project, ToolCodes::selectTool);
302 }
303
304 /// Handler to set the Envelope tool active
OnEnvelopeToolToolActions::Handler305 void OnEnvelopeTool(const CommandContext &context)
306 {
307 SetTool(context.project, ToolCodes::envelopeTool);
308 }
309
OnDrawToolToolActions::Handler310 void OnDrawTool(const CommandContext &context)
311 {
312 SetTool(context.project, ToolCodes::drawTool);
313 }
314
315 /// Handler to set the Zoom tool active
OnZoomToolToolActions::Handler316 void OnZoomTool(const CommandContext &context)
317 {
318 SetTool(context.project, ToolCodes::zoomTool);
319 }
320
OnMultiToolToolActions::Handler321 void OnMultiTool(const CommandContext &context)
322 {
323 SetTool(context.project, ToolCodes::multiTool);
324 }
325
OnPrevToolToolActions::Handler326 void OnPrevTool(const CommandContext &context)
327 {
328 auto &project = context.project;
329 auto &trackPanel = TrackPanel::Get( project );
330 auto &settings = ProjectSettings::Get( project );
331
332 settings.SetTool(
333 (settings.GetTool() + (ToolCodes::numTools - 1 )) % ToolCodes::numTools);
334 trackPanel.Refresh(false);
335 }
336
OnNextToolToolActions::Handler337 void OnNextTool(const CommandContext &context)
338 {
339 auto &project = context.project;
340 auto &trackPanel = TrackPanel::Get( project );
341 auto &settings = ProjectSettings::Get( project );
342
343 settings.SetTool( (settings.GetTool() + 1) % ToolCodes::numTools );
344 trackPanel.Refresh(false);
345 }
346
347 }; // struct Handler
348
findCommandHandler(AudacityProject &)349 static CommandHandlerObject &findCommandHandler(AudacityProject &) {
350 // Handler is not stateful. Doesn't need a factory registered with
351 // AudacityProject.
352 static ToolActions::Handler instance;
353 return instance;
354 };
355
356 #define FN(X) (& ToolActions::Handler :: X)
357
358 using namespace MenuTable;
ExtraToolsMenu()359 BaseItemSharedPtr ExtraToolsMenu()
360 {
361 static BaseItemSharedPtr menu{
362 ( FinderScope{ findCommandHandler },
363 Menu( wxT("Tools"), XXO("T&ools"),
364 Command( wxT("SelectTool"), XXO("&Selection Tool"), FN(OnSelectTool),
365 AlwaysEnabledFlag, wxT("F1") ),
366 Command( wxT("EnvelopeTool"), XXO("&Envelope Tool"),
367 FN(OnEnvelopeTool), AlwaysEnabledFlag, wxT("F2") ),
368 Command( wxT("DrawTool"), XXO("&Draw Tool"), FN(OnDrawTool),
369 AlwaysEnabledFlag, wxT("F3") ),
370 Command( wxT("ZoomTool"), XXO("&Zoom Tool"), FN(OnZoomTool),
371 AlwaysEnabledFlag, wxT("F4") ),
372 Command( wxT("MultiTool"), XXO("&Multi Tool"), FN(OnMultiTool),
373 AlwaysEnabledFlag, wxT("F6") ),
374 Command( wxT("PrevTool"), XXO("&Previous Tool"), FN(OnPrevTool),
375 AlwaysEnabledFlag, wxT("A") ),
376 Command( wxT("NextTool"), XXO("&Next Tool"), FN(OnNextTool),
377 AlwaysEnabledFlag, wxT("D") )
378 ) ) };
379 return menu;
380 }
381
382 #undef FN
383
384 AttachedItem sAttachment2{
385 wxT("Optional/Extra/Part1"),
386 Shared( ExtraToolsMenu() )
387 };
388 }
389