Toolbar drop down menu now contains options for managing favorites,

keyboard shortcuts and selecting all components of type
This commit is contained in:
bancika
2021-01-01 09:29:09 +01:00
parent a2b06c0a0d
commit 607f963ba7
5 changed files with 292 additions and 184 deletions
@@ -3430,6 +3430,10 @@
<changeType>NEW_FEATURE</changeType> <changeType>NEW_FEATURE</changeType>
<description>Scroll buttons added to the component toolbar that appear when needed</description> <description>Scroll buttons added to the component toolbar that appear when needed</description>
</org.diylc.appframework.update.Change> </org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Toolbar drop down menu now contains options for managing favorites, keyboard shortcuts and selecting all components of type</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType> <changeType>IMPROVEMENT</changeType>
<description>Save last selected tab in the component toolbar and restore it in the next session</description> <description>Save last selected tab in the component toolbar and restore it in the next session</description>
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,39 +1,42 @@
/* /*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
package org.diylc.swing.plugins.toolbox;
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2018 held jointly by the individual authors.
This file is part of DIYLC.
DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diylc.swing.plugins.toolbox;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Component; import java.awt.Component;
import java.awt.Container; import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import javax.swing.BoxLayout; import javax.swing.BoxLayout;
import javax.swing.JMenu;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JPopupMenu; import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTabbedPane; import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
@@ -51,71 +54,74 @@ import org.diylc.core.IDIYComponent;
import org.diylc.core.Template; import org.diylc.core.Template;
import org.diylc.lang.LangUtil; import org.diylc.lang.LangUtil;
import org.diylc.presenter.ComparatorFactory; import org.diylc.presenter.ComparatorFactory;
import org.diylc.presenter.ComponentProcessor; import org.diylc.presenter.ComponentProcessor;
import org.diylc.swing.images.IconLoader;
/** import org.diylc.swing.plugins.tree.TreePanel;
* Tabbed pane that shows all available components categorized into tabs. import org.diylc.swing.plugins.tree.TreePanel.SelectAllAction;
*
* @author Branislav Stojkovic /**
*/ * Tabbed pane that shows all available components categorized into tabs.
class ComponentTabbedPane extends JTabbedPane { *
* @author Branislav Stojkovic
private static final long serialVersionUID = 1L; */
class ComponentTabbedPane extends JTabbedPane {
private static final long serialVersionUID = 1L;
private static final Logger LOG = Logger.getLogger(ComponentTabbedPane.class); private static final Logger LOG = Logger.getLogger(ComponentTabbedPane.class);
public static String LAST_SELECTED_TAB = "lastSelectedTab"; public static String LAST_SELECTED_TAB = "lastSelectedTab";
private final IPlugInPort plugInPort; private final IPlugInPort plugInPort;
private Container recentToolbar; private Container recentToolbar;
private Container buildingBlocksToolbar; private Container buildingBlocksToolbar;
private Container favoritesToolbar; private Container favoritesToolbar;
private Map<String, ComponentType> typesByClass; private Map<String, ComponentType> typesByClass;
private List<Favorite> favorites; private List<Favorite> favorites;
private List<String> pendingRecentComponents = null; private List<String> pendingRecentComponents = null;
private List<String> blocks; private List<String> blocks;
public ComponentTabbedPane(IPlugInPort plugInPort) { public ComponentTabbedPane(IPlugInPort plugInPort) {
super(); super();
this.plugInPort = plugInPort; this.plugInPort = plugInPort;
initialize(); initialize();
// layout UI // layout UI
addTab(LangUtil.translate("(Favorites)"), createFavoritesPanel()); addTab(LangUtil.translate("(Favorites)"), createFavoritesPanel());
addTab(LangUtil.translate("(Recently Used)"), createRecentComponentsPanel()); addTab(LangUtil.translate("(Recently Used)"), createRecentComponentsPanel());
addTab(LangUtil.translate("(Building Blocks)"), createBuildingBlocksPanel()); addTab(LangUtil.translate("(Building Blocks)"), createBuildingBlocksPanel());
Map<String, List<ComponentType>> componentTypes = plugInPort.getComponentTypes(); Map<String, List<ComponentType>> componentTypes = plugInPort.getComponentTypes();
List<String> categories = new ArrayList<String>(componentTypes.keySet()); List<String> categories = new ArrayList<String>(componentTypes.keySet());
Collections.sort(categories); Collections.sort(categories);
for (String category : categories) { for (String category : categories) {
JPanel panel = createTab((componentTypes.get(category))); JPanel panel = createTab((componentTypes.get(category)));
addTab(category, panel); addTab(category, panel);
} }
// restore last selected tab // restore last selected tab
int lastSelectedTab = ConfigurationManager.getInstance().readInt(LAST_SELECTED_TAB, -1); int lastSelectedTab = ConfigurationManager.getInstance().readInt(LAST_SELECTED_TAB, -1);
if (lastSelectedTab >= 0) if (lastSelectedTab >= 0)
setSelectedIndex(lastSelectedTab); setSelectedIndex(lastSelectedTab);
addChangeListener(new ChangeListener() { addChangeListener(new ChangeListener() {
@Override @Override
public void stateChanged(ChangeEvent e) { public void stateChanged(ChangeEvent e) {
ConfigurationManager.getInstance().writeValue(LAST_SELECTED_TAB, getSelectedIndex()); ConfigurationManager.getInstance().writeValue(LAST_SELECTED_TAB, getSelectedIndex());
ComponentTabbedPane.this.plugInPort.setNewComponentTypeSlot(null, null, false); ComponentTabbedPane.this.plugInPort.setNewComponentTypeSlot(null, null, false);
// Refresh recent components if needed // Refresh recent components if needed
if (pendingRecentComponents != null) { if (pendingRecentComponents != null) {
refreshRecentComponentsToolbar(pendingRecentComponents); refreshRecentComponentsToolbar(pendingRecentComponents);
getRecentToolbar().invalidate(); getRecentToolbar().invalidate();
pendingRecentComponents = null; pendingRecentComponents = null;
} }
} }
}); });
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -125,7 +131,7 @@ class ComponentTabbedPane extends JTabbedPane {
for (Map.Entry<String, List<ComponentType>> e : componentTypes.entrySet()) for (Map.Entry<String, List<ComponentType>> e : componentTypes.entrySet())
for (ComponentType c : e.getValue()) for (ComponentType c : e.getValue())
typesByClass.put(c.getInstanceClass().getCanonicalName(), c); typesByClass.put(c.getInstanceClass().getCanonicalName(), c);
// load building blocks // load building blocks
ConfigurationManager.getInstance().addConfigListener(IPlugInPort.BLOCKS_KEY, ConfigurationManager.getInstance().addConfigListener(IPlugInPort.BLOCKS_KEY,
new IConfigListener() { new IConfigListener() {
@@ -139,14 +145,14 @@ class ComponentTabbedPane extends JTabbedPane {
Collections.sort(blockNames); Collections.sort(blockNames);
if (!blockNames.equals(ComponentTabbedPane.this.blocks)) { if (!blockNames.equals(ComponentTabbedPane.this.blocks)) {
LOG.info("Detected block change"); LOG.info("Detected block change");
ComponentTabbedPane.this.blocks = blockNames; ComponentTabbedPane.this.blocks = blockNames;
refreshBuildingBlocksToolbar(); refreshBuildingBlocksToolbar();
} else } else
LOG.info("Detected no block change"); LOG.info("Detected no block change");
} else } else
LOG.info("Detected no block change"); LOG.info("Detected no block change");
} }
}); });
Map<String, List<IDIYComponent<?>>> newBlocks = Map<String, List<IDIYComponent<?>>> newBlocks =
(Map<String, List<IDIYComponent<?>>>) ConfigurationManager.getInstance() (Map<String, List<IDIYComponent<?>>>) ConfigurationManager.getInstance()
.readObject(IPlugInPort.BLOCKS_KEY, null); .readObject(IPlugInPort.BLOCKS_KEY, null);
@@ -156,7 +162,7 @@ class ComponentTabbedPane extends JTabbedPane {
this.blocks = new ArrayList<String>(newBlocks.keySet()); this.blocks = new ArrayList<String>(newBlocks.keySet());
Collections.sort(this.blocks); Collections.sort(this.blocks);
} }
ConfigurationManager.getInstance().addConfigListener(IPlugInPort.FAVORITES_KEY, ConfigurationManager.getInstance().addConfigListener(IPlugInPort.FAVORITES_KEY,
new IConfigListener() { new IConfigListener() {
@@ -173,25 +179,25 @@ class ComponentTabbedPane extends JTabbedPane {
}); });
this.favorites = new ArrayList<Favorite>((List<Favorite>) ConfigurationManager.getInstance() this.favorites = new ArrayList<Favorite>((List<Favorite>) ConfigurationManager.getInstance()
.readObject(IPlugInPort.FAVORITES_KEY, new ArrayList<Favorite>())); .readObject(IPlugInPort.FAVORITES_KEY, new ArrayList<Favorite>()));
}
private JPanel createTab(List<ComponentType> componentTypes) {
JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(false);
panel.add(createComponentPanel(componentTypes), BorderLayout.CENTER);
return panel;
}
public Container getRecentToolbar() {
if (recentToolbar == null) {
recentToolbar = new Container();
recentToolbar.setLayout(new BoxLayout(recentToolbar, BoxLayout.X_AXIS));
}
return recentToolbar;
} }
private JPanel createTab(List<ComponentType> componentTypes) {
JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(false);
panel.add(createComponentPanel(componentTypes), BorderLayout.CENTER);
return panel;
}
public Container getRecentToolbar() {
if (recentToolbar == null) {
recentToolbar = new Container();
recentToolbar.setLayout(new BoxLayout(recentToolbar, BoxLayout.X_AXIS));
}
return recentToolbar;
}
public Container getBuildingBlocksToolbar() { public Container getBuildingBlocksToolbar() {
if (buildingBlocksToolbar == null) { if (buildingBlocksToolbar == null) {
buildingBlocksToolbar = new Container(); buildingBlocksToolbar = new Container();
@@ -199,62 +205,64 @@ class ComponentTabbedPane extends JTabbedPane {
} }
return buildingBlocksToolbar; return buildingBlocksToolbar;
} }
public Container getFavoritesToolbar() { public Container getFavoritesToolbar() {
if (favoritesToolbar == null) { if (favoritesToolbar == null) {
favoritesToolbar = new Container(); favoritesToolbar = new Container();
favoritesToolbar.setLayout(new BoxLayout(favoritesToolbar, BoxLayout.X_AXIS)); favoritesToolbar.setLayout(new BoxLayout(favoritesToolbar, BoxLayout.X_AXIS));
} }
return favoritesToolbar; return favoritesToolbar;
}
private Component createComponentPanel(List<ComponentType> componentTypes) {
Container toolbar = new Container();
Collections.sort(componentTypes, ComparatorFactory.getInstance().getComponentTypeComparator());
toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.X_AXIS));
for (ComponentType componentType : componentTypes) {
try {
Component button = ComponentButtonFactory.create(plugInPort, componentType, createVariantPopup(componentType));
toolbar.add(button);
} catch (Exception e) {
LOG.error("Could not create recent component button for " + componentType.getName(), e);
}
}
return new ToolbarScrollPane(toolbar);
}
@SuppressWarnings("unchecked")
private Component createRecentComponentsPanel() {
final Container toolbar = getRecentToolbar();
refreshRecentComponentsToolbar((List<String>) ConfigurationManager.getInstance().readObject(IPlugInPort.RECENT_COMPONENTS_KEY,
new ArrayList<String>()));
ConfigurationManager.getInstance().addConfigListener(IPlugInPort.RECENT_COMPONENTS_KEY, new IConfigListener() {
@Override
public void valueChanged(String key, Object value) {
// Cache the new list, we'll refresh when there's a
// chance
pendingRecentComponents = (List<String>) value;
}
});
JPanel panel = new ToolbarScrollPane(toolbar);
return panel;
} }
private Component createComponentPanel(List<ComponentType> componentTypes) {
Container toolbar = new Container();
Collections.sort(componentTypes, ComparatorFactory.getInstance().getComponentTypeComparator());
toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.X_AXIS));
for (ComponentType componentType : componentTypes) {
try {
Component button = ComponentButtonFactory.create(plugInPort, componentType,
createVariantPopup(componentType));
toolbar.add(button);
} catch (Exception e) {
LOG.error("Could not create recent component button for " + componentType.getName(), e);
}
}
return new ToolbarScrollPane(toolbar);
}
@SuppressWarnings("unchecked")
private Component createRecentComponentsPanel() {
final Container toolbar = getRecentToolbar();
refreshRecentComponentsToolbar((List<String>) ConfigurationManager.getInstance()
.readObject(IPlugInPort.RECENT_COMPONENTS_KEY, new ArrayList<String>()));
ConfigurationManager.getInstance().addConfigListener(IPlugInPort.RECENT_COMPONENTS_KEY,
new IConfigListener() {
@Override
public void valueChanged(String key, Object value) {
// Cache the new list, we'll refresh when there's a
// chance
pendingRecentComponents = (List<String>) value;
}
});
JPanel panel = new ToolbarScrollPane(toolbar);
return panel;
}
private Component createBuildingBlocksPanel() { private Component createBuildingBlocksPanel() {
final Container toolbar = getBuildingBlocksToolbar(); final Container toolbar = getBuildingBlocksToolbar();
JPanel panel = new ToolbarScrollPane(toolbar); JPanel panel = new ToolbarScrollPane(toolbar);
refreshBuildingBlocksToolbar(); refreshBuildingBlocksToolbar();
return panel; return panel;
} }
private Component createFavoritesPanel() { private Component createFavoritesPanel() {
JPanel panel = new JPanel(new BorderLayout()); JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(false); panel.setOpaque(false);
@@ -262,31 +270,31 @@ class ComponentTabbedPane extends JTabbedPane {
final Container toolbar = getFavoritesToolbar(); final Container toolbar = getFavoritesToolbar();
panel.add(toolbar, BorderLayout.CENTER); panel.add(toolbar, BorderLayout.CENTER);
refreshFavoritesToolbar(); refreshFavoritesToolbar();
return panel; return panel;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void refreshRecentComponentsToolbar(List<String> recentComponentClassList) { private void refreshRecentComponentsToolbar(List<String> recentComponentClassList) {
Container toolbar = getRecentToolbar(); Container toolbar = getRecentToolbar();
toolbar.removeAll(); toolbar.removeAll();
for (String componentClassName : recentComponentClassList) { for (String componentClassName : recentComponentClassList) {
ComponentType componentType; ComponentType componentType;
try { try {
componentType = componentType = ComponentProcessor.getInstance().extractComponentTypeFrom(
ComponentProcessor.getInstance().extractComponentTypeFrom( (Class<? extends IDIYComponent<?>>) Class.forName(componentClassName));
(Class<? extends IDIYComponent<?>>) Class.forName(componentClassName)); Component button = ComponentButtonFactory.create(plugInPort, componentType,
Component button = ComponentButtonFactory.create(plugInPort, componentType, createVariantPopup(componentType)); createVariantPopup(componentType));
toolbar.add(button); toolbar.add(button);
} catch (Exception e) { } catch (Exception e) {
LOG.error("Could not create recent component button for " + componentClassName, e); LOG.error("Could not create recent component button for " + componentClassName, e);
} }
} }
} }
private void refreshBuildingBlocksToolbar() { private void refreshBuildingBlocksToolbar() {
Container toolbar = getBuildingBlocksToolbar(); Container toolbar = getBuildingBlocksToolbar();
toolbar.removeAll(); toolbar.removeAll();
@@ -295,7 +303,7 @@ class ComponentTabbedPane extends JTabbedPane {
toolbar.add(button); toolbar.add(button);
} }
} }
private void refreshFavoritesToolbar() { private void refreshFavoritesToolbar() {
Container toolbar = getFavoritesToolbar(); Container toolbar = getFavoritesToolbar();
toolbar.removeAll(); toolbar.removeAll();
@@ -305,39 +313,135 @@ class ComponentTabbedPane extends JTabbedPane {
button = ComponentButtonFactory.createBuildingBlockButton(plugInPort, fav.getName()); button = ComponentButtonFactory.createBuildingBlockButton(plugInPort, fav.getName());
} else { } else {
ComponentType componentType = this.typesByClass.get(fav.getName()); ComponentType componentType = this.typesByClass.get(fav.getName());
button = ComponentButtonFactory.create(plugInPort, componentType, createVariantPopup(componentType)); button = ComponentButtonFactory.create(plugInPort, componentType,
createVariantPopup(componentType));
} }
toolbar.add(button); toolbar.add(button);
} }
} }
private JPopupMenu createVariantPopup(final ComponentType componentType) { private JPopupMenu createVariantPopup(final ComponentType componentType) {
final JPopupMenu variantPopup = new JPopupMenu(); final JPopupMenu variantPopup = new JPopupMenu();
variantPopup.add("Loading..."); variantPopup.add("Loading...");
variantPopup.addPopupMenuListener(new PopupMenuListener() { variantPopup.addPopupMenuListener(new PopupMenuListener() {
@Override @SuppressWarnings("unchecked")
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { @Override
variantPopup.removeAll(); public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
List<Template> variants = plugInPort.getVariantsFor(componentType); variantPopup.removeAll();
if (variants == null || variants.isEmpty()) {
JMenuItem item = new JMenuItem("<no variants>"); final String identifier = componentType.getInstanceClass().getCanonicalName();
item.setEnabled(false);
variantPopup.add(item); JMenu shortcutSubmenu = new JMenu("Assign Shortcut");
} else { final JRadioButtonMenuItem noneItem = new JRadioButtonMenuItem ("None");
for (Template variant : variants) { noneItem.addActionListener(new ActionListener() {
JMenuItem item = ComponentButtonFactory.createVariantItem(plugInPort, variant, componentType);
variantPopup.add(item); @Override
} public void actionPerformed(ActionEvent e) {
} HashMap<String, String> map = (HashMap<String, String>) ConfigurationManager
} .getInstance().readObject(TreePanel.COMPONENT_SHORTCUT_KEY, null);
if (map == null)
@Override map = new HashMap<String, String>();
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {}
Iterator<Entry<String, String>> it = map.entrySet().iterator();
@Override while (it.hasNext()) {
public void popupMenuCanceled(PopupMenuEvent e) {} Entry<String, String> item = it.next();
}); if (item.getValue().equals(identifier))
return variantPopup; it.remove();
} }
}
ConfigurationManager.getInstance().writeValue(TreePanel.COMPONENT_SHORTCUT_KEY, map);
}
});
HashMap<String, String> map = (HashMap<String, String>) ConfigurationManager
.getInstance().readObject(TreePanel.COMPONENT_SHORTCUT_KEY, null);
noneItem.setSelected(map == null);
shortcutSubmenu.add(noneItem);
for (int i = 1; i <= 12; i++) {
final JRadioButtonMenuItem item = new JRadioButtonMenuItem("F" + i);
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
HashMap<String, String> map = (HashMap<String, String>) ConfigurationManager
.getInstance().readObject(TreePanel.COMPONENT_SHORTCUT_KEY, null);
if (map == null)
map = new HashMap<String, String>();
if (map.containsKey(item.getText()))
map.remove(item.getText());
Iterator<Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Entry<String, String> item = it.next();
if (item.getValue().equals(identifier))
it.remove();
}
map.put(item.getText(), identifier);
ConfigurationManager.getInstance().writeValue(TreePanel.COMPONENT_SHORTCUT_KEY, map);
}
});
boolean selected;
if (map == null)
selected = false;
else
selected = map.containsKey(item.getText()) && map.get(item.getText()).equals(identifier);
item.setSelected(selected);
shortcutSubmenu.add(item);
}
final Favorite fav =
new Favorite(FavoriteType.Component, componentType.getInstanceClass().getCanonicalName());
final boolean isFavorite = favorites != null && favorites.indexOf(fav) >= 0;
final JMenuItem favoritesItem =
new JMenuItem(isFavorite ? "Remove From Favorites" : "Add To Favorites",
isFavorite ? IconLoader.StarBlue.getIcon() : IconLoader.StarGrey.getIcon());
favoritesItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<Favorite> favorites = new ArrayList<Favorite>(ComponentTabbedPane.this.favorites);
if (isFavorite) {
favorites.remove(fav);
} else {
favorites.add(fav);
Collections.sort(favorites);
}
ConfigurationManager.getInstance().writeValue(IPlugInPort.FAVORITES_KEY, favorites);
}
});
variantPopup.add(favoritesItem);
variantPopup.add(new SelectAllAction(plugInPort, componentType));
variantPopup.add(shortcutSubmenu);
List<Template> variants = plugInPort.getVariantsFor(componentType);
if (variants == null || variants.isEmpty()) {
JMenuItem item = new JMenuItem("<no variants>");
item.setEnabled(false);
variantPopup.add(item);
} else {
for (Template variant : variants) {
JMenuItem item =
ComponentButtonFactory.createVariantItem(plugInPort, variant, componentType);
variantPopup.add(item);
}
}
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {}
});
return variantPopup;
}
}