#82 WIP - reorganizing icon management and extracting icon model from the settings manager.

This commit is contained in:
Denny
2017-01-08 15:01:53 -05:00
parent 4481560c41
commit 488dc9da4c
17 changed files with 1796 additions and 1182 deletions

View File

@@ -1,369 +1,356 @@
package alias; package alias;
import audio.broadcast.BroadcastModel; import audio.broadcast.BroadcastModel;
import com.jidesoft.swing.JideSplitPane;
import gui.editor.Editor; import gui.editor.Editor;
import icon.IconManager;
import net.coderazzi.filters.gui.AutoChoices;
import net.coderazzi.filters.gui.TableFilterHeader;
import net.miginfocom.swing.MigLayout;
import java.awt.Color; import javax.swing.*;
import java.awt.Component; import javax.swing.event.ListSelectionEvent;
import java.awt.Dimension; import javax.swing.event.ListSelectionListener;
import java.awt.Rectangle; import javax.swing.table.DefaultTableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import net.coderazzi.filters.gui.AutoChoices;
import net.coderazzi.filters.gui.TableFilterHeader;
import net.miginfocom.swing.MigLayout;
import settings.SettingsManager;
import com.jidesoft.swing.JideSplitPane;
public class AliasController extends JPanel public class AliasController extends JPanel
implements ActionListener, ListSelectionListener implements ActionListener, ListSelectionListener
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private AliasModel mAliasModel; private AliasModel mAliasModel;
private JTable mAliasTable; private JTable mAliasTable;
private TableFilterHeader mTableFilterHeader; private TableFilterHeader mTableFilterHeader;
private AliasEditor mAliasEditor; private AliasEditor mAliasEditor;
private MultipleAliasEditor mMultipleAliasEditor; private MultipleAliasEditor mMultipleAliasEditor;
private JideSplitPane mSplitPane; private JideSplitPane mSplitPane;
private static final String NEW_ALIAS = "New"; private static final String NEW_ALIAS = "New";
private static final String COPY_ALIAS = "Copy"; private static final String COPY_ALIAS = "Copy";
private static final String DELETE_ALIAS = "Delete"; private static final String DELETE_ALIAS = "Delete";
private JButton mNewButton = new JButton( NEW_ALIAS ); private JButton mNewButton = new JButton(NEW_ALIAS);
private JButton mCopyButton = new JButton( COPY_ALIAS ); private JButton mCopyButton = new JButton(COPY_ALIAS);
private JButton mDeleteButton = new JButton( DELETE_ALIAS ); private JButton mDeleteButton = new JButton(DELETE_ALIAS);
private IconCellRenderer mIconCellRenderer; private IconCellRenderer mIconCellRenderer;
public AliasController(AliasModel aliasModel, BroadcastModel broadcastModel, SettingsManager settingsManager ) public AliasController(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager)
{ {
mAliasModel = aliasModel; mAliasModel = aliasModel;
mAliasEditor = new AliasEditor( mAliasModel, broadcastModel, settingsManager ); mAliasEditor = new AliasEditor(mAliasModel, broadcastModel, iconManager);
mMultipleAliasEditor = new MultipleAliasEditor( mAliasModel, broadcastModel, settingsManager ); mMultipleAliasEditor = new MultipleAliasEditor(mAliasModel, broadcastModel, iconManager);
mIconCellRenderer = new IconCellRenderer( settingsManager ); mIconCellRenderer = new IconCellRenderer(iconManager);
init(); init();
mAliasModel.addListener( mAliasEditor ); mAliasModel.addListener(mAliasEditor);
} }
private void init() private void init()
{ {
setLayout( new MigLayout( "insets 0 0 0 0", setLayout(new MigLayout("insets 0 0 0 0",
"[grow,fill]", "[grow,fill]",
"[grow,fill]") ); "[grow,fill]"));
//System Configuration View and Editor //System Configuration View and Editor
mAliasTable = new JTable( mAliasModel ); mAliasTable = new JTable(mAliasModel);
mAliasTable.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION ); mAliasTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
mAliasTable.getSelectionModel().addListSelectionListener( this ); mAliasTable.getSelectionModel().addListSelectionListener(this);
mAliasTable.setAutoCreateRowSorter( true ); mAliasTable.setAutoCreateRowSorter(true);
mAliasTable.getColumnModel().getColumn( AliasModel.COLUMN_COLOR ) mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_COLOR)
.setCellRenderer( new ColorCellRenderer() ); .setCellRenderer(new ColorCellRenderer());
mAliasTable.getColumnModel().getColumn( AliasModel.COLUMN_ICON ) mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_ICON)
.setCellRenderer( mIconCellRenderer ); .setCellRenderer(mIconCellRenderer);
mTableFilterHeader = new TableFilterHeader( mAliasTable, AutoChoices.ENABLED ); mTableFilterHeader = new TableFilterHeader(mAliasTable, AutoChoices.ENABLED);
mTableFilterHeader.setFilterOnUpdates( true ); mTableFilterHeader.setFilterOnUpdates(true);
JScrollPane tableScroller = new JScrollPane( mAliasTable ); JScrollPane tableScroller = new JScrollPane(mAliasTable);
JPanel buttonsPanel = new JPanel(); JPanel buttonsPanel = new JPanel();
buttonsPanel.setLayout( buttonsPanel.setLayout(
new MigLayout( "insets 0 0 0 0", "[grow,fill][grow,fill][grow,fill]", "[]") ); new MigLayout("insets 0 0 0 0", "[grow,fill][grow,fill][grow,fill]", "[]"));
mNewButton.addActionListener( this ); mNewButton.addActionListener(this);
mNewButton.setToolTipText( "Adds a new alias" ); mNewButton.setToolTipText("Adds a new alias");
buttonsPanel.add( mNewButton ); buttonsPanel.add(mNewButton);
mCopyButton.addActionListener( this ); mCopyButton.addActionListener(this);
mCopyButton.setEnabled( false ); mCopyButton.setEnabled(false);
mCopyButton.setToolTipText( "Creates a copy of the currently selected alias and adds it" ); mCopyButton.setToolTipText("Creates a copy of the currently selected alias and adds it");
buttonsPanel.add( mCopyButton ); buttonsPanel.add(mCopyButton);
mDeleteButton.addActionListener( this ); mDeleteButton.addActionListener(this);
mDeleteButton.setEnabled( false ); mDeleteButton.setEnabled(false);
mDeleteButton.setToolTipText( "Deletes the currently selected alias" ); mDeleteButton.setToolTipText("Deletes the currently selected alias");
buttonsPanel.add( mDeleteButton ); buttonsPanel.add(mDeleteButton);
JPanel listAndButtonsPanel = new JPanel(); JPanel listAndButtonsPanel = new JPanel();
listAndButtonsPanel.setLayout( listAndButtonsPanel.setLayout(
new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[grow,fill][]") ); new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill][]"));
listAndButtonsPanel.add( tableScroller, "wrap" ); listAndButtonsPanel.add(tableScroller, "wrap");
listAndButtonsPanel.add( buttonsPanel ); listAndButtonsPanel.add(buttonsPanel);
mSplitPane = new JideSplitPane( JideSplitPane.HORIZONTAL_SPLIT ); mSplitPane = new JideSplitPane(JideSplitPane.HORIZONTAL_SPLIT);
mSplitPane.setDividerSize( 5 ); mSplitPane.setDividerSize(5);
mSplitPane.setShowGripper( true ); mSplitPane.setShowGripper(true);
mSplitPane.add( listAndButtonsPanel ); mSplitPane.add(listAndButtonsPanel);
mSplitPane.add( mAliasEditor ); mSplitPane.add(mAliasEditor);
add( mSplitPane ); add(mSplitPane);
} }
/** /**
* Sets the editor argument as the currently visible alias editor * Sets the editor argument as the currently visible alias editor
*/ */
private void setEditor( Editor<?> editor ) private void setEditor(Editor<?> editor)
{ {
if( mSplitPane.getComponentCount() == 3 ) if(mSplitPane.getComponentCount() == 3)
{ {
Component component = mSplitPane.getComponent( 2 ); Component component = mSplitPane.getComponent(2);
if( component instanceof Editor<?> && component != editor ) if(component instanceof Editor<?> && component != editor)
{ {
//Get current divider location so that we can reapply it after //Get current divider location so that we can reapply it after
//changing out the editors, so that the interface doesn't move //changing out the editors, so that the interface doesn't move
int location = mSplitPane.getDividerLocation( 0 ); int location = mSplitPane.getDividerLocation(0);
((Editor<?>)component).setItem( null ); ((Editor<?>) component).setItem(null);
mSplitPane.remove( component ); mSplitPane.remove(component);
editor.setPreferredSize( new Dimension( 100, 100 ) ); editor.setPreferredSize(new Dimension(100, 100));
mSplitPane.add( editor ); mSplitPane.add(editor);
mSplitPane.validate(); mSplitPane.validate();
mSplitPane.setDividerLocation( 0, location ); mSplitPane.setDividerLocation(0, location);
mSplitPane.repaint(); mSplitPane.repaint();
} }
} }
} }
private Alias getAlias( int selectedRow ) private Alias getAlias(int selectedRow)
{ {
if( selectedRow >= 0 ) if(selectedRow >= 0)
{ {
int index = mAliasTable.convertRowIndexToModel( selectedRow ); int index = mAliasTable.convertRowIndexToModel(selectedRow);
return mAliasModel.getAliasAtIndex( index ); return mAliasModel.getAliasAtIndex(index);
} }
return null; return null;
} }
@Override @Override
public void valueChanged( ListSelectionEvent event ) public void valueChanged(ListSelectionEvent event)
{ {
//Limits event firing to only when selection is complete //Limits event firing to only when selection is complete
if( !event.getValueIsAdjusting() ) if(!event.getValueIsAdjusting())
{ {
int[] selectedRows = mAliasTable.getSelectedRows(); int[] selectedRows = mAliasTable.getSelectedRows();
if( selectedRows.length == 0 ) if(selectedRows.length == 0)
{ {
mAliasEditor.setItem( null ); mAliasEditor.setItem(null);
mCopyButton.setEnabled( false ); mCopyButton.setEnabled(false);
mDeleteButton.setEnabled( false ); mDeleteButton.setEnabled(false);
} }
else if( selectedRows.length == 1 ) else if(selectedRows.length == 1)
{ {
setEditor( mAliasEditor ); setEditor(mAliasEditor);
Alias selectedAlias = getAlias( selectedRows[ 0 ] ); Alias selectedAlias = getAlias(selectedRows[0]);
mAliasEditor.setItem( selectedAlias ); mAliasEditor.setItem(selectedAlias);
if( selectedAlias != null ) if(selectedAlias != null)
{ {
mCopyButton.setEnabled( true ); mCopyButton.setEnabled(true);
mDeleteButton.setEnabled( true ); mDeleteButton.setEnabled(true);
} }
else else
{ {
mCopyButton.setEnabled( false ); mCopyButton.setEnabled(false);
mDeleteButton.setEnabled( false ); mDeleteButton.setEnabled(false);
} }
} }
else else
{ {
setEditor( mMultipleAliasEditor ); setEditor(mMultipleAliasEditor);
mCopyButton.setEnabled( true ); mCopyButton.setEnabled(true);
mDeleteButton.setEnabled( true ); mDeleteButton.setEnabled(true);
List<Alias> selectedAliases = new ArrayList<Alias>(); List<Alias> selectedAliases = new ArrayList<Alias>();
for( int selectedRow: selectedRows ) for(int selectedRow : selectedRows)
{ {
Alias alias = getAlias( selectedRow ); Alias alias = getAlias(selectedRow);
selectedAliases.add( alias ); selectedAliases.add(alias);
} }
mMultipleAliasEditor.setItem( selectedAliases ); mMultipleAliasEditor.setItem(selectedAliases);
} }
} }
} }
/** /**
* Adds the alias to the alias table/model and scrolls the view it * Adds the alias to the alias table/model and scrolls the view it
*/ */
private void addAlias( Alias alias ) private void addAlias(Alias alias)
{ {
//HACK: when inserting a row to the model, the JTable gets //HACK: when inserting a row to the model, the JTable gets
//notified and attempts to tell the coderazzi table filter //notified and attempts to tell the coderazzi table filter
//adaptive choices filter to refresh before the table filter is //adaptive choices filter to refresh before the table filter is
//notified of the row additions, causing an index out of bounds //notified of the row additions, causing an index out of bounds
//exception. We turn off adaptive choices temporarily, add the //exception. We turn off adaptive choices temporarily, add the
//channel, and turn on adaptive choices again. //channel, and turn on adaptive choices again.
mTableFilterHeader.setAdaptiveChoices( false ); mTableFilterHeader.setAdaptiveChoices(false);
int index = mAliasModel.addAlias( alias ); int index = mAliasModel.addAlias(alias);
mTableFilterHeader.setAdaptiveChoices( true ); mTableFilterHeader.setAdaptiveChoices(true);
if( index >= 0 ) if(index >= 0)
{ {
int translatedIndex = mAliasTable.convertRowIndexToView( index ); int translatedIndex = mAliasTable.convertRowIndexToView(index);
mAliasTable.setRowSelectionInterval( translatedIndex, translatedIndex ); mAliasTable.setRowSelectionInterval(translatedIndex, translatedIndex);
mAliasTable.scrollRectToVisible( mAliasTable.scrollRectToVisible(
new Rectangle( mAliasTable.getCellRect( translatedIndex, 0, true ) ) ); new Rectangle(mAliasTable.getCellRect(translatedIndex, 0, true)));
} }
} }
private List<Alias> getSelectedAliases() private List<Alias> getSelectedAliases()
{ {
List<Alias> selected = new ArrayList<>(); List<Alias> selected = new ArrayList<>();
int[] rows = mAliasTable.getSelectedRows(); int[] rows = mAliasTable.getSelectedRows();
for( int row: rows ) for(int row : rows)
{ {
if( row >= 0 ) if(row >= 0)
{ {
Alias alias = mAliasModel.getAliasAtIndex( mAliasTable.convertRowIndexToModel( row ) ); Alias alias = mAliasModel.getAliasAtIndex(mAliasTable.convertRowIndexToModel(row));
if( alias != null ) if(alias != null)
{ {
selected.add( alias ); selected.add(alias);
} }
} }
} }
return selected; return selected;
} }
/** /**
* Responds to New, Copy and Delete Channel button invocations * Responds to New, Copy and Delete Channel button invocations
*/ */
@Override @Override
public void actionPerformed( ActionEvent event ) public void actionPerformed(ActionEvent event)
{ {
switch( event.getActionCommand() ) switch(event.getActionCommand())
{ {
case NEW_ALIAS: case NEW_ALIAS:
addAlias( new Alias( "New Alias" ) ); addAlias(new Alias("New Alias"));
break; break;
case COPY_ALIAS: case COPY_ALIAS:
for( Alias alias: getSelectedAliases() ) for(Alias alias : getSelectedAliases())
{ {
addAlias( AliasFactory.copyOf( alias ) ); addAlias(AliasFactory.copyOf(alias));
} }
break; break;
case DELETE_ALIAS: case DELETE_ALIAS:
List<Alias> toDelete = getSelectedAliases(); List<Alias> toDelete = getSelectedAliases();
if( toDelete != null && !toDelete.isEmpty() ) if(toDelete != null && !toDelete.isEmpty())
{ {
String title = toDelete.size() == 1 ? "Delete Alias?" : "Delete Aliases?"; String title = toDelete.size() == 1 ? "Delete Alias?" : "Delete Aliases?";
String prompt = toDelete.size() == 1 ? "Do you want to delete this alias?" : String prompt = toDelete.size() == 1 ? "Do you want to delete this alias?" :
"Do you want to delete these " + toDelete.size() + " aliases?"; "Do you want to delete these " + toDelete.size() + " aliases?";
int choice = JOptionPane.showConfirmDialog( AliasController.this, int choice = JOptionPane.showConfirmDialog(AliasController.this,
prompt, title, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE ); prompt, title, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if( choice == JOptionPane.YES_OPTION ) if(choice == JOptionPane.YES_OPTION)
{ {
for( Alias alias: toDelete ) for(Alias alias : toDelete)
{ {
mAliasModel.removeAlias( alias ); mAliasModel.removeAlias(alias);
} }
} }
} }
break; break;
default: default:
break; break;
} }
} }
/** /**
* Colorizes the cell based on the cell's integer value * Colorizes the cell based on the cell's integer value
*/ */
public class ColorCellRenderer extends DefaultTableCellRenderer public class ColorCellRenderer extends DefaultTableCellRenderer
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Override @Override
public Component getTableCellRendererComponent( JTable table, public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, Object value, boolean isSelected, boolean hasFocus, int row,
int column ) int column)
{ {
JLabel label = (JLabel)super.getTableCellRendererComponent( table, JLabel label = (JLabel) super.getTableCellRendererComponent(table,
value, isSelected, hasFocus, row, column ); value, isSelected, hasFocus, row, column);
label.setBackground( new Color( (int)value ) ); label.setBackground(new Color((int) value));
label.setText( "" ); label.setText("");
return label; return label;
} }
} }
/** /**
* Displays cell's icon and name * Displays cell's icon and name
*/ */
public class IconCellRenderer extends DefaultTableCellRenderer public class IconCellRenderer extends DefaultTableCellRenderer
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private SettingsManager mSettingsManager; private IconManager mIconManager;
public IconCellRenderer( SettingsManager settingsManager ) public IconCellRenderer(IconManager iconManager)
{ {
mSettingsManager = settingsManager; mIconManager = iconManager;
} }
@Override @Override
public Component getTableCellRendererComponent( JTable table, public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, Object value, boolean isSelected, boolean hasFocus, int row,
int column ) int column)
{ {
JLabel label = (JLabel)super.getTableCellRendererComponent( table, JLabel label = (JLabel) super.getTableCellRendererComponent(table,
value, isSelected, hasFocus, row, column ); value, isSelected, hasFocus, row, column);
ImageIcon icon = mSettingsManager.getImageIcon( label.getText(), 12 ); ImageIcon icon = mIconManager.getIcon(label.getText(), 12);
if( icon != null ) if(icon != null)
{ {
label.setIcon( icon ); label.setIcon(icon);
} }
return label; return label;
} }
} }
} }

