1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/extras/Projucer/Source/Project/UI/jucer_ModulesInformationComponent.h

344 lines
14 KiB
C++

/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
class ModulesInformationComponent : public Component,
private ListBoxModel,
private ValueTree::Listener
{
public:
ModulesInformationComponent (Project& p)
: project (p),
modulesValueTree (project.getEnabledModules().getState())
{
auto tempHeader = std::make_unique<ListBoxHeader> (Array<String> { "Module", "Version", "Make Local Copy", "Paths" },
Array<float> { 0.25f, 0.2f, 0.2f, 0.35f });
listHeader = tempHeader.get();
list.setHeaderComponent (std::move (tempHeader));
list.setModel (this);
list.setColour (ListBox::backgroundColourId, Colours::transparentBlack);
addAndMakeVisible (list);
list.updateContent();
list.setRowHeight (30);
list.setMultipleSelectionEnabled (true);
addAndMakeVisible (header);
addAndMakeVisible (setCopyModeButton);
setCopyModeButton.setTriggeredOnMouseDown (true);
setCopyModeButton.onClick = [this] { showCopyModeMenu(); };
addAndMakeVisible (copyPathButton);
copyPathButton.setTriggeredOnMouseDown (true);
copyPathButton.onClick = [this] { showSetPathsMenu(); };
addAndMakeVisible (globalPathsButton);
globalPathsButton.onClick = [this] { showGlobalPathsMenu(); };
modulesValueTree.addListener (this);
lookAndFeelChanged();
}
void paint (Graphics& g) override
{
g.setColour (findColour (secondaryBackgroundColourId));
g.fillRect (getLocalBounds().reduced (12, 0));
}
void resized() override
{
auto bounds = getLocalBounds().reduced (12, 0);
header.setBounds (bounds.removeFromTop (40));
bounds.reduce (10, 0);
list.setBounds (bounds.removeFromTop (list.getRowPosition (getNumRows() - 1, true).getBottom() + 20));
if (bounds.getHeight() < 35)
{
parentSizeChanged();
}
else
{
auto buttonRow = bounds.removeFromTop (35);
setCopyModeButton.setBounds (buttonRow.removeFromLeft (jmin (200, bounds.getWidth() / 3)));
buttonRow.removeFromLeft (8);
copyPathButton.setBounds (buttonRow.removeFromLeft (jmin (200, bounds.getWidth() / 3)));
buttonRow.removeFromLeft (8);
globalPathsButton.setBounds (buttonRow.removeFromLeft (jmin (200, bounds.getWidth() / 3)));
}
}
void parentSizeChanged() override
{
auto width = jmax (550, getParentWidth());
auto y = list.getRowPosition (getNumRows() - 1, true).getBottom() + 200;
y = jmax (getParentHeight(), y);
setSize (width, y);
}
int getNumRows() override
{
return project.getEnabledModules().getNumModules();
}
void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) override
{
ignoreUnused (height);
Rectangle<int> bounds (0, 0, width, height);
g.setColour (rowIsSelected ? findColour (defaultHighlightColourId) : findColour (rowNumber % 2 == 0 ? widgetBackgroundColourId
: secondaryWidgetBackgroundColourId));
g.fillRect (bounds.withTrimmedBottom (1));
bounds.removeFromLeft (5);
g.setColour (rowIsSelected ? findColour (defaultHighlightedTextColourId) : findColour (widgetTextColourId));
//==============================================================================
auto moduleID = project.getEnabledModules().getModuleID (rowNumber);
g.drawFittedText (moduleID, bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (0) * (float) width)), Justification::centredLeft, 1);
//==============================================================================
auto version = project.getEnabledModules().getModuleInfo (moduleID).getVersion();
if (version.isEmpty())
version = "?";
g.drawFittedText (version, bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (1) * (float) width)), Justification::centredLeft, 1);
//==============================================================================
g.drawFittedText (String (project.getEnabledModules().shouldCopyModuleFilesLocally (moduleID) ? "Yes" : "No"),
bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (2) * (float) width)), Justification::centredLeft, 1);
//==============================================================================
String pathText;
if (project.getEnabledModules().shouldUseGlobalPath (moduleID))
{
pathText = "Global";
}
else
{
StringArray paths;
for (Project::ExporterIterator exporter (project); exporter.next();)
paths.addIfNotAlreadyThere (exporter->getPathForModuleString (moduleID).trim());
paths.removeEmptyStrings();
paths.removeDuplicates (true);
pathText = paths.joinIntoString (", ");
}
g.drawFittedText (pathText, bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (3) * (float) width)), Justification::centredLeft, 1);
}
void listBoxItemDoubleClicked (int row, const MouseEvent&) override
{
auto moduleID = project.getEnabledModules().getModuleID (row);
if (moduleID.isNotEmpty())
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->showModule (moduleID);
}
void deleteKeyPressed (int row) override
{
project.getEnabledModules().removeModule (project.getEnabledModules().getModuleID (row));
}
void lookAndFeelChanged() override
{
setCopyModeButton.setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId));
copyPathButton.setColour (TextButton::buttonColourId, findColour (defaultButtonBackgroundColourId));
globalPathsButton.setColour (TextButton::buttonColourId, findColour (defaultButtonBackgroundColourId));
}
private:
enum
{
nameCol = 1,
versionCol,
copyCol,
pathCol
};
Project& project;
ValueTree modulesValueTree;
ContentViewHeader header { "Modules", { getIcons().modules, Colours::transparentBlack } };
ListBox list;
ListBoxHeader* listHeader;
TextButton setCopyModeButton { "Set copy-mode for all modules..." };
TextButton copyPathButton { "Set paths for all modules..." };
TextButton globalPathsButton { "Enable/disable global path for modules..." };
std::map<String, var> modulePathClipboard;
void valueTreePropertyChanged (ValueTree&, const Identifier&) override { itemChanged(); }
void valueTreeChildAdded (ValueTree&, ValueTree&) override { itemChanged(); }
void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override { itemChanged(); }
void valueTreeChildOrderChanged (ValueTree&, int, int) override { itemChanged(); }
void valueTreeParentChanged (ValueTree&) override { itemChanged(); }
void itemChanged()
{
list.updateContent();
resized();
repaint();
}
static void setLocalCopyModeForAllModules (Project& project, bool copyLocally)
{
auto& modules = project.getEnabledModules();
for (auto i = modules.getNumModules(); --i >= 0;)
modules.shouldCopyModuleFilesLocallyValue (modules.getModuleID (i)) = copyLocally;
}
void showCopyModeMenu()
{
PopupMenu m;
m.addItem (PopupMenu::Item ("Set all modules to copy locally")
.setAction ([&] { setLocalCopyModeForAllModules (project, true); }));
m.addItem (PopupMenu::Item ("Set all modules to not copy locally")
.setAction ([&] { setLocalCopyModeForAllModules (project, false); }));
m.showMenuAsync (PopupMenu::Options().withTargetComponent (setCopyModeButton));
}
static void setAllModulesToUseGlobalPaths (Project& project, bool useGlobal)
{
auto& modules = project.getEnabledModules();
for (auto moduleID : modules.getAllModules())
modules.shouldUseGlobalPathValue (moduleID) = useGlobal;
}
static void setSelectedModulesToUseGlobalPaths (Project& project, SparseSet<int> selected, bool useGlobal)
{
auto& modules = project.getEnabledModules();
for (int i = 0; i < selected.size(); ++i)
modules.shouldUseGlobalPathValue (modules.getModuleID (selected[i])) = useGlobal;
}
void showGlobalPathsMenu()
{
PopupMenu m;
m.addItem (PopupMenu::Item ("Set all modules to use global paths")
.setAction ([&] { setAllModulesToUseGlobalPaths (project, true); }));
m.addItem (PopupMenu::Item ("Set all modules to not use global paths")
.setAction ([&] { setAllModulesToUseGlobalPaths (project, false); }));
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()
{
PopupMenu m;
auto moduleToCopy = project.getEnabledModules().getModuleID (list.getSelectedRow());
if (moduleToCopy.isNotEmpty())
{
m.addItem (PopupMenu::Item ("Copy the paths from the module '" + moduleToCopy + "' to all other modules")
.setAction ([this, moduleToCopy]
{
auto& modulesList = project.getEnabledModules();
for (Project::ExporterIterator exporter (project); exporter.next();)
{
for (int i = 0; i < modulesList.getNumModules(); ++i)
{
auto modID = modulesList.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->getUniqueName()] = 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->getUniqueName()];
}
list.repaint();
}));
}
else
{
m.addItem (PopupMenu::Item ("(Select a module in the list above to use this option)")
.setEnabled (false));
}
m.showMenuAsync (PopupMenu::Options()
.withDeletionCheck (*this)
.withTargetComponent (copyPathButton));
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModulesInformationComponent)
};