/********************************************************************** Audacity: A Digital Audio Editor ToolsToolBar.cpp Dominic Mazzoni Shane T. Mueller Leland Lucius See ToolsToolBar.h for details *******************************************************************//*! \class ToolsToolBar \brief A kind of ToolBar with Tools on it. This class, which is a child of Toolbar, creates the window containing the tool selection (ibeam, envelope, move, zoom). The window can be embedded within a normal project window, or within a ToolBarFrame. All of the controls in this window were custom-written for Audacity - they are not native controls on any platform - however, it is intended that the images could be easily replaced to allow "skinning" or just customization to match the look and feel of each platform. \see \ref Themability *//*******************************************************************/ #include "../Audacity.h" #include "ToolsToolBar.h" #include "ToolManager.h" // For compilers that support precompilation, includes "wx/wx.h". #include #include // for wxUSE_* macros #ifndef WX_PRECOMP #include #include #include #include #endif #include #include "../Prefs.h" #include "../AllThemeResources.h" #include "../ImageManipulation.h" #include "../Project.h" #include "../ProjectSettings.h" #include "../ProjectWindow.h" #include "../tracks/ui/Scrubbing.h" #include "../widgets/AButton.h" IMPLEMENT_CLASS(ToolsToolBar, ToolBar); //////////////////////////////////////////////////////////// /// Methods for ToolsToolBar //////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(ToolsToolBar, ToolBar) EVT_COMMAND_RANGE(ToolCodes::firstTool + FirstToolID, ToolCodes::lastTool + FirstToolID, wxEVT_COMMAND_BUTTON_CLICKED, ToolsToolBar::OnTool) END_EVENT_TABLE() //Standard constructor ToolsToolBar::ToolsToolBar( AudacityProject &project ) : ToolBar(project, ToolsBarID, XO("Tools"), wxT("Tools")) { using namespace ToolCodes; //Read the following wxASSERTs as documentating a design decision wxASSERT( selectTool == selectTool - firstTool ); wxASSERT( envelopeTool == envelopeTool - firstTool ); wxASSERT( slideTool == slideTool - firstTool ); wxASSERT( zoomTool == zoomTool - firstTool ); wxASSERT( drawTool == drawTool - firstTool ); wxASSERT( multiTool == multiTool - firstTool ); bool multiToolActive = false; gPrefs->Read(wxT("/GUI/ToolBars/Tools/MultiToolActive"), &multiToolActive); if (multiToolActive) mCurrentTool = multiTool; else mCurrentTool = selectTool; } ToolsToolBar::~ToolsToolBar() { static_assert( ToolsToolBar::numTools == ToolCodes::numTools, "mismatch in number of tools" ); } ToolsToolBar &ToolsToolBar::Get( AudacityProject &project ) { auto &toolManager = ToolManager::Get( project ); return *static_cast( toolManager.GetToolBar(ToolsBarID) ); } const ToolsToolBar &ToolsToolBar::Get( const AudacityProject &project ) { return Get( const_cast( project )) ; } void ToolsToolBar::RegenerateTooltips() { // JKC: // Under Win98 Tooltips appear to be buggy, when you have a lot of // tooltip messages flying around. I found that just creating a // twelfth tooltip caused Audacity to crash when it tried to show // any tooltip. // // Win98 does NOT recover from this crash - for any application which is // using tooltips will also crash thereafter... so you must reboot. // Rather weird. // // Getting windows to process more of its stacked up messages seems // to workaround the problem. The problem is not fully understood though // (as of April 2003). // Vaughan, October 2003: Now we're crashing on Win2K if // "Quit when closing last window" is unchecked, when we come back // through here, on either of the wxSafeYield calls. // James confirms that commenting them out does not cause his original problem // to reappear, so they're commented out now. // wxSafeYield(); //Deal with some queued up messages... #if wxUSE_TOOLTIPS using namespace ToolCodes; static const struct Entry { int tool; CommandID commandName; TranslatableString untranslatedLabel; } table[] = { { selectTool, wxT("SelectTool"), XO("Selection Tool") }, { envelopeTool, wxT("EnvelopeTool"), XO("Envelope Tool") }, { slideTool, wxT("TimeShiftTool"), XO("Time Shift Tool") }, { zoomTool, wxT("ZoomTool"), XO("Zoom Tool") }, { drawTool, wxT("DrawTool"), XO("Draw Tool") }, { multiTool, wxT("MultiTool"), XO("Multi Tool") }, }; for (const auto &entry : table) { ComponentInterfaceSymbol command{ entry.commandName, entry.untranslatedLabel }; ToolBar::SetButtonToolTip( mProject, *mTool[entry.tool], &command, 1u ); } #endif // wxSafeYield(); return; } void ToolsToolBar::UpdatePrefs() { RegenerateTooltips(); ToolBar::UpdatePrefs(); } AButton * ToolsToolBar::MakeTool( ToolsToolBar *pBar, teBmps eTool, int id, const TranslatableString &label) { AButton *button = ToolBar::MakeButton(pBar, bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredUpHiliteSmall, bmpRecoloredDownSmall, // Not bmpRecoloredHiliteSmall as down is inactive. eTool, eTool, eTool, wxWindowID(id + FirstToolID), wxDefaultPosition, true, theTheme.ImageSize( bmpRecoloredUpSmall )); button->SetLabel( label ); pBar->mToolSizer->Add( button ); return button; } void ToolsToolBar::Populate() { SetBackgroundColour( theTheme.Colour( clrMedium ) ); MakeButtonBackgroundsSmall(); Add(mToolSizer = safenew wxGridSizer(2, 3, 1, 1)); /* Tools */ using namespace ToolCodes; mTool[ selectTool ] = MakeTool( this, bmpIBeam, selectTool, XO("Selection Tool") ); mTool[ envelopeTool ] = MakeTool( this, bmpEnvelope, envelopeTool, XO("Envelope Tool") ); mTool[ drawTool ] = MakeTool( this, bmpDraw, drawTool, XO("Draw Tool") ); mTool[ zoomTool ] = MakeTool( this, bmpZoom, zoomTool, XO("Zoom Tool") ); mTool[ slideTool ] = MakeTool( this, bmpTimeShift, slideTool, XO("Slide Tool") ); mTool[ multiTool ] = MakeTool( this, bmpMulti, multiTool, XO("Multi Tool") ); mTool[mCurrentTool]->PushDown(); RegenerateTooltips(); } /// Gets the currently active tool /// In Multi-mode this might not return the multi-tool itself /// since the active tool may be changed by what you hover over. int ToolsToolBar::GetCurrentTool() const { return mCurrentTool; } /// Sets the currently active tool /// @param tool - The index of the tool to be used. void ToolsToolBar::SetCurrentTool(int tool) { //In multi-mode the current tool is shown by the //cursor icon. The buttons are not updated. using namespace ToolCodes; bool leavingMulticlipMode = IsDown(multiTool) && tool != multiTool; if (leavingMulticlipMode) mTool[multiTool]->PopUp(); if (tool != mCurrentTool || leavingMulticlipMode) { mTool[mCurrentTool]->PopUp(); mCurrentTool=tool; mTool[mCurrentTool]->PushDown(); } //JKC: ANSWER-ME: Why is this required? //msmeyer: I think it isn't, we leave it out for 1.3.1 (beta), and // we'll see if anyone complains. //for ( auto pProject : AllProjects{} ) // ProjectWindow::Get( *pProject ).RedrawProject(); gPrefs->Write(wxT("/GUI/ToolBars/Tools/MultiToolActive"), IsDown(multiTool)); gPrefs->Flush(); ProjectSettings::Get( mProject ).SetTool( mCurrentTool ); } bool ToolsToolBar::IsDown(int tool) const { return mTool[tool]->IsDown(); } int ToolsToolBar::GetDownTool() { int tool; using namespace ToolCodes; for (tool = firstTool; tool <= lastTool; tool++) if (IsDown(tool)) return tool; return firstTool; // Should never happen } void ToolsToolBar::OnTool(wxCommandEvent & evt) { using namespace ToolCodes; mCurrentTool = evt.GetId() - firstTool - FirstToolID; for (int i = 0; i < numTools; i++) if (i == mCurrentTool) mTool[i]->PushDown(); else mTool[i]->PopUp(); for ( auto pProject : AllProjects{} ) ProjectWindow::Get( *pProject ).RedrawProject(); gPrefs->Write(wxT("/GUI/ToolBars/Tools/MultiToolActive"), IsDown(multiTool)); gPrefs->Flush(); ProjectSettings::Get( mProject ).SetTool( mCurrentTool ); } void ToolsToolBar::Create(wxWindow * parent) { ToolBar::Create(parent); UpdatePrefs(); } static RegisteredToolbarFactory factory{ ToolsBarID, []( AudacityProject &project ){ return ToolBar::Holder{ safenew ToolsToolBar{ project } }; } };