View File

@@ -28,6 +28,7 @@ import javax.swing.JButton;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JSeparator; import javax.swing.JSeparator;
import icon.IconManager;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import sample.Listener; import sample.Listener;
import settings.SettingsManager; import settings.SettingsManager;
@@ -50,10 +51,10 @@ public class AliasEditor extends Editor<Alias>
private AliasIdentifierEditor mAliasIdentifierEditor; private AliasIdentifierEditor mAliasIdentifierEditor;
private AliasActionEditor mAliasActionEditor; private AliasActionEditor mAliasActionEditor;
public AliasEditor(AliasModel aliasModel, BroadcastModel broadcastModel, SettingsManager settingsManager ) public AliasEditor(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager )
{ {
mAliasModel = aliasModel; mAliasModel = aliasModel;
mAliasNameEditor = new AliasNameEditor( mAliasModel, settingsManager ); mAliasNameEditor = new AliasNameEditor( mAliasModel, iconManager );
mAliasIdentifierEditor = new AliasIdentifierEditor( aliasModel, broadcastModel ); mAliasIdentifierEditor = new AliasIdentifierEditor( aliasModel, broadcastModel );
mAliasActionEditor = new AliasActionEditor( aliasModel ); mAliasActionEditor = new AliasActionEditor( aliasModel );

View File

@@ -1,291 +1,278 @@
package alias; package alias;
import alias.AliasEvent.Event;
import gui.editor.Editor; import gui.editor.Editor;
import icon.Icon;
import icon.IconCellRenderer;
import icon.IconManager;
import map.MapIcon;
import net.miginfocom.swing.MigLayout;
import settings.SettingsManager;
import java.awt.Color; import javax.swing.*;
import java.awt.Dimension; import javax.swing.event.DocumentEvent;
import java.awt.EventQueue; import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.List; import java.util.List;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import map.IconManager;
import map.MapIcon;
import map.MapIconListCellRenderer;
import net.miginfocom.swing.MigLayout;
import settings.SettingsManager;
import alias.AliasEvent.Event;
public class AliasNameEditor extends Editor<Alias> public class AliasNameEditor extends Editor<Alias>
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static ComboBoxModel<String> EMPTY_MODEL = new DefaultComboBoxModel<>(); private static ComboBoxModel<String> EMPTY_MODEL = new DefaultComboBoxModel<>();
private JComboBox<String> mListCombo = new JComboBox<>( EMPTY_MODEL ); private JComboBox<String> mListCombo = new JComboBox<>(EMPTY_MODEL);
private JComboBox<String> mGroupCombo = new JComboBox<>( EMPTY_MODEL ); private JComboBox<String> mGroupCombo = new JComboBox<>(EMPTY_MODEL);
private JComboBox<MapIcon> mMapIconCombo; private JComboBox<Icon> mIconCombo;
private JTextField mName; private JTextField mName;
private JButton mButtonColor; private JButton mButtonColor;
private JButton mBtnIconManager; private JButton mBtnIconManager;
private AliasModel mAliasModel; private AliasModel mAliasModel;
private SettingsManager mSettingsManager; private IconManager mIconManager;
public AliasNameEditor( AliasModel aliasModel, SettingsManager settingsManager ) public AliasNameEditor(AliasModel aliasModel, IconManager iconManager)
{ {
mAliasModel = aliasModel; mAliasModel = aliasModel;
mSettingsManager = settingsManager; mIconManager = iconManager;
init();
}
private void init() init();
{ }
setLayout( new MigLayout( "fill,wrap 2", "[right][grow,fill]",
"[][][][][][][grow]" ) );
add( new JLabel( "Name:" ) ); private void init()
mName = new JTextField(); {
mName.getDocument().addDocumentListener( new DocumentListener() setLayout(new MigLayout("fill,wrap 2", "[right][grow,fill]",
{ "[][][][][][][grow]"));
@Override
public void removeUpdate( DocumentEvent e )
{
setModified( true );
}
@Override add(new JLabel("Name:"));
public void insertUpdate( DocumentEvent e ) mName = new JTextField();
{ mName.getDocument().addDocumentListener(new DocumentListener()
setModified( true ); {
} @Override
public void removeUpdate(DocumentEvent e)
@Override
public void changedUpdate( DocumentEvent e ){}
} );
add( mName, "wrap" );
add( new JLabel( "List:" ) );
mListCombo.setEditable( true );
mListCombo.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
if( mListCombo.getSelectedItem() != null )
{
List<String> groups = mAliasModel
.getGroupNames( (String)mListCombo.getSelectedItem() );
if( groups.isEmpty() )
{
mGroupCombo.setModel( EMPTY_MODEL );
}
else
{
mGroupCombo.setModel( new DefaultComboBoxModel<String>(
groups.toArray( new String[ groups.size() ] ) ) );;
}
}
setModified( true );
}
} );
add( mListCombo, "wrap" );
add( new JLabel( "Group:" ) );
mGroupCombo.setEditable( true );
mGroupCombo.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
setModified( true );
}
} );
add( mGroupCombo, "wrap" );
add( new JLabel( "Color:" ) );
mButtonColor = new JButton( "Select ..." );
mButtonColor.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{ {
Color newColor = JColorChooser.showDialog( setModified(true);
AliasNameEditor.this,
"Choose color for this alias",
( hasItem() ? getItem().getMapColor() : null ) );
if( newColor != null )
{
mButtonColor.setForeground( newColor );
mButtonColor.setBackground( newColor );
setModified( true );
}
} }
} );
add( mButtonColor, "wrap" );
add( new JLabel( "Icon:" ) ); @Override
public void insertUpdate(DocumentEvent e)
mMapIconCombo = new JComboBox<MapIcon>( mSettingsManager.getMapIcons() );
MapIconListCellRenderer renderer = new MapIconListCellRenderer();
renderer.setPreferredSize( new Dimension( 200, 30 ) );
mMapIconCombo.setRenderer( renderer );
mMapIconCombo.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
setModified( true );
}
} );
add( mMapIconCombo, "wrap" );
//Dummy place holder
add( new JLabel() );
mBtnIconManager = new JButton( "Icon Manager" );
mBtnIconManager.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
{ {
final IconManager iconManager = setModified(true);
new IconManager( mSettingsManager, AliasNameEditor.this );
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
iconManager.setVisible( true );
}
} );
} }
} );
add( mBtnIconManager, "span 2,wrap" ); @Override
public void changedUpdate(DocumentEvent e)
{
}
});
add(mName, "wrap");
setModified( false ); add(new JLabel("List:"));
} mListCombo.setEditable(true);
mListCombo.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
if(mListCombo.getSelectedItem() != null)
{
List<String> groups = mAliasModel
.getGroupNames((String) mListCombo.getSelectedItem());
@Override if(groups.isEmpty())
public void setItem( Alias alias ) {
{ mGroupCombo.setModel(EMPTY_MODEL);
super.setItem( alias ); }
else
{
mGroupCombo.setModel(new DefaultComboBoxModel<String>(
groups.toArray(new String[groups.size()])));
;
}
}
if( hasItem() ) setModified(true);
{ }
mName.setText( alias.getName() ); });
add(mListCombo, "wrap");
List<String> listNames = mAliasModel.getListNames(); add(new JLabel("Group:"));
mGroupCombo.setEditable(true);
mGroupCombo.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
setModified(true);
}
});
add(mGroupCombo, "wrap");
if( listNames.isEmpty() ) add(new JLabel("Color:"));
{
mListCombo.setModel( EMPTY_MODEL );
}
else
{
mListCombo.setModel( new DefaultComboBoxModel<String>(
listNames.toArray( new String[ listNames.size() ] ) ) );;
}
mListCombo.setSelectedItem( alias.getList() ); mButtonColor = new JButton("Select ...");
mButtonColor.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
Color newColor = JColorChooser.showDialog(
AliasNameEditor.this,
"Choose color for this alias",
(hasItem() ? getItem().getMapColor() : null));
List<String> groupNames = mAliasModel.getGroupNames( alias.getList() ); if(newColor != null)
{
mButtonColor.setForeground(newColor);
mButtonColor.setBackground(newColor);
if( groupNames.isEmpty() ) setModified(true);
{ }
mGroupCombo.setModel( EMPTY_MODEL ); }
} });
else add(mButtonColor, "wrap");
{
mGroupCombo.setModel( new DefaultComboBoxModel<String>(
groupNames.toArray( new String[ groupNames.size() ] ) ) );;
}
mGroupCombo.setSelectedItem( alias.getGroup() ); add(new JLabel("Icon:"));
Color color = alias.getMapColor(); mIconCombo = new JComboBox<Icon>(mIconManager.getIcons());
mButtonColor.setBackground( color ); IconCellRenderer renderer = new IconCellRenderer(mIconManager);
mButtonColor.setForeground( color ); renderer.setPreferredSize(new Dimension(200, 30));
mIconCombo.setRenderer( renderer );
mIconCombo.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
setModified(true);
}
});
String iconName = alias.getIconName(); add(mIconCombo, "wrap");
if( iconName == null ) //Dummy place holder
{ add(new JLabel());
iconName = SettingsManager.DEFAULT_ICON;
}
MapIcon savedIcon = mSettingsManager.getMapIcon( iconName ); mBtnIconManager = new JButton("Icon Manager");
mBtnIconManager.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent arg0)
{
mIconManager.showEditor(AliasNameEditor.this);
}
});
if( savedIcon != null ) add(mBtnIconManager, "span 2,wrap");
{
mMapIconCombo.setSelectedItem( savedIcon );
}
}
else
{
mListCombo.setModel( EMPTY_MODEL );
mGroupCombo.setModel( EMPTY_MODEL );
mName.setText( null );
mButtonColor.setBackground( getBackground() ); setModified(false);
mButtonColor.setForeground( getForeground() ); }
}
repaint(); @Override
public void setItem(Alias alias)
{
super.setItem(alias);
setModified( false ); if(hasItem())
} {
mName.setText(alias.getName());
@Override List<String> listNames = mAliasModel.getListNames();
public void save()
{
if( hasItem() && isModified() )
{
Alias alias = getItem();
if( mListCombo.getSelectedItem() != null ) if(listNames.isEmpty())
{ {
alias.setList( (String)mListCombo.getSelectedItem() ); mListCombo.setModel(EMPTY_MODEL);
} }
else
{
mListCombo.setModel(new DefaultComboBoxModel<String>(
listNames.toArray(new String[listNames.size()])));
;
}
if( mGroupCombo.getSelectedItem() != null ) mListCombo.setSelectedItem(alias.getList());
{
alias.setGroup( (String)mGroupCombo.getSelectedItem() );
}
alias.setName( mName.getText() ); List<String> groupNames = mAliasModel.getGroupNames(alias.getList());
alias.setColor( mButtonColor.getBackground().getRGB() ); if(groupNames.isEmpty())
{
mGroupCombo.setModel(EMPTY_MODEL);
}
else
{
mGroupCombo.setModel(new DefaultComboBoxModel<String>(
groupNames.toArray(new String[groupNames.size()])));
;
}
if( mMapIconCombo.getSelectedItem() != null ) mGroupCombo.setSelectedItem(alias.getGroup());
{
alias.setIconName( ((MapIcon)mMapIconCombo.getSelectedItem()).getName() );
}
setModified( false ); Color color = alias.getMapColor();
//Broadcast an alias change event to save the updates mButtonColor.setBackground(color);
mAliasModel.broadcast( new AliasEvent( getItem(), Event.CHANGE ) ); mButtonColor.setForeground(color);
}
} String iconName = alias.getIconName();
if(iconName == null)
{
iconName = SettingsManager.DEFAULT_ICON;
}
Icon savedIcon = mIconManager.getModel().getIcon(iconName);
if(savedIcon != null)
{
mIconCombo.setSelectedItem(savedIcon);
}
}
else
{
mListCombo.setModel(EMPTY_MODEL);
mGroupCombo.setModel(EMPTY_MODEL);
mName.setText(null);
mButtonColor.setBackground(getBackground());
mButtonColor.setForeground(getForeground());
}
repaint();
setModified(false);
}
@Override
public void save()
{
if(hasItem() && isModified())
{
Alias alias = getItem();
if(mListCombo.getSelectedItem() != null)
{
alias.setList((String) mListCombo.getSelectedItem());
}
if(mGroupCombo.getSelectedItem() != null)
{
alias.setGroup((String) mGroupCombo.getSelectedItem());
}
alias.setName(mName.getText());
alias.setColor(mButtonColor.getBackground().getRGB());
if(mIconCombo.getSelectedItem() != null)
{
alias.setIconName(((MapIcon) mIconCombo.getSelectedItem()).getName());
}
setModified(false);
//Broadcast an alias change event to save the updates
mAliasModel.broadcast(new AliasEvent(getItem(), Event.CHANGE));
}
}
} }

