@@ -335,7 +335,7 @@ private: | |||||
m.addItem (1, "Use one thread per ball", true, ! isUsingPool); | m.addItem (1, "Use one thread per ball", true, ! isUsingPool); | ||||
m.addItem (2, "Use a thread pool", true, isUsingPool); | m.addItem (2, "Use a thread pool", true, isUsingPool); | ||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (&controlButton), | |||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (controlButton), | |||||
ModalCallbackFunction::forComponent (menuItemChosenCallback, this)); | ModalCallbackFunction::forComponent (menuItemChosenCallback, this)); | ||||
} | } | ||||
@@ -359,8 +359,6 @@ enum | |||||
recentProjectsBaseID = 100, | recentProjectsBaseID = 100, | ||||
openWindowsBaseID = 300, | openWindowsBaseID = 300, | ||||
activeDocumentsBaseID = 400, | activeDocumentsBaseID = 400, | ||||
colourSchemeBaseID = 1000, | |||||
codeEditorColourSchemeBaseID = 1500, | |||||
showPathsID = 1999, | showPathsID = 1999, | ||||
examplesBaseID = 2000 | examplesBaseID = 2000 | ||||
}; | }; | ||||
@@ -496,16 +494,24 @@ void ProjucerApplication::createBuildMenu (PopupMenu& menu) | |||||
void ProjucerApplication::createColourSchemeItems (PopupMenu& menu) | void ProjucerApplication::createColourSchemeItems (PopupMenu& menu) | ||||
{ | { | ||||
PopupMenu colourSchemes; | |||||
PopupMenu colourSchemeMenu; | |||||
colourSchemes.addItem (colourSchemeBaseID + 0, "Dark", true, selectedColourSchemeIndex == 0); | |||||
colourSchemes.addItem (colourSchemeBaseID + 1, "Grey", true, selectedColourSchemeIndex == 1); | |||||
colourSchemes.addItem (colourSchemeBaseID + 2, "Light", true, selectedColourSchemeIndex == 2); | |||||
colourSchemeMenu.addItem (PopupMenu::Item ("Dark") | |||||
.setTicked (selectedColourSchemeIndex == 0) | |||||
.setAction ([this] { setColourScheme (0, true); updateEditorColourSchemeIfNeeded(); })); | |||||
menu.addSubMenu ("Colour Scheme", colourSchemes); | |||||
colourSchemeMenu.addItem (PopupMenu::Item ("Grey") | |||||
.setTicked (selectedColourSchemeIndex == 1) | |||||
.setAction ([this] { setColourScheme (1, true); updateEditorColourSchemeIfNeeded(); })); | |||||
colourSchemeMenu.addItem (PopupMenu::Item ("Light") | |||||
.setTicked (selectedColourSchemeIndex == 2) | |||||
.setAction ([this] { setColourScheme (2, true); updateEditorColourSchemeIfNeeded(); })); | |||||
menu.addSubMenu ("Colour Scheme", colourSchemeMenu); | |||||
//========================================================================== | //========================================================================== | ||||
PopupMenu editorColourSchemes; | |||||
PopupMenu editorColourSchemeMenu; | |||||
auto& appearanceSettings = getAppSettings().appearance; | auto& appearanceSettings = getAppSettings().appearance; | ||||
@@ -513,21 +519,22 @@ void ProjucerApplication::createColourSchemeItems (PopupMenu& menu) | |||||
auto schemes = appearanceSettings.getPresetSchemes(); | auto schemes = appearanceSettings.getPresetSchemes(); | ||||
auto i = 0; | auto i = 0; | ||||
for (auto s : schemes) | |||||
for (auto& s : schemes) | |||||
{ | { | ||||
editorColourSchemes.addItem (codeEditorColourSchemeBaseID + i, s, | |||||
editorColourSchemeWindow == nullptr, | |||||
selectedEditorColourSchemeIndex == i); | |||||
editorColourSchemeMenu.addItem (PopupMenu::Item (s) | |||||
.setEnabled (editorColourSchemeWindow == nullptr) | |||||
.setTicked (selectedEditorColourSchemeIndex == i) | |||||
.setAction ([this, i] { setEditorColourScheme (i, true); })); | |||||
++i; | ++i; | ||||
} | } | ||||
numEditorColourSchemes = i; | |||||
editorColourSchemes.addSeparator(); | |||||
editorColourSchemes.addItem (codeEditorColourSchemeBaseID + numEditorColourSchemes, | |||||
"Create...", editorColourSchemeWindow == nullptr); | |||||
editorColourSchemeMenu.addSeparator(); | |||||
editorColourSchemeMenu.addItem (PopupMenu::Item ("Create...") | |||||
.setEnabled (editorColourSchemeWindow == nullptr) | |||||
.setAction ([this] { showEditorColourSchemeWindow(); })); | |||||
menu.addSubMenu ("Editor Colour Scheme", editorColourSchemes); | |||||
menu.addSubMenu ("Editor Colour Scheme", editorColourSchemeMenu); | |||||
} | } | ||||
void ProjucerApplication::createWindowMenu (PopupMenu& menu) | void ProjucerApplication::createWindowMenu (PopupMenu& menu) | ||||
@@ -538,14 +545,11 @@ void ProjucerApplication::createWindowMenu (PopupMenu& menu) | |||||
menu.addSeparator(); | menu.addSeparator(); | ||||
int counter = 0; | int counter = 0; | ||||
for (auto* window : mainWindowList.windows) | for (auto* window : mainWindowList.windows) | ||||
{ | |||||
if (window != nullptr) | if (window != nullptr) | ||||
{ | |||||
if (auto* project = window->getProject()) | if (auto* project = window->getProject()) | ||||
menu.addItem (openWindowsBaseID + counter++, project->getProjectNameString()); | menu.addItem (openWindowsBaseID + counter++, project->getProjectNameString()); | ||||
} | |||||
} | |||||
menu.addSeparator(); | menu.addSeparator(); | ||||
menu.addCommandItem (commandManager.get(), CommandIDs::closeAllWindows); | menu.addCommandItem (commandManager.get(), CommandIDs::closeAllWindows); | ||||
@@ -956,19 +960,6 @@ void ProjucerApplication::handleMainMenuCommand (int menuItemID) | |||||
else | else | ||||
jassertfalse; | jassertfalse; | ||||
} | } | ||||
else if (menuItemID >= colourSchemeBaseID && menuItemID < (colourSchemeBaseID + 3)) | |||||
{ | |||||
setColourScheme (menuItemID - colourSchemeBaseID, true); | |||||
updateEditorColourSchemeIfNeeded(); | |||||
} | |||||
else if (menuItemID >= codeEditorColourSchemeBaseID && menuItemID < (codeEditorColourSchemeBaseID + numEditorColourSchemes)) | |||||
{ | |||||
setEditorColourScheme (menuItemID - codeEditorColourSchemeBaseID, true); | |||||
} | |||||
else if (menuItemID == (codeEditorColourSchemeBaseID + numEditorColourSchemes)) | |||||
{ | |||||
showEditorColourSchemeWindow(); | |||||
} | |||||
else if (menuItemID == showPathsID) | else if (menuItemID == showPathsID) | ||||
{ | { | ||||
showPathsWindow (true); | showPathsWindow (true); | ||||
@@ -208,7 +208,7 @@ private: | |||||
ChildProcess makeProcess; | ChildProcess makeProcess; | ||||
#endif | #endif | ||||
int selectedColourSchemeIndex = 0, selectedEditorColourSchemeIndex = 0, numEditorColourSchemes = 0; | |||||
int selectedColourSchemeIndex = 0, selectedEditorColourSchemeIndex = 0; | |||||
//============================================================================== | //============================================================================== | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjucerApplication) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjucerApplication) | ||||
@@ -218,112 +218,114 @@ private: | |||||
void showCopyModeMenu() | void showCopyModeMenu() | ||||
{ | { | ||||
PopupMenu m; | PopupMenu m; | ||||
m.addItem (1, "Set all modules to copy locally"); | |||||
m.addItem (2, "Set all modules to not copy locally"); | |||||
auto res = m.showAt (&setCopyModeButton); | |||||
m.addItem (PopupMenu::Item ("Set all modules to copy locally") | |||||
.setAction ([&] { project.getEnabledModules().setLocalCopyModeForAllModules (true); })); | |||||
if (res != 0) | |||||
project.getEnabledModules().setLocalCopyModeForAllModules (res == 1); | |||||
m.addItem (PopupMenu::Item ("Set all modules to not copy locally") | |||||
.setAction ([&] { project.getEnabledModules().setLocalCopyModeForAllModules (false); })); | |||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (setCopyModeButton)); | |||||
} | } | ||||
void showGlobalPathsMenu() | |||||
static void setAllModulesToUseGlobalPaths (Project& project, bool useGlobal) | |||||
{ | { | ||||
auto areAnyModulesSelected = (list.getNumSelectedRows() > 0); | |||||
auto& moduleList = project.getEnabledModules(); | |||||
PopupMenu m; | |||||
m.addItem (1, "Set all modules to use global paths"); | |||||
m.addItem (2, "Set all modules to not use global paths"); | |||||
m.addItem (3, "Set selected modules to use global paths", areAnyModulesSelected); | |||||
m.addItem (4, "Set selected modules to not use global paths", areAnyModulesSelected); | |||||
for (auto id : moduleList.getAllModules()) | |||||
moduleList.getShouldUseGlobalPathValue (id).setValue (useGlobal); | |||||
} | |||||
auto res = m.showAt (&globalPathsButton); | |||||
static void setSelectedModulesToUseGlobalPaths (Project& project, SparseSet<int> selected, bool useGlobal) | |||||
{ | |||||
auto& moduleList = project.getEnabledModules(); | |||||
if (res != 0) | |||||
{ | |||||
auto enableGlobalPaths = (res % 2 == 1); | |||||
for (int i = 0; i < selected.size(); ++i) | |||||
moduleList.getShouldUseGlobalPathValue (moduleList.getModuleID (selected[i])).setValue (useGlobal); | |||||
} | |||||
auto& moduleList = project.getEnabledModules(); | |||||
void showGlobalPathsMenu() | |||||
{ | |||||
PopupMenu m; | |||||
if (res < 3) | |||||
{ | |||||
auto moduleIDs = moduleList.getAllModules(); | |||||
m.addItem (PopupMenu::Item ("Set all modules to use global paths") | |||||
.setAction ([&] { setAllModulesToUseGlobalPaths (project, true); })); | |||||
for (auto id : moduleIDs) | |||||
moduleList.getShouldUseGlobalPathValue (id).setValue (enableGlobalPaths); | |||||
} | |||||
else | |||||
{ | |||||
auto selected = list.getSelectedRows(); | |||||
m.addItem (PopupMenu::Item ("Set all modules to not use global paths") | |||||
.setAction ([&] { setAllModulesToUseGlobalPaths (project, false); })); | |||||
for (int i = 0; i < selected.size(); ++i) | |||||
moduleList.getShouldUseGlobalPathValue (moduleList.getModuleID (selected[i])).setValue (enableGlobalPaths); | |||||
} | |||||
} | |||||
m.addItem (PopupMenu::Item ("Set selected modules to use global paths") | |||||
.setEnabled (list.getNumSelectedRows() > 0) | |||||
.setAction ([&] { setSelectedModulesToUseGlobalPaths (project, list.getSelectedRows(), true); })); | |||||
m.addItem (PopupMenu::Item ("Set selected modules to not use global paths") | |||||
.setEnabled (list.getNumSelectedRows() > 0) | |||||
.setAction ([&] { setSelectedModulesToUseGlobalPaths (project, list.getSelectedRows(), false); })); | |||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (globalPathsButton)); | |||||
} | } | ||||
void showSetPathsMenu() | void showSetPathsMenu() | ||||
{ | { | ||||
enum | |||||
{ | |||||
copyPathsToAllModulesID = 1, | |||||
copyPathsID, | |||||
pastePathsID | |||||
}; | |||||
auto& moduleList = project.getEnabledModules(); | |||||
auto moduleToCopy = moduleList.getModuleID (list.getSelectedRow()); | |||||
PopupMenu m; | |||||
auto moduleToCopy = project.getEnabledModules().getModuleID (list.getSelectedRow()); | |||||
if (moduleToCopy.isNotEmpty()) | if (moduleToCopy.isNotEmpty()) | ||||
{ | { | ||||
PopupMenu m; | |||||
m.addItem (copyPathsToAllModulesID, "Copy the paths from the module '" + moduleToCopy + "' to all other modules"); | |||||
m.addItem (copyPathsID, "Copy paths from selected module", list.getNumSelectedRows() == 1); | |||||
m.addItem (pastePathsID, "Paste paths to selected modules", ! modulePathClipboard.empty()); | |||||
int res = m.showAt (©PathButton); | |||||
if (res == copyPathsToAllModulesID) | |||||
{ | |||||
for (Project::ExporterIterator exporter (project); exporter.next();) | |||||
{ | |||||
for (int i = 0; i < moduleList.getNumModules(); ++i) | |||||
{ | |||||
auto modID = moduleList.getModuleID (i); | |||||
if (modID != moduleToCopy) | |||||
exporter->getPathForModuleValue (modID) = exporter->getPathForModuleValue (moduleToCopy).get(); | |||||
} | |||||
} | |||||
} | |||||
else if (res == copyPathsID) | |||||
{ | |||||
modulePathClipboard.clear(); | |||||
for (Project::ExporterIterator exporter (project); exporter.next();) | |||||
modulePathClipboard[exporter->getName()] = exporter->getPathForModuleValue (moduleToCopy).get(); | |||||
} | |||||
else if (res == pastePathsID) | |||||
{ | |||||
for (int selectionId = 0; selectionId < list.getNumSelectedRows(); ++selectionId) | |||||
{ | |||||
auto rowNumber = list.getSelectedRow (selectionId); | |||||
auto modID = moduleList.getModuleID (rowNumber); | |||||
for (Project::ExporterIterator exporter (project); exporter.next();) | |||||
exporter->getPathForModuleValue (modID) = modulePathClipboard[exporter->getName()]; | |||||
} | |||||
} | |||||
list.repaint(); | |||||
m.addItem (PopupMenu::Item ("Copy the paths from the module '" + moduleToCopy + "' to all other modules") | |||||
.setAction ([this, moduleToCopy] | |||||
{ | |||||
auto& moduleList = project.getEnabledModules(); | |||||
for (Project::ExporterIterator exporter (project); exporter.next();) | |||||
{ | |||||
for (int i = 0; i < moduleList.getNumModules(); ++i) | |||||
{ | |||||
auto modID = moduleList.getModuleID (i); | |||||
if (modID != moduleToCopy) | |||||
exporter->getPathForModuleValue (modID) = exporter->getPathForModuleValue (moduleToCopy).get(); | |||||
} | |||||
} | |||||
list.repaint(); | |||||
})); | |||||
m.addItem (PopupMenu::Item ("Copy paths from selected module") | |||||
.setEnabled (list.getNumSelectedRows() == 1) | |||||
.setAction ([this, moduleToCopy] | |||||
{ | |||||
modulePathClipboard.clear(); | |||||
for (Project::ExporterIterator exporter (project); exporter.next();) | |||||
modulePathClipboard[exporter->getName()] = exporter->getPathForModuleValue (moduleToCopy).get(); | |||||
list.repaint(); | |||||
})); | |||||
m.addItem (PopupMenu::Item ("Paste paths to selected modules") | |||||
.setEnabled (! modulePathClipboard.empty()) | |||||
.setAction ([this] | |||||
{ | |||||
for (int selectionId = 0; selectionId < list.getNumSelectedRows(); ++selectionId) | |||||
{ | |||||
auto rowNumber = list.getSelectedRow (selectionId); | |||||
auto modID = project.getEnabledModules().getModuleID (rowNumber); | |||||
for (Project::ExporterIterator exporter (project); exporter.next();) | |||||
exporter->getPathForModuleValue (modID) = modulePathClipboard[exporter->getName()]; | |||||
} | |||||
list.repaint(); | |||||
})); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
PopupMenu m; | |||||
m.addItem (1, "(Select a module in the list above to use this option)", false); | |||||
m.showAt (©PathButton); | |||||
m.addItem (PopupMenu::Item ("(Select a module in the list above to use this option)") | |||||
.setEnabled (false)); | |||||
} | } | ||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (copyPathButton)); | |||||
} | } | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModulesInformationComponent) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModulesInformationComponent) | ||||
@@ -311,7 +311,7 @@ void PluginListComponent::showOptionsMenu() | |||||
menu.addItem (10 + i, "Scan for new or updated " + format->getName() + " plug-ins"); | menu.addItem (10 + i, "Scan for new or updated " + format->getName() + " plug-ins"); | ||||
} | } | ||||
menu.showMenuAsync (PopupMenu::Options().withTargetComponent (&optionsButton), | |||||
menu.showMenuAsync (PopupMenu::Options().withTargetComponent (optionsButton), | |||||
ModalCallbackFunction::forComponent (optionsMenuStaticCallback, this)); | ModalCallbackFunction::forComponent (optionsMenuStaticCallback, this)); | ||||
} | } | ||||
@@ -121,6 +121,12 @@ | |||||
#define JUCE_CONSTEXPR | #define JUCE_CONSTEXPR | ||||
#endif | #endif | ||||
#if JUCE_MSVC && _MSC_VER < 1900 | |||||
#define JUCE_REF_QUALIFIER | |||||
#else | |||||
#define JUCE_REF_QUALIFIER & | |||||
#endif | |||||
#if (! JUCE_MSVC) && (! JUCE_CXX14_IS_AVAILABLE) | #if (! JUCE_MSVC) && (! JUCE_CXX14_IS_AVAILABLE) | ||||
namespace std | namespace std | ||||
{ | { | ||||
@@ -552,26 +552,22 @@ void TabbedButtonBar::setTabBackgroundColour (int tabIndex, Colour newColour) | |||||
} | } | ||||
} | } | ||||
void TabbedButtonBar::extraItemsMenuCallback (int result, TabbedButtonBar* bar) | |||||
{ | |||||
if (bar != nullptr && result > 0) | |||||
bar->setCurrentTabIndex (result - 1); | |||||
} | |||||
void TabbedButtonBar::showExtraItemsMenu() | void TabbedButtonBar::showExtraItemsMenu() | ||||
{ | { | ||||
PopupMenu m; | PopupMenu m; | ||||
Component::SafePointer<TabbedButtonBar> bar (this); | |||||
for (int i = 0; i < tabs.size(); ++i) | for (int i = 0; i < tabs.size(); ++i) | ||||
{ | { | ||||
auto* tab = tabs.getUnchecked(i); | auto* tab = tabs.getUnchecked(i); | ||||
if (! tab->button->isVisible()) | if (! tab->button->isVisible()) | ||||
m.addItem (i + 1, tab->name, true, i == currentTabIndex); | |||||
m.addItem (PopupMenu::Item (tab->name) | |||||
.setTicked (i == currentTabIndex) | |||||
.setAction ([this, bar, i] { if (bar != nullptr) setCurrentTabIndex (i); })); | |||||
} | } | ||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (extraTabsButton.get()), | |||||
ModalCallbackFunction::forComponent (extraItemsMenuCallback, this)); | |||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (extraTabsButton.get())); | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -364,7 +364,6 @@ private: | |||||
std::unique_ptr<Button> extraTabsButton; | std::unique_ptr<Button> extraTabsButton; | ||||
void showExtraItemsMenu(); | void showExtraItemsMenu(); | ||||
static void extraItemsMenuCallback (int, TabbedButtonBar*); | |||||
void updateTabPositions (bool animate); | void updateTabPositions (bool animate); | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TabbedButtonBar) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TabbedButtonBar) | ||||
@@ -1305,6 +1305,7 @@ void PopupMenu::clear() | |||||
//============================================================================== | //============================================================================== | ||||
PopupMenu::Item::Item() = default; | PopupMenu::Item::Item() = default; | ||||
PopupMenu::Item::Item (String t) : text (std::move (t)), itemID (-1) {} | |||||
#if JUCE_MSVC && _MSC_VER < 1900 // tedious VC2013 workaround | #if JUCE_MSVC && _MSC_VER < 1900 // tedious VC2013 workaround | ||||
PopupMenu::Item::Item (Item&& other) | PopupMenu::Item::Item (Item&& other) | ||||
@@ -1385,6 +1386,80 @@ PopupMenu::Item& PopupMenu::Item::operator= (const Item& other) | |||||
return *this; | return *this; | ||||
} | } | ||||
PopupMenu::Item& PopupMenu::Item::setTicked (bool shouldBeTicked) JUCE_REF_QUALIFIER noexcept | |||||
{ | |||||
isTicked = shouldBeTicked; | |||||
return *this; | |||||
} | |||||
PopupMenu::Item& PopupMenu::Item::setEnabled (bool shouldBeEnabled) JUCE_REF_QUALIFIER noexcept | |||||
{ | |||||
isEnabled = shouldBeEnabled; | |||||
return *this; | |||||
} | |||||
PopupMenu::Item& PopupMenu::Item::setAction (std::function<void()> newAction) JUCE_REF_QUALIFIER noexcept | |||||
{ | |||||
action = std::move (newAction); | |||||
return *this; | |||||
} | |||||
PopupMenu::Item& PopupMenu::Item::setID (int newID) JUCE_REF_QUALIFIER noexcept | |||||
{ | |||||
itemID = newID; | |||||
return *this; | |||||
} | |||||
PopupMenu::Item& PopupMenu::Item::setColour (Colour newColour) JUCE_REF_QUALIFIER noexcept | |||||
{ | |||||
colour = newColour; | |||||
return *this; | |||||
} | |||||
PopupMenu::Item& PopupMenu::Item::setCustomComponent (ReferenceCountedObjectPtr<CustomComponent> comp) JUCE_REF_QUALIFIER noexcept | |||||
{ | |||||
customComponent = comp; | |||||
return *this; | |||||
} | |||||
#if ! (JUCE_MSVC && _MSC_VER < 1900) // Gah.. no ref-qualifiers in VC2013... | |||||
PopupMenu::Item&& PopupMenu::Item::setTicked (bool shouldBeTicked) && noexcept | |||||
{ | |||||
isTicked = shouldBeTicked; | |||||
return std::move (*this); | |||||
} | |||||
PopupMenu::Item&& PopupMenu::Item::setEnabled (bool shouldBeEnabled) && noexcept | |||||
{ | |||||
isEnabled = shouldBeEnabled; | |||||
return std::move (*this); | |||||
} | |||||
PopupMenu::Item&& PopupMenu::Item::setAction (std::function<void()> newAction) && noexcept | |||||
{ | |||||
action = std::move (newAction); | |||||
return std::move (*this); | |||||
} | |||||
PopupMenu::Item&& PopupMenu::Item::setID (int newID) && noexcept | |||||
{ | |||||
itemID = newID; | |||||
return std::move (*this); | |||||
} | |||||
PopupMenu::Item&& PopupMenu::Item::setColour (Colour newColour) && noexcept | |||||
{ | |||||
colour = newColour; | |||||
return std::move (*this); | |||||
} | |||||
PopupMenu::Item&& PopupMenu::Item::setCustomComponent (ReferenceCountedObjectPtr<CustomComponent> comp) && noexcept | |||||
{ | |||||
customComponent = comp; | |||||
return std::move (*this); | |||||
} | |||||
#endif | |||||
void PopupMenu::addItem (Item newItem) | void PopupMenu::addItem (Item newItem) | ||||
{ | { | ||||
// An ID of 0 is used as a return value to indicate that the user | // An ID of 0 is used as a return value to indicate that the user | ||||
@@ -1403,10 +1478,8 @@ void PopupMenu::addItem (String itemText, std::function<void()> action) | |||||
void PopupMenu::addItem (String itemText, bool isActive, bool isTicked, std::function<void()> action) | void PopupMenu::addItem (String itemText, bool isActive, bool isTicked, std::function<void()> action) | ||||
{ | { | ||||
Item i; | |||||
i.text = std::move (itemText); | |||||
Item i (std::move (itemText)); | |||||
i.action = std::move (action); | i.action = std::move (action); | ||||
i.itemID = -1; | |||||
i.isEnabled = isActive; | i.isEnabled = isActive; | ||||
i.isTicked = isTicked; | i.isTicked = isTicked; | ||||
addItem (std::move (i)); | addItem (std::move (i)); | ||||
@@ -1414,8 +1487,7 @@ void PopupMenu::addItem (String itemText, bool isActive, bool isTicked, std::fun | |||||
void PopupMenu::addItem (int itemResultID, String itemText, bool isActive, bool isTicked) | void PopupMenu::addItem (int itemResultID, String itemText, bool isActive, bool isTicked) | ||||
{ | { | ||||
Item i; | |||||
i.text = std::move (itemText); | |||||
Item i (std::move (itemText)); | |||||
i.itemID = itemResultID; | i.itemID = itemResultID; | ||||
i.isEnabled = isActive; | i.isEnabled = isActive; | ||||
i.isTicked = isTicked; | i.isTicked = isTicked; | ||||
@@ -1442,8 +1514,7 @@ void PopupMenu::addItem (int itemResultID, String itemText, bool isActive, bool | |||||
void PopupMenu::addItem (int itemResultID, String itemText, bool isActive, | void PopupMenu::addItem (int itemResultID, String itemText, bool isActive, | ||||
bool isTicked, std::unique_ptr<Drawable> iconToUse) | bool isTicked, std::unique_ptr<Drawable> iconToUse) | ||||
{ | { | ||||
Item i; | |||||
i.text = std::move (itemText); | |||||
Item i (std::move (itemText)); | |||||
i.itemID = itemResultID; | i.itemID = itemResultID; | ||||
i.isEnabled = isActive; | i.isEnabled = isActive; | ||||
i.isTicked = isTicked; | i.isTicked = isTicked; | ||||
@@ -1477,8 +1548,7 @@ void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager, | |||||
void PopupMenu::addColouredItem (int itemResultID, String itemText, Colour itemTextColour, | void PopupMenu::addColouredItem (int itemResultID, String itemText, Colour itemTextColour, | ||||
bool isActive, bool isTicked, std::unique_ptr<Drawable> iconToUse) | bool isActive, bool isTicked, std::unique_ptr<Drawable> iconToUse) | ||||
{ | { | ||||
Item i; | |||||
i.text = std::move (itemText); | |||||
Item i (std::move (itemText)); | |||||
i.itemID = itemResultID; | i.itemID = itemResultID; | ||||
i.colour = itemTextColour; | i.colour = itemTextColour; | ||||
i.isEnabled = isActive; | i.isEnabled = isActive; | ||||
@@ -1490,8 +1560,7 @@ void PopupMenu::addColouredItem (int itemResultID, String itemText, Colour itemT | |||||
void PopupMenu::addColouredItem (int itemResultID, String itemText, Colour itemTextColour, | void PopupMenu::addColouredItem (int itemResultID, String itemText, Colour itemTextColour, | ||||
bool isActive, bool isTicked, const Image& iconToUse) | bool isActive, bool isTicked, const Image& iconToUse) | ||||
{ | { | ||||
Item i; | |||||
i.text = std::move (itemText); | |||||
Item i (std::move (itemText)); | |||||
i.itemID = itemResultID; | i.itemID = itemResultID; | ||||
i.colour = itemTextColour; | i.colour = itemTextColour; | ||||
i.isEnabled = isActive; | i.isEnabled = isActive; | ||||
@@ -1533,8 +1602,7 @@ void PopupMenu::addSubMenu (String subMenuName, PopupMenu subMenu, bool isActive | |||||
void PopupMenu::addSubMenu (String subMenuName, PopupMenu subMenu, bool isActive, | void PopupMenu::addSubMenu (String subMenuName, PopupMenu subMenu, bool isActive, | ||||
std::unique_ptr<Drawable> iconToUse, bool isTicked, int itemResultID) | std::unique_ptr<Drawable> iconToUse, bool isTicked, int itemResultID) | ||||
{ | { | ||||
Item i; | |||||
i.text = std::move (subMenuName); | |||||
Item i (std::move (subMenuName)); | |||||
i.itemID = itemResultID; | i.itemID = itemResultID; | ||||
i.isEnabled = isActive && (itemResultID != 0 || subMenu.getNumItems() > 0); | i.isEnabled = isActive && (itemResultID != 0 || subMenu.getNumItems() > 0); | ||||
i.subMenu.reset (new PopupMenu (std::move (subMenu))); | i.subMenu.reset (new PopupMenu (std::move (subMenu))); | ||||
@@ -1555,8 +1623,7 @@ void PopupMenu::addSeparator() | |||||
void PopupMenu::addSectionHeader (String title) | void PopupMenu::addSectionHeader (String title) | ||||
{ | { | ||||
Item i; | |||||
i.text = std::move (title); | |||||
Item i (std::move (title)); | |||||
i.isSectionHeader = true; | i.isSectionHeader = true; | ||||
addItem (std::move (i)); | addItem (std::move (i)); | ||||
} | } | ||||
@@ -1578,6 +1645,11 @@ PopupMenu::Options PopupMenu::Options::withTargetComponent (Component* comp) con | |||||
return o; | return o; | ||||
} | } | ||||
PopupMenu::Options PopupMenu::Options::withTargetComponent (Component& comp) const noexcept | |||||
{ | |||||
return withTargetComponent (&comp); | |||||
} | |||||
PopupMenu::Options PopupMenu::Options::withTargetScreenArea (Rectangle<int> area) const noexcept | PopupMenu::Options PopupMenu::Options::withTargetScreenArea (Rectangle<int> area) const noexcept | ||||
{ | { | ||||
Options o (*this); | Options o (*this); | ||||
@@ -116,6 +116,12 @@ public: | |||||
*/ | */ | ||||
Item(); | Item(); | ||||
/** Creates an item with the given text. | |||||
This constructor also initialises the itemID to -1, which makes it suitable for | |||||
creating lambda-based item actions. | |||||
*/ | |||||
Item (String text); | |||||
Item (const Item&); | Item (const Item&); | ||||
Item& operator= (const Item&); | Item& operator= (const Item&); | ||||
Item (Item&&); | Item (Item&&); | ||||
@@ -124,7 +130,11 @@ public: | |||||
/** The menu item's name. */ | /** The menu item's name. */ | ||||
String text; | String text; | ||||
/** The menu item's ID. This must not be 0 if you want the item to be triggerable! */ | |||||
/** The menu item's ID. | |||||
This must not be 0 if you want the item to be triggerable, but if you're attaching | |||||
an action callback to the item, you can set the itemID to -1 to indicate that it | |||||
isn't actively needed. | |||||
*/ | |||||
int itemID = 0; | int itemID = 0; | ||||
/** An optional function which should be invoked when this menu item is triggered. */ | /** An optional function which should be invoked when this menu item is triggered. */ | ||||
@@ -169,6 +179,34 @@ public: | |||||
/** True if this menu item is a section header. */ | /** True if this menu item is a section header. */ | ||||
bool isSectionHeader = false; | bool isSectionHeader = false; | ||||
/** Sets the isTicked flag (and returns a reference to this item to allow chaining). */ | |||||
Item& setTicked (bool shouldBeTicked = true) JUCE_REF_QUALIFIER noexcept; | |||||
/** Sets the isEnabled flag (and returns a reference to this item to allow chaining). */ | |||||
Item& setEnabled (bool shouldBeEnabled) JUCE_REF_QUALIFIER noexcept; | |||||
/** Sets the action property (and returns a reference to this item to allow chaining). */ | |||||
Item& setAction (std::function<void()> action) JUCE_REF_QUALIFIER noexcept; | |||||
/** Sets the itemID property (and returns a reference to this item to allow chaining). */ | |||||
Item& setID (int newID) JUCE_REF_QUALIFIER noexcept; | |||||
/** Sets the colour property (and returns a reference to this item to allow chaining). */ | |||||
Item& setColour (Colour) JUCE_REF_QUALIFIER noexcept; | |||||
/** Sets the customComponent property (and returns a reference to this item to allow chaining). */ | |||||
Item& setCustomComponent (ReferenceCountedObjectPtr<CustomComponent> customComponent) JUCE_REF_QUALIFIER noexcept; | |||||
#if ! (JUCE_MSVC && _MSC_VER < 1900) // Gah.. no ref-qualifiers in VC2013... | |||||
/** Sets the isTicked flag (and returns a reference to this item to allow chaining). */ | |||||
Item&& setTicked (bool shouldBeTicked = true) && noexcept; | |||||
/** Sets the isEnabled flag (and returns a reference to this item to allow chaining). */ | |||||
Item&& setEnabled (bool shouldBeEnabled) && noexcept; | |||||
/** Sets the action property (and returns a reference to this item to allow chaining). */ | |||||
Item&& setAction (std::function<void()> action) && noexcept; | |||||
/** Sets the itemID property (and returns a reference to this item to allow chaining). */ | |||||
Item&& setID (int newID) && noexcept; | |||||
/** Sets the colour property (and returns a reference to this item to allow chaining). */ | |||||
Item&& setColour (Colour) && noexcept; | |||||
/** Sets the customComponent property (and returns a reference to this item to allow chaining). */ | |||||
Item&& setCustomComponent (ReferenceCountedObjectPtr<CustomComponent> customComponent) && noexcept; | |||||
#endif | |||||
}; | }; | ||||
/** Adds an item to the menu. | /** Adds an item to the menu. | ||||
@@ -410,6 +448,7 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
Options withTargetComponent (Component* targetComponent) const noexcept; | Options withTargetComponent (Component* targetComponent) const noexcept; | ||||
Options withTargetComponent (Component& targetComponent) const noexcept; | |||||
Options withTargetScreenArea (Rectangle<int> targetArea) const noexcept; | Options withTargetScreenArea (Rectangle<int> targetArea) const noexcept; | ||||
Options withMinimumWidth (int minWidth) const noexcept; | Options withMinimumWidth (int minWidth) const noexcept; | ||||
Options withMinimumNumColumns (int minNumColumns) const noexcept; | Options withMinimumNumColumns (int minNumColumns) const noexcept; | ||||