From 75cb6c27d441a68b555ff49d225a3f7edf754f2a Mon Sep 17 00:00:00 2001 From: Denny Date: Wed, 11 Jan 2017 20:44:07 -0500 Subject: [PATCH] #82 - resolves issue with icon management and list updating after additions/deletions of icons. Updates the single and multi alias list editors to refresh their view any time that changes are made to the list of icons. --- src/alias/AliasNameEditor.java | 48 +++- src/alias/MultipleAliasEditor.java | 69 +++-- src/gui/editor/Editor.java | 233 ++++++++------- src/icon/{IconViewer.java => IconEditor.java} | 49 +++- ...enderer.java => IconListCellRenderer.java} | 11 +- src/icon/IconManager.java | 65 ++--- src/icon/IconModel.java | 150 ---------- src/icon/IconSelector.java | 14 +- src/icon/IconTableCellRenderer.java | 71 +++++ src/icon/IconTableModel.java | 270 ++++++++++++++++++ 10 files changed, 622 insertions(+), 358 deletions(-) rename src/icon/{IconViewer.java => IconEditor.java} (74%) rename src/icon/{IconCellRenderer.java => IconListCellRenderer.java} (84%) delete mode 100644 src/icon/IconModel.java create mode 100644 src/icon/IconTableCellRenderer.java create mode 100644 src/icon/IconTableModel.java diff --git a/src/alias/AliasNameEditor.java b/src/alias/AliasNameEditor.java index 6d2729aa..70b5cd66 100644 --- a/src/alias/AliasNameEditor.java +++ b/src/alias/AliasNameEditor.java @@ -21,15 +21,16 @@ package alias; import alias.AliasEvent.Event; import gui.editor.Editor; import icon.Icon; -import icon.IconCellRenderer; +import icon.IconListCellRenderer; import icon.IconManager; -import icon.IconModel; -import map.MapIcon; +import icon.IconTableModel; import net.miginfocom.swing.MigLayout; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -56,6 +57,15 @@ public class AliasNameEditor extends Editor mAliasModel = aliasModel; mIconManager = iconManager; + mIconManager.getModel().addTableModelListener(new TableModelListener() + { + @Override + public void tableChanged(TableModelEvent e) + { + refreshIcons(); + } + }); + init(); } @@ -155,7 +165,7 @@ public class AliasNameEditor extends Editor mIconCombo = new JComboBox(mIconManager.getIcons()); - IconCellRenderer renderer = new IconCellRenderer(mIconManager); + IconListCellRenderer renderer = new IconListCellRenderer(mIconManager); renderer.setPreferredSize(new Dimension(200, 30)); mIconCombo.setRenderer(renderer); mIconCombo.addActionListener(new ActionListener() @@ -187,6 +197,32 @@ public class AliasNameEditor extends Editor setModified(false); } + private void refreshIcons() + { + if(mIconCombo != null) + { + EventQueue.invokeLater(new Runnable() + { + @Override + public void run() + { + mIconCombo.setModel(new DefaultComboBoxModel<>(mIconManager.getIcons())); + + if(hasItem()) + { + String iconName = getItem().getIconName(); + Icon aliasIcon = mIconManager.getModel().getIcon(iconName); + + if(aliasIcon != null) + { + mIconCombo.setSelectedItem(aliasIcon); + } + } + } + }); + } + } + @Override public void setItem(Alias alias) { @@ -237,7 +273,7 @@ public class AliasNameEditor extends Editor if(iconName == null) { - iconName = IconModel.DEFAULT_ICON; + iconName = IconTableModel.DEFAULT_ICON; } Icon savedIcon = mIconManager.getModel().getIcon(iconName); @@ -285,7 +321,7 @@ public class AliasNameEditor extends Editor if(mIconCombo.getSelectedItem() != null) { - alias.setIconName(((MapIcon) mIconCombo.getSelectedItem()).getName()); + alias.setIconName(((Icon) mIconCombo.getSelectedItem()).getName()); } setModified(false); diff --git a/src/alias/MultipleAliasEditor.java b/src/alias/MultipleAliasEditor.java index 415c615e..796379b4 100644 --- a/src/alias/MultipleAliasEditor.java +++ b/src/alias/MultipleAliasEditor.java @@ -1,41 +1,29 @@ package alias; +import alias.AliasEvent.Event; import alias.id.AliasIDType; import alias.id.broadcast.BroadcastChannel; +import alias.id.priority.Priority; import audio.broadcast.BroadcastModel; -import com.sun.org.apache.xpath.internal.operations.Mult; import gui.editor.Editor; +import icon.Icon; +import icon.IconListCellRenderer; +import icon.IconManager; +import net.miginfocom.swing.MigLayout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import sample.Listener; -import java.awt.Color; -import java.awt.Dimension; +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JColorChooser; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JSeparator; -import javax.swing.JSlider; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import icon.Icon; -import icon.IconManager; -import map.MapIcon; -import icon.IconCellRenderer; -import net.miginfocom.swing.MigLayout; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import sample.Listener; -import alias.AliasEvent.Event; -import alias.id.priority.Priority; - public class MultipleAliasEditor extends Editor> implements Listener { @@ -76,6 +64,14 @@ public class MultipleAliasEditor extends Editor> mIconManager = iconManager; mAliasModel.addListener(this); + mIconManager.getModel().addTableModelListener(new TableModelListener() + { + @Override + public void tableChanged(TableModelEvent e) + { + refreshIcons(); + } + }); init(); } @@ -140,7 +136,7 @@ public class MultipleAliasEditor extends Editor> mIconCombo = new JComboBox(mIconManager.getIcons()); - IconCellRenderer renderer = new IconCellRenderer(mIconManager); + IconListCellRenderer renderer = new IconListCellRenderer(mIconManager); renderer.setPreferredSize(new Dimension(200, 30)); mIconCombo.setRenderer(renderer); add(mIconCombo, "wrap"); @@ -232,6 +228,21 @@ public class MultipleAliasEditor extends Editor> setModified(false); } + private void refreshIcons() + { + if(mIconCombo != null) + { + EventQueue.invokeLater(new Runnable() + { + @Override + public void run() + { + mIconCombo.setModel(new DefaultComboBoxModel<>(mIconManager.getIcons())); + } + }); + } + } + @Override public void setItem(List item) { @@ -356,7 +367,7 @@ public class MultipleAliasEditor extends Editor> { if (mIconCombo.getSelectedItem() != null) { - alias.setIconName(((MapIcon) mIconCombo.getSelectedItem()).getName()); + alias.setIconName(((Icon)mIconCombo.getSelectedItem()).getName()); } else { diff --git a/src/gui/editor/Editor.java b/src/gui/editor/Editor.java index f8261d81..305b3c59 100644 --- a/src/gui/editor/Editor.java +++ b/src/gui/editor/Editor.java @@ -1,131 +1,148 @@ +/******************************************************************************* + * sdrtrunk + * Copyright (C) 2014-2017 Dennis Sheirer + * + * This program 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. + * + * This program 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 this program. If not, see + * + ******************************************************************************/ package gui.editor; -import javax.swing.JOptionPane; -import javax.swing.JPanel; +import javax.swing.*; /** * Generic editor with change detection, save and reset functions. - * + * * This editor supports hierarchical nesting of sub-component editors where changes are detected - * at the lowest editor in the tree and percolated up to the top-level editor for managing the - * configuration set as a whole. - * + * at the lowest editor in the tree and percolated up to the top-level editor for managing the + * configuration set as a whole. + * * To configure this editor as a collective, register each parent editor as a saveRequestListener * on each child editor. If no save request listener is registered, the editor will simply invoke * save when a change is detected and the user opts to save the contents. - * + * * The top-level editor can override the saveRequest() method to perform custom save operations * and validation. */ public abstract class Editor extends JPanel { - private static final long serialVersionUID = 1L; - - protected T mItem; - protected boolean mModified = false; - protected Editor mSaveRequestListener; + private static final long serialVersionUID = 1L; - public Editor() - { - } + protected T mItem; + protected boolean mModified = false; + protected Editor mSaveRequestListener; - /** - * Requests to save the contents of this editor. - * - * If a save request listener is registered, the listener is notified that a save is requested, - * otherwise the save is request is processed by the instance. - * - * This allows for a save event to be percolated up the hierarchical set of editors so that - * a top-level editor can invoke custom operations such as configuration validation. - */ - protected void saveRequest() - { - if( mSaveRequestListener != null ) - { - mSaveRequestListener.saveRequest(); - } - else - { - save(); - } - } + public Editor() + { + } - /** - * Registers the editor to be notified when this editor contents have been saved. - */ - public void setSaveRequestListener( Editor listener ) - { - mSaveRequestListener = listener; - } - - - /** - * Sets the object to be edited. If the contents from the previous object have changed, this - * prompts the user to save these changes. A saveRequest() is issued and either this editor - * or the parent editor will respond to the save request and invoke the save() method. - */ - public void setItem( T item ) - { - if( isModified() ) - { - int option = JOptionPane.showConfirmDialog( - Editor.this, - "This item has changed. Do you want to save these changes?", - "Save Changes?", - JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE ); - - if( option == JOptionPane.YES_OPTION ) - { - saveRequest(); - } - - setModified( false ); - } - - mItem = item; - } + /** + * Requests to save the contents of this editor. + * + * If a save request listener is registered, the listener is notified that a save is requested, + * otherwise the save is request is processed by the instance. + * + * This allows for a save event to be percolated up the hierarchical set of editors so that + * a top-level editor can invoke custom operations such as configuration validation. + */ + protected void saveRequest() + { + if(mSaveRequestListener != null) + { + mSaveRequestListener.saveRequest(); + } + else + { + save(); + } + } - /** - * Current editing item - */ - public T getItem() - { - return mItem; - } - - public boolean hasItem() - { - return mItem != null; - } + /** + * Registers the editor to be notified when this editor contents have been saved. + */ + public void setSaveRequestListener(Editor listener) + { + mSaveRequestListener = listener; + } - /** - * Sets the contents modified flag - */ - public void setModified( boolean modified ) - { - mModified = modified; - } - /** - * Indicates if this editor contents have been modified - */ - public boolean isModified() - { - return mModified; - } + /** + * Sets the object to be edited. If the contents from the previous object have changed, this + * prompts the user to save these changes. A saveRequest() is issued and either this editor + * or the parent editor will respond to the save request and invoke the save() method. + */ + public void setItem(T item) + { + if(isModified()) + { + int option = JOptionPane.showConfirmDialog( + Editor.this, + "This item has changed. Do you want to save these changes?", + "Save Changes?", + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); - /** - * Save the contents of the editor - */ - public abstract void save(); + if(option == JOptionPane.YES_OPTION) + { + saveRequest(); + } - /** - * Reset the contents of the editor without saving any changes - */ - public void reset() - { - mModified = false; - setItem( mItem ); - } + setModified(false); + } + + mItem = item; + } + + /** + * Current editing item + */ + public T getItem() + { + return mItem; + } + + public boolean hasItem() + { + return mItem != null; + } + + /** + * Sets the contents modified flag + */ + public void setModified(boolean modified) + { + mModified = modified; + } + + /** + * Indicates if this editor contents have been modified + */ + public boolean isModified() + { + return mModified; + } + + /** + * Save the contents of the editor + */ + public abstract void save(); + + /** + * Reset the contents of the editor without saving any changes + */ + public void reset() + { + mModified = false; + setItem(mItem); + } } diff --git a/src/icon/IconViewer.java b/src/icon/IconEditor.java similarity index 74% rename from src/icon/IconViewer.java rename to src/icon/IconEditor.java index d581584d..e5fff02c 100644 --- a/src/icon/IconViewer.java +++ b/src/icon/IconEditor.java @@ -29,10 +29,10 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -public class IconViewer extends JFrame implements ActionListener +public class IconEditor extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; - private static final Logger mLog = LoggerFactory.getLogger(IconViewer.class); + private static final Logger mLog = LoggerFactory.getLogger(IconEditor.class); private static final String ADD = "Add"; private static final String DEFAULT = "Set Default"; private static final String DELETE = "Delete"; @@ -40,10 +40,10 @@ public class IconViewer extends JFrame implements ActionListener private JButton mAddButton; private JButton mDeleteButton; private JButton mDefaultButton; - private JList mIconList; + private JTable mIconTable; private IconManager mIconManager; - public IconViewer(IconManager model) + public IconEditor(IconManager model) { mIconManager = model; @@ -52,7 +52,7 @@ public class IconViewer extends JFrame implements ActionListener private void init() { - setTitle("Icon Viewer"); + setTitle("Icon Manager"); setSize(400, 400); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setLayout(new MigLayout("", "[grow,fill]", "[grow,fill]")); @@ -63,11 +63,13 @@ public class IconViewer extends JFrame implements ActionListener JPanel editorPanel = new JPanel(); editorPanel.setLayout(new MigLayout("insets 1 1 1 1", "[grow,fill][grow,fill][grow,fill]", "[grow,fill][]")); - mIconList = new JList<>(mIconManager.getModel()); - IconCellRenderer renderer = new IconCellRenderer(mIconManager); - renderer.setPreferredSize(new Dimension(200, 30)); - mIconList.setCellRenderer(renderer); - mIconList.addListSelectionListener(new ListSelectionListener() + mIconTable = new JTable(mIconManager.getModel()); + IconTableCellRenderer renderer = new IconTableCellRenderer(mIconManager); + mIconTable.getColumnModel().getColumn(IconTableModel.COLUMN_IMAGE_ICON).setCellRenderer(renderer); + mIconTable.setAutoCreateRowSorter(true); + mIconTable.getRowSorter().toggleSortOrder(IconTableModel.COLUMN_ICON_NAME); + mIconTable.setRowHeight(36); + mIconTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) @@ -75,7 +77,7 @@ public class IconViewer extends JFrame implements ActionListener checkButtons(); } }); - editorPanel.add(new JScrollPane(mIconList), "span"); + editorPanel.add(new JScrollPane(mIconTable), "span"); mAddButton = new JButton(ADD); mAddButton.addActionListener(this); @@ -96,15 +98,32 @@ public class IconViewer extends JFrame implements ActionListener private void checkButtons() { - Icon selected = mIconList.getSelectedValue(); + Icon selected = getSelectedIcon(); mDefaultButton.setEnabled(selected != null && selected != mIconManager.getModel().getDefaultIcon()); mDeleteButton.setEnabled(selected != null && selected != mIconManager.getModel().getDefaultIcon()); } + private Icon getSelectedIcon() + { + int selectedViewRow = mIconTable.getSelectedRow(); + + if(selectedViewRow >= 0) + { + int selectedModelRow = mIconTable.convertRowIndexToModel(mIconTable.getSelectedRow()); + + if(selectedModelRow >= 0) + { + return mIconManager.getModel().get(selectedModelRow); + } + } + + return null; + } + public void actionPerformed(ActionEvent e) { - Icon selected = mIconList.getSelectedValue(); + Icon selected = getSelectedIcon(); switch(e.getActionCommand()) { @@ -115,12 +134,12 @@ public class IconViewer extends JFrame implements ActionListener case DELETE: if(selected != null) { - int choice = JOptionPane.showConfirmDialog(IconViewer.this, + int choice = JOptionPane.showConfirmDialog(IconEditor.this, "Are you sure you want to delete this icon?", "Delete Icon?", JOptionPane.YES_NO_OPTION); if(choice == JOptionPane.YES_OPTION) { - mIconManager.getModel().removeElement(selected); + mIconManager.getModel().remove(selected); } } break; diff --git a/src/icon/IconCellRenderer.java b/src/icon/IconListCellRenderer.java similarity index 84% rename from src/icon/IconCellRenderer.java rename to src/icon/IconListCellRenderer.java index 128cffae..eb62683f 100644 --- a/src/icon/IconCellRenderer.java +++ b/src/icon/IconListCellRenderer.java @@ -21,13 +21,13 @@ package icon; import javax.swing.*; import java.awt.*; -public class IconCellRenderer extends JLabel implements ListCellRenderer +public class IconListCellRenderer extends JLabel implements ListCellRenderer { private static final long serialVersionUID = 1L; private IconManager mIconManager; - public IconCellRenderer(IconManager iconManager) + public IconListCellRenderer(IconManager iconManager) { mIconManager = iconManager; setOpaque(true); @@ -37,15 +37,16 @@ public class IconCellRenderer extends JLabel implements ListCellRenderer public Component getListCellRendererComponent(JList list, Icon icon, int index, boolean isSelected, boolean cellHasFocus) { + //Get a scaled version of the icon setIcon(mIconManager.getIcon(icon.getName(), 24)); - if(icon == mIconManager.getModel().getDefaultIcon()) + if(mIconManager.getModel().isDefaultIcon(icon)) { - setText(icon.toString() + " (default)"); + setText(icon.getName() + " (default)"); } else { - setText(icon.toString()); + setText(icon.getName()); } if(isSelected) diff --git a/src/icon/IconManager.java b/src/icon/IconManager.java index 41f6642a..5d61c1ac 100644 --- a/src/icon/IconManager.java +++ b/src/icon/IconManager.java @@ -26,6 +26,8 @@ import properties.SystemProperties; import javax.swing.*; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; @@ -53,8 +55,8 @@ public class IconManager private Path mIconLockFilePath; private ThreadPoolManager mThreadPoolManager; - private IconViewer mIconViewer; - private IconModel mIconModel; + private IconEditor mIconEditor; + private IconTableModel mIconTableModel; private AtomicBoolean mSavingIcons = new AtomicBoolean(); private Map mResizedIcons = new HashMap<>(); @@ -71,32 +73,33 @@ public class IconManager */ public void showEditor(Component centerOnComponent) { - if(mIconViewer == null) + if(mIconEditor == null) { - mIconViewer = new IconViewer(this); - mIconViewer.setLocationRelativeTo(centerOnComponent); + mIconEditor = new IconEditor(this); + } - if(mIconViewer.isVisible()) + mIconEditor.setLocationRelativeTo(centerOnComponent); + + if(mIconEditor.isVisible()) + { + mIconEditor.requestFocus(); + } + else + { + EventQueue.invokeLater(new Runnable() { - mIconViewer.requestFocus(); - } - else - { - EventQueue.invokeLater(new Runnable() + @Override + public void run() { - @Override - public void run() - { - mIconViewer.setVisible(true); - } - }); - } + mIconEditor.setVisible(true); + } + }); } } - public IconModel getModel() + public IconTableModel getModel() { - if(mIconModel == null) + if(mIconTableModel == null) { IconSet loadedIcons = load(); @@ -108,23 +111,11 @@ public class IconManager saveRequired = true; } - mIconModel = new IconModel(loadedIcons); - mIconModel.addListDataListener(new ListDataListener() + mIconTableModel = new IconTableModel(loadedIcons); + mIconTableModel.addTableModelListener(new TableModelListener() { @Override - public void intervalAdded(ListDataEvent e) - { - scheduleSave(); - } - - @Override - public void intervalRemoved(ListDataEvent e) - { - scheduleSave(); - } - - @Override - public void contentsChanged(ListDataEvent e) + public void tableChanged(TableModelEvent e) { scheduleSave(); } @@ -136,7 +127,7 @@ public class IconManager } } - return mIconModel; + return mIconTableModel; } /** @@ -389,7 +380,7 @@ public class IconManager { IconSet iconSet = new IconSet(); - Icon defaultIcon = new Icon(IconModel.DEFAULT_ICON, "images/no_icon.png"); + Icon defaultIcon = new Icon(IconTableModel.DEFAULT_ICON, "images/no_icon.png"); iconSet.add(defaultIcon); iconSet.setDefaultIcon(defaultIcon.getName()); diff --git a/src/icon/IconModel.java b/src/icon/IconModel.java deleted file mode 100644 index 7250ac31..00000000 --- a/src/icon/IconModel.java +++ /dev/null @@ -1,150 +0,0 @@ -/******************************************************************************* - * sdrtrunk - * Copyright (C) 2014-2017 Dennis Sheirer - * - * This program 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. - * - * This program 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 this program. If not, see - * - ******************************************************************************/ -package icon; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class IconModel extends DefaultListModel -{ - public static final String DEFAULT_ICON = "No Icon"; - - private Icon mDefaultIcon; - private Map mIconMap = new HashMap<>(); - - public IconModel(IconSet iconSet) - { - for(Icon icon : iconSet.getIcons()) - { - this.addElement(icon); - } - - String defaultIconName = iconSet.getDefaultIcon(); - - if(defaultIconName == null) - { - defaultIconName = DEFAULT_ICON; - } - - Icon defaultIcon = mIconMap.get(defaultIconName); - - if(defaultIcon != null) - { - mDefaultIcon = defaultIcon; - } - else - { - mDefaultIcon = new Icon(DEFAULT_ICON, "images/no_icon.png"); - } - } - - /** - * Icons in an array - suitable for use in a JComboBox - */ - public Icon[] getIconsAsArray() - { - List icons = new ArrayList<>(mIconMap.values()); - - Collections.sort(icons); - - return icons.toArray(new Icon[icons.size()]); - } - - public Icon getDefaultIcon() - { - return mDefaultIcon; - } - - /** - * Indicates if this model contains an icon with the specified name - * - * @param name to check - * @return true if name is not null and not empty and the internal map contains an icon matching name - */ - public boolean hasIcon(String name) - { - return name != null && !name.isEmpty() && mIconMap.containsKey(name); - } - - public void setDefaultIcon(Icon icon) - { - if(icon != null) - { - mDefaultIcon = icon; - - int index = indexOf(icon); - - fireContentsChanged(icon, index, index); - } - } - - /** - * Returns the named icon or the default icon if the named icon does not exist - */ - public Icon getIcon(String name) - { - if(name == null) - { - return mDefaultIcon; - } - - Icon icon = mIconMap.get(name); - - if(icon == null) - { - icon = mDefaultIcon; - } - - return icon; - } - - @Override - public void addElement(Icon icon) - { - super.addElement(icon); - - mIconMap.put(icon.getName(), icon); - } - - @Override - public boolean removeElement(Object object) - { - if(object instanceof Icon) - { - mIconMap.remove(((Icon) object).getName()); - } - - return super.removeElement(object); - } - - /** - * Creates a new icon set from a snapshot of the icons contained in this model - */ - public IconSet getIconSet() - { - IconSet iconSet = new IconSet(); - iconSet.setIcons(new ArrayList(mIconMap.values())); - iconSet.setDefaultIcon(getDefaultIcon().getName()); - return iconSet; - } -} diff --git a/src/icon/IconSelector.java b/src/icon/IconSelector.java index 6118a0e1..ced888df 100644 --- a/src/icon/IconSelector.java +++ b/src/icon/IconSelector.java @@ -19,8 +19,6 @@ package icon; import net.miginfocom.swing.MigLayout; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -32,7 +30,7 @@ import java.io.File; public class IconSelector extends JDialog implements DocumentListener { - private IconModel mIconModel; + private IconTableModel mIconTableModel; private JTextField mNameText; private JTextField mFileLabel; private JButton mFileChooserButton; @@ -43,13 +41,13 @@ public class IconSelector extends JDialog implements DocumentListener * Window for selecting an Icon to add to the Icon Model * * @param owner for this modal dialog - * @param iconModel to receive the added/selected icon + * @param iconTableModel to receive the added/selected icon */ - public IconSelector(Frame owner, IconModel iconModel) + public IconSelector(Frame owner, IconTableModel iconTableModel) { super(owner, "Add Icon", true); - mIconModel = iconModel; + mIconTableModel = iconTableModel; init(); @@ -122,7 +120,7 @@ public class IconSelector extends JDialog implements DocumentListener String path = mFileLabel.getText(); Icon icon = new Icon(name, path); - mIconModel.addElement(icon); + mIconTableModel.add(icon); IconSelector.this.dispose(); } @@ -151,7 +149,7 @@ public class IconSelector extends JDialog implements DocumentListener String name = mNameText.getText(); String path = mFileLabel.getText(); - mOKButton.setEnabled(name != null && path != null && !path.isEmpty() && !mIconModel.hasIcon(name)); + mOKButton.setEnabled(name != null && path != null && !path.isEmpty() && !mIconTableModel.hasIcon(name)); } @Override diff --git a/src/icon/IconTableCellRenderer.java b/src/icon/IconTableCellRenderer.java new file mode 100644 index 00000000..f58758b1 --- /dev/null +++ b/src/icon/IconTableCellRenderer.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * sdrtrunk + * Copyright (C) 2014-2017 Dennis Sheirer + * + * This program 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. + * + * This program 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 this program. If not, see + * + ******************************************************************************/ +package icon; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import javax.swing.table.TableCellRenderer; +import java.awt.*; + +public class IconTableCellRenderer extends JLabel implements TableCellRenderer +{ + private final static Logger mLog = LoggerFactory.getLogger(IconTableCellRenderer.class); + + private static final long serialVersionUID = 1L; + + private IconManager mIconManager; + + public IconTableCellRenderer(IconManager iconManager) + { + mIconManager = iconManager; + setOpaque(true); + setHorizontalAlignment(JLabel.CENTER); + setPreferredSize(new Dimension(40,34)); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, + int row, int column) + { + if(value instanceof ImageIcon) + { + //Get a scaled version of the icon + setIcon(mIconManager.getScaledIcon((ImageIcon)value, 24)); + } + else + { + setIcon(null); + } + + if(isSelected) + { + setBackground(table.getSelectionBackground()); + setForeground(table.getSelectionForeground()); + } + else + { + setBackground(table.getBackground()); + setForeground(table.getForeground()); + } + + return this; + } +} diff --git a/src/icon/IconTableModel.java b/src/icon/IconTableModel.java new file mode 100644 index 00000000..7b1d72c8 --- /dev/null +++ b/src/icon/IconTableModel.java @@ -0,0 +1,270 @@ +/******************************************************************************* + * sdrtrunk + * Copyright (C) 2014-2017 Dennis Sheirer + * + * This program 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. + * + * This program 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 this program. If not, see + * + ******************************************************************************/ +package icon; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class IconTableModel extends AbstractTableModel +{ + public static final String DEFAULT_ICON = "No Icon"; + public static final int COLUMN_IMAGE_ICON = 0; + public static final int COLUMN_ICON_NAME = 1; + + private Icon mDefaultIcon; + + private Map mIconMap = new HashMap<>(); + private List mIcons = new ArrayList<>(); + + public IconTableModel() + { + setDefaultIcon(DEFAULT_ICON); + } + + public IconTableModel(IconSet iconSet) + { + mIconMap.clear(); + mIcons.clear(); + + fireTableDataChanged(); + + for(Icon icon: iconSet.getIcons()) + { + add(icon); + } + + setDefaultIcon(iconSet.getDefaultIcon()); + } + + /** + * Adds the icon to the model + */ + public void add(Icon icon) + { + if(icon != null) + { + mIcons.add(icon); + mIconMap.put(icon.getName(), icon); + + int index = mIcons.indexOf(icon); + fireTableRowsInserted(index, index); + } + } + + /** + * Removes the icon from the model + */ + public void remove(Icon icon) + { + if(icon != null && mIcons.contains(icon)) + { + int index = mIcons.indexOf(icon); + + mIcons.remove(icon); + mIconMap.remove(icon.getName()); + + fireTableRowsDeleted(index, index); + } + + } + + public Icon get(int row) + { + if(row < mIcons.size()) + { + return mIcons.get(row); + } + + return null; + } + + @Override + public int getRowCount() + { + return mIcons.size(); + } + + @Override + public int getColumnCount() + { + return 2; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) + { + if(rowIndex < mIcons.size() && columnIndex < getColumnCount()) + { + Icon icon = get(rowIndex); + + switch(columnIndex) + { + case COLUMN_IMAGE_ICON: + return icon.getIcon(); + case COLUMN_ICON_NAME: + if(rowIndex == mIcons.indexOf(getDefaultIcon())) + { + return icon.getName() + " (default)"; + } + else + { + return icon.getName(); + } + } + } + + return null; + } + + @Override + public String getColumnName(int column) + { + if(column == COLUMN_ICON_NAME) + { + return "Name"; + } + + return null; + } + + @Override + public Class getColumnClass(int columnIndex) + { + if(columnIndex == COLUMN_IMAGE_ICON) + { + return ImageIcon.class; + } + + return String.class; + } + + /** + * Icons in an array - suitable for use in a JComboBox + */ + public Icon[] getIconsAsArray() + { + List icons = new ArrayList<>(mIconMap.values()); + + Collections.sort(icons); + + return icons.toArray(new Icon[icons.size()]); + } + + /** + * Returns the current default icon + */ + public Icon getDefaultIcon() + { + return mDefaultIcon; + } + + /** + * Indicates if the icon argument is the current default icon + */ + public boolean isDefaultIcon(Icon icon) + { + return icon == getDefaultIcon(); + } + + /** + * Indicates if this model contains an icon with the specified name + * + * @param name to check + * @return true if name is not null and not empty and the internal map contains an icon matching name + */ + public boolean hasIcon(String name) + { + return name != null && !name.isEmpty() && mIconMap.containsKey(name); + } + + public void setDefaultIcon(Icon icon) + { + if(icon != null) + { + int currentIndex = mIcons.indexOf(getDefaultIcon()); + + mDefaultIcon = icon; + + int newIndex = mIcons.indexOf(icon); + + fireTableCellUpdated(currentIndex, COLUMN_ICON_NAME); + fireTableCellUpdated(newIndex, COLUMN_ICON_NAME); + } + } + + /** + * Sets the default icon to the icon with the specified name, or to a default icon of the named icon does not exist + */ + public void setDefaultIcon(String name) + { + if(name == null) + { + name = DEFAULT_ICON; + } + + Icon defaultIcon = mIconMap.get(name); + + if(defaultIcon != null) + { + setDefaultIcon(defaultIcon); + } + else + { + defaultIcon = new Icon(DEFAULT_ICON, "images/no_icon.png"); + add(defaultIcon); + setDefaultIcon(defaultIcon); + } + } + + /** + * Returns the named icon or the default icon if the named icon does not exist + */ + public Icon getIcon(String name) + { + if(name == null || name.isEmpty()) + { + return mDefaultIcon; + } + + Icon icon = mIconMap.get(name); + + if(icon == null) + { + icon = mDefaultIcon; + } + + return icon; + } + + /** + * Creates a new icon set from a snapshot of the icons contained in this model + */ + public IconSet getIconSet() + { + IconSet iconSet = new IconSet(); + iconSet.setIcons(new ArrayList(mIconMap.values())); + iconSet.setDefaultIcon(getDefaultIcon().getName()); + return iconSet; + } +}