View File

@@ -3,14 +3,13 @@ package alias;
import alias.id.AliasIDType; import alias.id.AliasIDType;
import alias.id.broadcast.BroadcastChannel; import alias.id.broadcast.BroadcastChannel;
import audio.broadcast.BroadcastModel; import audio.broadcast.BroadcastModel;
import com.sun.org.apache.xpath.internal.operations.Mult;
import gui.editor.Editor; import gui.editor.Editor;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultComboBoxModel;
@@ -24,16 +23,16 @@ import javax.swing.JSlider;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import map.IconManager; import icon.Icon;
import icon.IconManager;
import map.MapIcon; import map.MapIcon;
import map.MapIconListCellRenderer; import icon.IconCellRenderer;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sample.Listener; import sample.Listener;
import settings.SettingsManager;
import alias.AliasEvent.Event; import alias.AliasEvent.Event;
import alias.id.priority.Priority; import alias.id.priority.Priority;
@@ -54,7 +53,7 @@ public class MultipleAliasEditor extends Editor<List<Alias>>
private JCheckBox mGroupCheckBox = new JCheckBox("Group"); private JCheckBox mGroupCheckBox = new JCheckBox("Group");
private JComboBox<String> mGroupCombo = new JComboBox<>(); private JComboBox<String> mGroupCombo = new JComboBox<>();
private JCheckBox mIconCheckBox = new JCheckBox("Icon"); private JCheckBox mIconCheckBox = new JCheckBox("Icon");
private JComboBox<MapIcon> mMapIconCombo; private JComboBox<Icon> mIconCombo;
private JCheckBox mColorCheckBox = new JCheckBox("Color"); private JCheckBox mColorCheckBox = new JCheckBox("Color");
private JButton mButtonColor; private JButton mButtonColor;
private JButton mBtnIconManager; private JButton mBtnIconManager;
@@ -68,13 +67,13 @@ public class MultipleAliasEditor extends Editor<List<Alias>>
private AliasModel mAliasModel; private AliasModel mAliasModel;
private BroadcastModel mBroadcastModel; private BroadcastModel mBroadcastModel;
private SettingsManager mSettingsManager; private IconManager mIconManager;
public MultipleAliasEditor(AliasModel aliasModel, BroadcastModel broadcastModel, SettingsManager settingsManager) public MultipleAliasEditor(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager)
{ {
mAliasModel = aliasModel; mAliasModel = aliasModel;
mBroadcastModel = broadcastModel; mBroadcastModel = broadcastModel;
mSettingsManager = settingsManager; mIconManager = iconManager;
mAliasModel.addListener(this); mAliasModel.addListener(this);
@@ -139,12 +138,12 @@ public class MultipleAliasEditor extends Editor<List<Alias>>
add(mIconCheckBox); add(mIconCheckBox);
mMapIconCombo = new JComboBox<MapIcon>(mSettingsManager.getMapIcons()); mIconCombo = new JComboBox<Icon>(mIconManager.getIcons());
MapIconListCellRenderer renderer = new MapIconListCellRenderer(); IconCellRenderer renderer = new IconCellRenderer(mIconManager);
renderer.setPreferredSize(new Dimension(200, 30)); renderer.setPreferredSize(new Dimension(200, 30));
mMapIconCombo.setRenderer(renderer); mIconCombo.setRenderer(renderer);
add(mMapIconCombo, "wrap"); add(mIconCombo, "wrap");
//Dummy place holder //Dummy place holder
add(new JLabel()); add(new JLabel());
@@ -155,17 +154,7 @@ public class MultipleAliasEditor extends Editor<List<Alias>>
@Override @Override
public void actionPerformed(ActionEvent arg0) public void actionPerformed(ActionEvent arg0)
{ {
final IconManager iconManager = mIconManager.showEditor(MultipleAliasEditor.this);
new IconManager(mSettingsManager, MultipleAliasEditor.this);
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
iconManager.setVisible(true);
}
});
} }
}); });
@@ -363,9 +352,9 @@ public class MultipleAliasEditor extends Editor<List<Alias>>
if (mIconCheckBox.isSelected()) if (mIconCheckBox.isSelected())
{ {
if (mMapIconCombo.getSelectedItem() != null) if (mIconCombo.getSelectedItem() != null)
{ {
alias.setIconName(((MapIcon) mMapIconCombo.getSelectedItem()).getName()); alias.setIconName(((MapIcon) mIconCombo.getSelectedItem()).getName());
} }
else else
{ {

View File

@@ -29,6 +29,7 @@ import javax.swing.event.ChangeListener;
import audio.broadcast.BroadcastModel; import audio.broadcast.BroadcastModel;
import audio.broadcast.BroadcastPanel; import audio.broadcast.BroadcastPanel;
import icon.IconManager;
import map.MapPanel; import map.MapPanel;
import map.MapService; import map.MapService;
import module.decode.event.CallEventPanel; import module.decode.event.CallEventPanel;
@@ -78,6 +79,7 @@ public class ControllerPanel extends JPanel
ChannelModel channelModel, ChannelModel channelModel,
ChannelMapModel channelMapModel, ChannelMapModel channelMapModel,
ChannelProcessingManager channelProcessingManager, ChannelProcessingManager channelProcessingManager,
IconManager iconManager,
MapService mapService, MapService mapService,
SettingsManager settingsManager, SettingsManager settingsManager,
SourceManager sourceManager, SourceManager sourceManager,
@@ -104,8 +106,7 @@ public class ControllerPanel extends JPanel
mChannelController = new ChannelController(channelModel, channelMapModel, mChannelController = new ChannelController(channelModel, channelMapModel,
sourceManager, aliasModel); sourceManager, aliasModel);
mAliasController = new AliasController(aliasModel, broadcastModel, settingsManager); mAliasController = new AliasController(aliasModel, broadcastModel, iconManager);
mTunerManagerPanel = new TunerViewPanel(tunerModel); mTunerManagerPanel = new TunerViewPanel(tunerModel);
init(); init();

View File

@@ -30,7 +30,7 @@ import controller.channel.ChannelModel;
import controller.channel.ChannelProcessingManager; import controller.channel.ChannelProcessingManager;
import controller.channel.ChannelSelectionManager; import controller.channel.ChannelSelectionManager;
import controller.channel.map.ChannelMapModel; import controller.channel.map.ChannelMapModel;
import map.IconManager; import icon.IconManager;
import map.MapService; import map.MapService;
import module.log.EventLogManager; import module.log.EventLogManager;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
@@ -66,6 +66,7 @@ public class SDRTrunk implements Listener<TunerEvent>
{ {
private final static Logger mLog = LoggerFactory.getLogger(SDRTrunk.class); private final static Logger mLog = LoggerFactory.getLogger(SDRTrunk.class);
private IconManager mIconManager;
private ControllerPanel mControllerPanel; private ControllerPanel mControllerPanel;
private SettingsManager mSettingsManager; private SettingsManager mSettingsManager;
private SpectralDisplayPanel mSpectralPanel; private SpectralDisplayPanel mSpectralPanel;
@@ -105,6 +106,8 @@ public class SDRTrunk implements Listener<TunerEvent>
ThreadPoolManager threadPoolManager = new ThreadPoolManager(); ThreadPoolManager threadPoolManager = new ThreadPoolManager();
mIconManager = new IconManager(threadPoolManager);
mSettingsManager = new SettingsManager(threadPoolManager, tunerConfigurationModel); mSettingsManager = new SettingsManager(threadPoolManager, tunerConfigurationModel);
AliasModel aliasModel = new AliasModel(); AliasModel aliasModel = new AliasModel();
@@ -144,7 +147,7 @@ public class SDRTrunk implements Listener<TunerEvent>
channelProcessingManager.addMessageListener(mapService); channelProcessingManager.addMessageListener(mapService);
mControllerPanel = new ControllerPanel(audioManager, aliasModel, broadcastModel, mControllerPanel = new ControllerPanel(audioManager, aliasModel, broadcastModel,
channelModel, channelMapModel, channelProcessingManager, channelModel, channelMapModel, channelProcessingManager, mIconManager,
mapService, mSettingsManager, sourceManager, tunerModel); mapService, mSettingsManager, sourceManager, tunerModel);
mSpectralPanel = new SpectralDisplayPanel(channelModel, mSpectralPanel = new SpectralDisplayPanel(channelModel,
@@ -268,16 +271,7 @@ public class SDRTrunk implements Listener<TunerEvent>
@Override @Override
public void actionPerformed(ActionEvent arg0) public void actionPerformed(ActionEvent arg0)
{ {
final IconManager iconManager = new IconManager(mSettingsManager, mMainGui); mIconManager.showEditor(mMainGui);
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
iconManager.setVisible(true);
}
});
} }
}); });
fileMenu.add(settingsMenu); fileMenu.add(settingsMenu);

99
src/icon/Icon.java Normal file
View File

@@ -0,0 +1,99 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
package icon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
@XmlRootElement(name = "icon")
public class Icon implements Comparable<Icon>
{
private final static Logger mLog = LoggerFactory.getLogger(Icon.class);
protected String mName;
private String mPath;
private ImageIcon mImageIcon;
public Icon()
{
//No-arg JAXB constructor
}
public Icon(String name, String path)
{
mName = name;
mPath = path;
}
@XmlAttribute(name = "name")
public String getName()
{
return mName;
}
public void setName(String name)
{
mName = name;
}
public String toString()
{
return mName;
}
@XmlAttribute(name = "path")
public String getPath()
{
return mPath;
}
public void setPath(String path)
{
mPath = path;
}
@XmlTransient
public ImageIcon getIcon()
{
if(mImageIcon == null && mPath != null)
{
try
{
mImageIcon = new ImageIcon(mPath);
}
catch(Exception e)
{
mLog.error("Error loading Icon [" + mPath + "]", e);
}
}
return mImageIcon;
}
@Override
public int compareTo(Icon otherIcon)
{
return getName().compareTo(otherIcon.getName());
}
}

View File

@@ -0,0 +1,64 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
package icon;
import javax.swing.*;
import java.awt.*;
public class IconCellRenderer extends JLabel implements ListCellRenderer<Icon>
{
private static final long serialVersionUID = 1L;
private IconManager mIconManager;
public IconCellRenderer(IconManager iconManager)
{
mIconManager = iconManager;
setOpaque(true);
}
@Override
public Component getListCellRendererComponent(JList<? extends Icon> list, Icon icon, int index,
boolean isSelected, boolean cellHasFocus)
{
setIcon(mIconManager.getIcon(icon.getName(), 24));
if(icon == mIconManager.getModel().getDefaultIcon())
{
setText(icon.toString() + " (default)");
}
else
{
setText(icon.toString());
}
if(isSelected)
{
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
}
else
{
setBackground(list.getBackground());
setForeground(list.getForeground());
}
return this;
}
}

432
src/icon/IconManager.java Normal file
View File

@@ -0,0 +1,432 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
package icon;
import controller.ThreadPoolManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public class IconManager
{
private final static Logger mLog = LoggerFactory.getLogger(IconManager.class);
private Path mIconFolderPath;
private Path mIconFilePath;
private Path mIconBackupFilePath;
private Path mIconLockFilePath;
private ThreadPoolManager mThreadPoolManager;
private IconViewer mIconViewer;
private IconModel mIconModel;
private AtomicBoolean mSavingIcons = new AtomicBoolean();
private Map<String, ImageIcon> mResizedIcons = new HashMap<>();
public IconManager(ThreadPoolManager threadPoolManager)
{
mThreadPoolManager = threadPoolManager;
}
/**
* Display the icon editor centered over the specified component.
*
* @param centerOnComponent to center the editor
*/
public void showEditor(Component centerOnComponent)
{
if(mIconViewer == null)
{
mIconViewer = new IconViewer(this);
mIconViewer.setLocationRelativeTo(centerOnComponent);
if(mIconViewer.isVisible())
{
mIconViewer.requestFocus();
}
else
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
mIconViewer.setVisible(true);
}
});
}
}
}
public IconModel getModel()
{
if(mIconModel == null)
{
IconSet loadedIcons = load();
mIconModel = new IconModel(loadedIcons);
mIconModel.addListDataListener(new ListDataListener()
{
@Override
public void intervalAdded(ListDataEvent e)
{
scheduleSave();
}
@Override
public void intervalRemoved(ListDataEvent e)
{
scheduleSave();
}
@Override
public void contentsChanged(ListDataEvent e)
{
scheduleSave();
}
});
}
return mIconModel;
}
/**
* All icons in a sorted array
*/
public Icon[] getIcons()
{
return getModel().getIconsAsArray();
}
/**
* Returns named icon scaled to the specified height. Utilizes an internal map to retain scaled icons so that they
* are only scaled/generated once.
*
* @param name - name of icon
* @param height - height of icon in pixels
* @return - scaled named icon (if it exists) or a scaled version of the default icon
*/
public ImageIcon getIcon(String name, int height)
{
if(name == null)
{
name = getModel().getDefaultIcon().getName();
}
String scaledIconName = name + height;
if(mResizedIcons.containsKey(scaledIconName))
{
return mResizedIcons.get(scaledIconName);
}
Icon icon = getModel().getIcon(name);
ImageIcon scaledIcon = getScaledIcon(icon.getIcon(), height);
mResizedIcons.put(scaledIconName, scaledIcon);
return scaledIcon;
}
/**
* Scales the icon to the new pixel height value
*
* @param original image icon
* @param height new height to scale the image (width will be scaled accordingly)
* @return
*/
private static ImageIcon getScaledIcon(ImageIcon original, int height)
{
double scale = (double) original.getIconHeight() / (double) height;
int scaledWidth = (int) ((double) original.getIconWidth() / scale);
Image scaledImage = original.getImage().getScaledInstance(scaledWidth,
height, java.awt.Image.SCALE_SMOOTH);
return new ImageIcon(scaledImage);
}
/**
* Folder where icon, backup and lock files are stored
*/
private Path getIconFolderPath()
{
if(mIconFolderPath == null)
{
SystemProperties props = SystemProperties.getInstance();
mIconFolderPath = props.getApplicationFolder("settings");
}
return mIconFolderPath;
}
/**
* Path to current icon file
*/
private Path getIconFilePath()
{
if(mIconFilePath == null)
{
mIconFilePath = getIconFolderPath().resolve("icons.xml");
}
return mIconFilePath;
}
/**
* Path to most recent playlist backup
*/
private Path getIconBackupFilePath()
{
if(mIconBackupFilePath == null)
{
mIconBackupFilePath = getIconFolderPath().resolve("icons.backup");
}
return mIconBackupFilePath;
}
/**
* Path to playlist lock file that is created prior to saving a playlist and removed immediately thereafter.
* Presence of a lock file indicates an incomplete or corrupt playlist file on startup.
*/
private Path getIconLockFilePath()
{
if(mIconLockFilePath == null)
{
mIconLockFilePath = getIconFolderPath().resolve("icons.lock");
}
return mIconLockFilePath;
}
/**
* Saves the current playlist
*/
private void save()
{
IconSet iconSet = getModel().getIconSet();
JAXBContext context = null;
//Create a backup copy of the current playlist
if(Files.exists(getIconFilePath()))
{
try
{
Files.copy(getIconFilePath(), getIconBackupFilePath(), StandardCopyOption.REPLACE_EXISTING);
}
catch(Exception e)
{
mLog.error("Error creating backup copy of current icons prior to saving updates [" +
getIconFilePath().toString() + "]", e);
}
}
//Create a temporary lock file to signify that we're in the process of updating the playlist
if(!Files.exists(getIconLockFilePath()))
{
try
{
Files.createFile(getIconLockFilePath());
}
catch(IOException e)
{
mLog.error("Error creating temporary lock file prior to saving icons [" +
getIconLockFilePath().toString() + "]", e);
}
}
try(OutputStream out = Files.newOutputStream(getIconFilePath()))
{
context = JAXBContext.newInstance(IconSet.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(iconSet, out);
out.flush();
//Remove the playlist lock file to indicate that we successfully saved the file
if(Files.exists(getIconLockFilePath()))
{
Files.delete(getIconLockFilePath());
}
}
catch(JAXBException je)
{
mLog.error("JAXB exception while serializing icons to a file [" + getIconFilePath().toString() + "]", je);
}
catch(IOException ioe)
{
mLog.error("IO error while writing icons to a file [" + getIconFilePath().toString() + "]", ioe);
}
catch(Exception e)
{
mLog.error("Error while saving icons [" + getIconFilePath().toString() + "]", e);
}
}
/**
* Loads icons from file or creates a default set of icons
*/
public IconSet load()
{
mLog.info("loading icons file [" + getIconFilePath().toString() + "]");
IconSet iconSet = null;
//Check for a lock file that indicates the previous save attempt was incomplete or had an error
if(Files.exists(getIconLockFilePath()))
{
try
{
//Remove the previous icons file
Files.delete(getIconFilePath());
//Copy the backup file to restore the previous icons file
if(Files.exists(getIconBackupFilePath()))
{
Files.copy(getIconBackupFilePath(), getIconFilePath());
}
//Remove the lock file
Files.delete(getIconLockFilePath());
}
catch(IOException ioe)
{
mLog.error("Previous icons save attempt was incomplete and there was an error restoring the " +
"icons backup file", ioe);
}
}
if(Files.exists(getIconFilePath()))
{
JAXBContext context = null;
try(InputStream in = Files.newInputStream(getIconFilePath()))
{
context = JAXBContext.newInstance(IconSet.class);
Unmarshaller m = context.createUnmarshaller();
iconSet = (IconSet) m.unmarshal(in);
}
catch(JAXBException je)
{
mLog.error("JAXB exception while loading/unmarshalling icons", je);
}
catch(IOException ioe)
{
mLog.error("IO error while reading icons file", ioe);
}
}
else
{
mLog.info("Icons file not found at [" + getIconFilePath().toString() + "]");
}
if(iconSet == null)
{
iconSet = getDefaultIconSet();
}
return iconSet;
}
/**
* Creates a default icon set
*/
private IconSet getDefaultIconSet()
{
IconSet iconSet = new IconSet();
Icon defaultIcon = new Icon(IconModel.DEFAULT_ICON, "images/no_icon.png");
iconSet.add(defaultIcon);
iconSet.setDefaultIcon(defaultIcon.getName());
iconSet.add(new Icon("Ambulance", "images/ambulance.png"));
iconSet.add(new Icon("Block Truck", "images/concrete_block_truck.png"));
iconSet.add(new Icon("CWID", "images/cwid.png"));
iconSet.add(new Icon("Dispatcher", "images/dispatcher.png"));
iconSet.add(new Icon("Dump Truck", "images/dump_truck_red.png"));
iconSet.add(new Icon("Fire Truck", "images/fire_truck.png"));
iconSet.add(new Icon("Garbage Truck", "images/garbage_truck.png"));
iconSet.add(new Icon("Loader", "images/loader.png"));
iconSet.add(new Icon("Police", "images/police.png"));
iconSet.add(new Icon("Propane Truck", "images/propane_truck.png"));
iconSet.add(new Icon("Rescue Truck", "images/rescue_truck.png"));
iconSet.add(new Icon("School Bus", "images/school_bus.png"));
iconSet.add(new Icon("Taxi", "images/taxi.png"));
iconSet.add(new Icon("Train", "images/train.png"));
iconSet.add(new Icon("Transport Bus", "images/opt_bus.png"));
iconSet.add(new Icon("Van", "images/van.png"));
return iconSet;
}
/**
* Schedules an icon file save task. Subsequent calls to this method will be ignored until the save event occurs,
* thus limiting repetitive saving to a minimum.
*/
private void scheduleSave()
{
if(mSavingIcons.compareAndSet(false, true))
{
mThreadPoolManager.scheduleOnce(new IconSaveTask(), 2, TimeUnit.SECONDS);
}
}
/**
* Resets the playlist save pending flag to false and proceeds to save the playlist.
*/
public class IconSaveTask implements Runnable
{
@Override
public void run()
{
save();
mSavingIcons.set(false);
}
}
}

150
src/icon/IconModel.java Normal file
View File

@@ -0,0 +1,150 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
package icon;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class IconModel extends DefaultListModel<Icon>
{
public static final String DEFAULT_ICON = "No Icon";
private Icon mDefaultIcon;
private Map<String,Icon> 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<Icon> 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<Icon>(mIconMap.values()));
iconSet.setDefaultIcon(getDefaultIcon().getName());
return iconSet;
}
}

175
src/icon/IconSelector.java Normal file
View File

@@ -0,0 +1,175 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
package icon;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
public class IconSelector extends JDialog implements DocumentListener
{
private IconModel mIconModel;
private JTextField mNameText;
private JTextField mFileLabel;
private JButton mFileChooserButton;
private JButton mOKButton;
private JButton mCancelButton;
/**
* 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
*/
public IconSelector(Frame owner, IconModel iconModel)
{
super(owner, "Add Icon", true);
mIconModel = iconModel;
init();
setLocationRelativeTo(owner);
}
private void init()
{
setSize(250, 170);
JPanel contentPanel = new JPanel();
contentPanel.setPreferredSize(new Dimension(250, 170));
contentPanel.setLayout(new MigLayout("insets 1 1 1 1", "[align right][align left,grow,fill]", "[][][][grow,fill][]"));
contentPanel.add(new JLabel("Name"));
mNameText = new JTextField();
mNameText.getDocument().addDocumentListener(this);
contentPanel.add(mNameText, "wrap");
contentPanel.add(new JLabel("File"));
mFileLabel = new JTextField();
mFileLabel.setEnabled(false);
contentPanel.add(mFileLabel, "wrap");
mFileChooserButton = new JButton("Select File ...");
mFileChooserButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
JFileChooser fileChooser = new JFileChooser();
// fileChooser.setSelectedFile(null);
//Add a custom file filter and disable the default
fileChooser.addChoosableFileFilter(new ImageFilter());
fileChooser.setAcceptAllFileFilterUsed(false);
int returnVal = fileChooser.showDialog(IconSelector.this, "Select");
if(returnVal == JFileChooser.APPROVE_OPTION)
{
File file = fileChooser.getSelectedFile();
if(file != null)
{
mFileLabel.setText(file.getAbsolutePath());
checkButtons();
}
}
}
});
contentPanel.add(mFileChooserButton, "span,align center");
contentPanel.add(new JLabel(), "wrap");
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new MigLayout("", "[grow,fill][grow,fill]", "[]"));
mOKButton = new JButton("OK");
mOKButton.setEnabled(false);
mOKButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
String name = mNameText.getText();
String path = mFileLabel.getText();
Icon icon = new Icon(name, path);
mIconModel.addElement(icon);
IconSelector.this.dispose();
}
});
mCancelButton = new JButton("Cancel");
mCancelButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
IconSelector.this.dispose();
}
});
buttonPanel.add(mOKButton);
buttonPanel.add(mCancelButton);
contentPanel.add(buttonPanel, "span,grow");
add(contentPanel);
}
private void checkButtons()
{
String name = mNameText.getText();
String path = mFileLabel.getText();
mOKButton.setEnabled(name != null && path != null && !path.isEmpty() && !mIconModel.hasIcon(name));
}
@Override
public void insertUpdate(DocumentEvent e)
{
checkButtons();
}
@Override
public void removeUpdate(DocumentEvent e)
{
checkButtons();
}
@Override
public void changedUpdate(DocumentEvent e)
{
checkButtons();
}
}

76
src/icon/IconSet.java Normal file
View File

@@ -0,0 +1,76 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
package icon;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
@XmlRootElement(name="iconset")
public class IconSet
{
private String mDefaultIcon;
private List<Icon> mIcons = new ArrayList<>();
public IconSet()
{
//No-arg JAXB constructor
}
public void add(Icon icon)
{
mIcons.add(icon);
}
public void remove(Icon icon)
{
mIcons.remove(icon);
}
@XmlElementWrapper(name="icons")
@XmlElement(name = "icon")
public List<Icon> getIcons()
{
if(mIcons == null)
{
mIcons = new ArrayList<>();
}
return mIcons;
}
public void setIcons(List<Icon> icons)
{
mIcons = icons;
}
@XmlAttribute(name = "default")
public String getDefaultIcon()
{
return mDefaultIcon;
}
public void setDefaultIcon(String name)
{
mDefaultIcon = name;
}
}

137
src/icon/IconViewer.java Normal file
View File

@@ -0,0 +1,137 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
package icon;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class IconViewer extends JFrame implements ActionListener
{
private static final long serialVersionUID = 1L;
private static final Logger mLog = LoggerFactory.getLogger(IconViewer.class);
private static final String ADD = "Add";
private static final String DEFAULT = "Set Default";
private static final String DELETE = "Delete";
private JButton mAddButton;
private JButton mDeleteButton;
private JButton mDefaultButton;
private JList<Icon> mIconList;
private IconManager mIconManager;
public IconViewer(IconManager model)
{
mIconManager = model;
init();
}
private void init()
{
setTitle("Icon Viewer");
setSize(400, 400);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLayout(new MigLayout("", "[grow,fill]", "[grow,fill]"));
/**
* Editor Panel
*/
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()
{
@Override
public void valueChanged(ListSelectionEvent e)
{
checkButtons();
}
});
editorPanel.add(new JScrollPane(mIconList), "span");
mAddButton = new JButton(ADD);
mAddButton.addActionListener(this);
editorPanel.add(mAddButton);
mDeleteButton = new JButton(DELETE);
mDeleteButton.addActionListener(this);
mDeleteButton.setEnabled(false);
editorPanel.add(mDeleteButton);
mDefaultButton = new JButton(DEFAULT);
mDefaultButton.addActionListener(this);
mDefaultButton.setEnabled(false);
editorPanel.add(mDefaultButton, "wrap");
add(editorPanel);
}
private void checkButtons()
{
Icon selected = mIconList.getSelectedValue();
mDefaultButton.setEnabled(selected != null && selected != mIconManager.getModel().getDefaultIcon());
mDeleteButton.setEnabled(selected != null && selected != mIconManager.getModel().getDefaultIcon());
}
public void actionPerformed(ActionEvent e)
{
Icon selected = mIconList.getSelectedValue();
switch(e.getActionCommand())
{
case ADD:
IconSelector iconSelector = new IconSelector(this, mIconManager.getModel());
iconSelector.setVisible(true);
break;
case DELETE:
if(selected != null)
{
int choice = JOptionPane.showConfirmDialog(IconViewer.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);
}
}
break;
case DEFAULT:
if(selected != null)
{
mIconManager.getModel().setDefaultIcon(selected);
}
break;
}
checkButtons();
}
}

74
src/icon/ImageFilter.java Normal file
View File

@@ -0,0 +1,74 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
package icon;
import javax.swing.filechooser.FileFilter;
import java.io.File;
public class ImageFilter extends FileFilter
{
//Accept all directories and all gif, jpg, tiff, or png files.
public boolean accept(File f)
{
if(f.isDirectory())
{
return true;
}
String extension = getExtension(f);
if(extension != null)
{
if(extension.equals("tiff") ||
extension.equals("tif") ||
extension.equals("gif") ||
extension.equals("jpeg") ||
extension.equals("jpg") ||
extension.equals("png"))
{
return true;
}
else
{
return false;
}
}
return false;
}
//The description of this filter
public String getDescription()
{
return "Images (*.gif,*.jpg,*.png.";
}
public String getExtension(File f)
{
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if(i > 0 && i < s.length() - 1)
{
ext = s.substring(i + 1).toLowerCase();
}
return ext;
}
}

View File

@@ -1,495 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package map;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import settings.Setting;
import settings.SettingChangeListener;
import settings.SettingsManager;
public class IconManager extends JFrame
implements ActionListener, SettingChangeListener
{
public enum Mode { NORMAL, NEW, EDIT }
private static final long serialVersionUID = 1L;
private final static Logger mLog =
LoggerFactory.getLogger( IconManager.class );
private static final String sMSG_NEW = "Type a name for the new icon, "
+ "select the file, and click Save,\nor Cancel to reset";
private static final String sMSG_EDIT = "Change the name for the selected \n"
+ "icon and/or the file, and click Save\nto update, or Cancel to reset";
private static final String sMSG_NORMAL = "Select an icon to edit, or \n"
+ "click New to add an icon";
private JTextField mIconName;
private JTextField mIconPath;
private JButton mButtonLeft = new JButton( "New" );
private JButton mButtonRight = new JButton( "Edit" );
private JButton mButtonFile = new JButton( "File" );
private JTextArea mInstructionLabel = new JTextArea();
private JList<MapIcon> mIconList;
private JFileChooser mFileChooser;
private Mode mMode = Mode.NORMAL;
private SettingsManager mSettingsManager;
public IconManager( SettingsManager settingsManager, Component displayOver )
{
mSettingsManager = settingsManager;
init( displayOver );
}
private void init( Component displayOver )
{
setTitle( "Icon Manager" );
setLocationRelativeTo( displayOver );
setSize( 400, 400 );
setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
setLayout( new MigLayout( "", "[grow,fill]", "[grow,fill]" ) );
/**
* Editor Panel
*/
JPanel editorPanel = new JPanel();
editorPanel.setLayout( new MigLayout( "", "", "[][][][grow,fill]" ) );
mButtonFile.addActionListener( this );
editorPanel.add( mButtonFile, "align right" );
mIconPath = new JTextField();
editorPanel.add( mIconPath, "grow,wrap" );
editorPanel.add( new JLabel( "Name:" ), "align right" );
mIconName = new JTextField();
editorPanel.add( mIconName, "grow,wrap" );
mButtonLeft.addActionListener( this );
editorPanel.add( mButtonLeft );
mButtonRight.addActionListener( this );
mButtonRight.setEnabled( false );
editorPanel.add( mButtonRight, "wrap" );
mInstructionLabel.setText( sMSG_NORMAL );
mInstructionLabel.setRows( 3 );
mInstructionLabel.setBackground( getBackground() );
editorPanel.add( mInstructionLabel, "span,grow,wrap" );
/**
* MapIcon list
*/
MapIcon[] icons = mSettingsManager.getMapIcons();
Arrays.sort( icons );
mIconList = new JList<MapIcon>( icons );
MapIconListCellRenderer renderer = new MapIconListCellRenderer();
renderer.setPreferredSize( new Dimension( 200, 30 ) );
mIconList.setCellRenderer( renderer );
mIconList.addListSelectionListener( new ListSelectionListener()
{
@Override
public void valueChanged( ListSelectionEvent event )
{
/**
* Refresh the display by setting the mode to normal. If we
* were in editing or new mode, and the user clicks in the list
* throw away the changes and set the mode to normal
*/
setMode( Mode.NORMAL );
}
} );
mIconList.addMouseListener( new MouseListener()
{
@Override
public void mouseClicked( MouseEvent event )
{
if( event.getButton() == MouseEvent.BUTTON3 )
{
//Select the item
mIconList.setSelectedIndex(
mIconList.locationToIndex( event.getPoint() ) );
//Determine if it can be deleted
final MapIcon icon = mIconList.getSelectedValue();
if( icon != null )
{
JPopupMenu context = new JPopupMenu();
JMenuItem setDefault = new JMenuItem( "Set As Default" );
setDefault.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
mSettingsManager.setDefaultIcon( icon );
refreshList();
}
} );
context.add( setDefault );
if( icon.isEditable() )
{
JMenuItem deleteItem = new JMenuItem( "Delete Icon" );
deleteItem.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
{
mSettingsManager.deleteMapIcon( icon );
}
} );
context.add( deleteItem );
}
context.show( mIconList, event.getX(), event.getY() );
}
}
}
//Unused
public void mouseEntered( MouseEvent arg0 ) {}
public void mouseExited( MouseEvent arg0 ) {}
public void mousePressed( MouseEvent arg0 ) {}
public void mouseReleased( MouseEvent arg0 ) {}
} );
JScrollPane scroller = new JScrollPane( mIconList );
/**
* Splitpane to hold editor and icon list
*/
JSplitPane splitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT,
scroller,
editorPanel );
splitPane.setResizeWeight( 0.7D );
add( splitPane );
}
private void setMode( Mode mode )
{
MapIcon selected = mIconList.getSelectedValue();
switch( mode )
{
case NORMAL:
setTitle( "Icon Manager" );
mButtonLeft.setText( "New" );
mButtonRight.setText( "Edit" );
if( selected != null )
{
if( selected.isEditable() )
{
mButtonRight.setEnabled( true );
mIconName.setText( selected.getName() );
mIconPath.setText( selected.getPath() );
}
else
{
mButtonRight.setEnabled( false );
mIconName.setText( selected.getName() + " [NO EDIT]" );
mIconPath.setText( null );
}
}
else
{
mButtonRight.setEnabled( false );
mIconName.setText( null );
mIconPath.setText( null );
}
mInstructionLabel.setText( sMSG_NORMAL );
break;
case EDIT:
if( selected != null )
{
setTitle( "Icon Manager - editing [" + selected.getName() + "]" );
}
else
{
setTitle( "Icon Manager - edit [*]" );
}
mButtonLeft.setText( "Save" );
mButtonRight.setText( "Cancel" );
mButtonRight.setEnabled( true );
mInstructionLabel.setText( sMSG_EDIT );
break;
case NEW:
setTitle( "Icon Manager - add new icon" );
mButtonLeft.setText( "Save" );
mButtonRight.setText( "Cancel" );
mButtonRight.setEnabled( true );
mIconName.setText( null );
mIconPath.setText( null );
mInstructionLabel.setText( sMSG_NEW );
break;
}
mMode = mode;
repaint();
}
public void actionPerformed(ActionEvent e)
{
if( e.getSource() == mButtonFile )
{
if ( mFileChooser == null )
{
mFileChooser = new JFileChooser();
//Add a custom file filter and disable the default
mFileChooser.addChoosableFileFilter( new ImageFilter() );
mFileChooser.setAcceptAllFileFilterUsed( false );
}
int returnVal = mFileChooser.showDialog( this, "Select" );
if ( returnVal == JFileChooser.APPROVE_OPTION )
{
File file = mFileChooser.getSelectedFile();
if( file != null )
{
mIconPath.setText( file.getAbsolutePath() );
}
}
//Reset the file chooser for the next time it's shown.
mFileChooser.setSelectedFile( null );
}
else if( e.getSource() == mButtonLeft )
{
switch( mMode )
{
case EDIT: //Save
save();
break;
case NEW: //Save
save();
break;
case NORMAL:
setMode( Mode.NEW );
break;
}
}
else if( e.getSource() == mButtonRight )
{
switch( mMode )
{
case EDIT: //Cancel
case NEW: //Cancel
setMode( Mode.NORMAL );
break;
case NORMAL: //Edit
setMode( Mode.EDIT );
break;
}
}
}
private void refreshList()
{
MapIcon[] icons = mSettingsManager.getMapIcons();
Arrays.sort( icons );
mIconList.setListData( icons );
repaint();
}
private void save()
{
String name = mIconName.getText();
String path = mIconPath.getText();
switch( mMode )
{
case NEW:
if( name != null && !name.isEmpty() )
{
if( path != null && !path.isEmpty() )
{
mSettingsManager.addMapIcon( new MapIcon( name, path, true ) );
}
else
{
JOptionPane.showMessageDialog( this,
"Please select an image file",
"Filename and path missing",
JOptionPane.ERROR_MESSAGE );
}
}
else
{
JOptionPane.showMessageDialog( this,
"Please type a name for the new icon",
"Name missing",
JOptionPane.ERROR_MESSAGE );
}
break;
case EDIT:
MapIcon selected = mIconList.getSelectedValue();
if( name != null && !name.isEmpty() )
{
if( path != null && !path.isEmpty() )
{
selected.setName( name );
selected.setPath( path );
mSettingsManager.updatMapIcon( selected, name, path );
}
else
{
JOptionPane.showMessageDialog( this,
"Please select an image file",
"Filename and path missing",
JOptionPane.ERROR_MESSAGE );
}
}
else
{
JOptionPane.showMessageDialog( this,
"Please type a name for the new icon",
"Name missing",
JOptionPane.ERROR_MESSAGE );
}
break;
default:
break;
}
}
public class ImageFilter extends FileFilter
{
//Accept all directories and all gif, jpg, tiff, or png files.
public boolean accept(File f)
{
if ( f.isDirectory() )
{
return true;
}
String extension = getExtension( f );
if (extension != null)
{
if (extension.equals( "tiff" ) ||
extension.equals( "tif" ) ||
extension.equals( "gif" ) ||
extension.equals( "jpeg" ) ||
extension.equals( "jpg" ) ||
extension.equals( "png" ) )
{
return true;
}
else
{
return false;
}
}
return false;
}
//The description of this filter
public String getDescription()
{
return "Images (*.gif,*.jpg,*.png.";
}
public String getExtension( File f )
{
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1) {
ext = s.substring(i+1).toLowerCase();
}
return ext;
}
}
@Override
public void settingChanged( Setting setting )
{
if( setting instanceof MapIcon )
{
refreshList();
setMode( Mode.NORMAL );
}
}
@Override
public void settingDeleted( Setting setting )
{
if( setting instanceof MapIcon )
{
refreshList();
setMode( Mode.NORMAL );
}
}
}

View File

@@ -1,57 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package map;
import java.awt.Component;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
public class MapIconListCellRenderer extends JLabel
implements ListCellRenderer<MapIcon>
{
private static final long serialVersionUID = 1L;
public MapIconListCellRenderer()
{
setOpaque( true );
}
@Override
public Component getListCellRendererComponent(
JList<? extends MapIcon> list, MapIcon value, int index,
boolean isSelected, boolean cellHasFocus )
{
setIcon( value.getImageIcon() );
setText( value.toString() );
if ( isSelected )
{
setBackground( list.getSelectionBackground() );
setForeground( list.getSelectionForeground() );
}
else
{
setBackground( list.getBackground() );
setForeground( list.getForeground() );
}
return this;
}
}

View File

@@ -432,9 +432,9 @@ public class PlaylistManager implements ChannelEventListener
@Override @Override
public void run() public void run()
{ {
mPlaylistSavePending.set(false);
save(); save();
mPlaylistSavePending.set(false);
} }
} }
} }