mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Initial code check in continued
This commit is contained in:
36
src/map/DefaultIcon.java
Normal file
36
src/map/DefaultIcon.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*******************************************************************************
|
||||
* 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 settings.Setting;
|
||||
|
||||
public class DefaultIcon extends Setting
|
||||
{
|
||||
public DefaultIcon( String name )
|
||||
{
|
||||
super( name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't use this constructor. This is used by JAXB to unmarshall saved
|
||||
* map icons.
|
||||
*/
|
||||
public DefaultIcon()
|
||||
{
|
||||
}
|
||||
}
|
||||
494
src/map/IconManager.java
Normal file
494
src/map/IconManager.java
Normal file
@@ -0,0 +1,494 @@
|
||||
/*******************************************************************************
|
||||
* 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 log.Log;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.Setting;
|
||||
import settings.SettingChangeListener;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class IconManager extends JFrame
|
||||
implements ActionListener, SettingChangeListener
|
||||
|
||||
{
|
||||
public enum Mode { NORMAL, NEW, EDIT }
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
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;
|
||||
|
||||
public IconManager( ResourceManager resourceManager, Component displayOver )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
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 = mResourceManager.getSettingsManager().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 )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.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 )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.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
|
||||
Log.info( "Right clicked - cancel" );
|
||||
setMode( Mode.NORMAL );
|
||||
break;
|
||||
case NORMAL: //Edit
|
||||
Log.info( "Right clicked - edit" );
|
||||
setMode( Mode.EDIT );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshList()
|
||||
{
|
||||
MapIcon[] icons = mResourceManager.getSettingsManager().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() )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.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 );
|
||||
mResourceManager.getSettingsManager()
|
||||
.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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
188
src/map/MapIcon.java
Normal file
188
src/map/MapIcon.java
Normal file
@@ -0,0 +1,188 @@
|
||||
/*******************************************************************************
|
||||
* 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.Image;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
import settings.Setting;
|
||||
|
||||
public class MapIcon extends Setting implements Comparable<MapIcon>
|
||||
{
|
||||
private static final int sMAX_IMAGE_DIMENSION = 48;
|
||||
private String mPath;
|
||||
private ImageIcon mImageIcon;
|
||||
|
||||
/**
|
||||
* Only map icons created at runtime can be marked as non-editable, and
|
||||
* therefore this property is transient.
|
||||
*/
|
||||
@XmlTransient
|
||||
private boolean mEditable;
|
||||
|
||||
@XmlTransient
|
||||
private boolean mDefaultIcon;
|
||||
|
||||
/**
|
||||
* Wrapper class for a map icon.
|
||||
* @param name - name of the icon - also used as key to lookup the icon
|
||||
* @param path - file path to the icon
|
||||
* @param editable - defines if the map icon or details can be edited
|
||||
*
|
||||
* Note: the default icons are constructed with editable = false, so that
|
||||
* they cannot be deleted from the Icon Manager editor window
|
||||
*/
|
||||
public MapIcon( String name, String path, boolean editable )
|
||||
{
|
||||
super( name );
|
||||
mPath = path;
|
||||
mEditable = editable;
|
||||
}
|
||||
|
||||
public MapIcon( String name, String path )
|
||||
{
|
||||
this( name, path, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't use this constructor. This is used by JAXB to unmarshall saved
|
||||
* map icons.
|
||||
*/
|
||||
public MapIcon()
|
||||
{
|
||||
mEditable = true;
|
||||
}
|
||||
|
||||
|
||||
@XmlAttribute( name="editable" )
|
||||
public boolean isEditable()
|
||||
{
|
||||
return mEditable;
|
||||
}
|
||||
|
||||
@XmlAttribute( name="default" )
|
||||
public boolean isDefaultIcon()
|
||||
{
|
||||
return mDefaultIcon;
|
||||
}
|
||||
|
||||
public void setDefaultIcon( boolean isDefault )
|
||||
{
|
||||
mDefaultIcon = isDefault;
|
||||
}
|
||||
|
||||
public ImageIcon getImageIcon()
|
||||
{
|
||||
if( mImageIcon == null )
|
||||
{
|
||||
mImageIcon = new ImageIcon( mPath );
|
||||
|
||||
/**
|
||||
* If the image is too big, scale it down to max pixel size squared
|
||||
*/
|
||||
if( mImageIcon.getIconWidth() > sMAX_IMAGE_DIMENSION ||
|
||||
mImageIcon.getIconHeight() > sMAX_IMAGE_DIMENSION )
|
||||
{
|
||||
/**
|
||||
* getScaled instance will correct any negative value to the
|
||||
* correct value, maintaining original aspect ratio. So, we
|
||||
* only scale the larger value, and allow the image class to
|
||||
* determine the correct value for the other measurement
|
||||
*/
|
||||
int height = -1;
|
||||
int width = -1;
|
||||
|
||||
/**
|
||||
* Use the larger width or height value to determine the
|
||||
* scaling factor
|
||||
*/
|
||||
if( mImageIcon.getIconHeight() > mImageIcon.getIconWidth() )
|
||||
{
|
||||
height = sMAX_IMAGE_DIMENSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = sMAX_IMAGE_DIMENSION;
|
||||
}
|
||||
|
||||
mImageIcon = new ImageIcon( mImageIcon.getImage()
|
||||
.getScaledInstance( width, height, Image.SCALE_SMOOTH ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return mImageIcon;
|
||||
}
|
||||
|
||||
@XmlAttribute( name="path" )
|
||||
public String getPath()
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
public void setPath( String path )
|
||||
{
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
if( mDefaultIcon )
|
||||
{
|
||||
return getName() + " (default)";
|
||||
}
|
||||
else
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object obj )
|
||||
{
|
||||
if( obj instanceof MapIcon )
|
||||
{
|
||||
MapIcon other = (MapIcon)obj;
|
||||
|
||||
return other.getName().contentEquals( getName() ) &&
|
||||
other.getPath().contentEquals( getPath() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return getName().hashCode() + getPath().hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort order is determined by the icon name
|
||||
*/
|
||||
@Override
|
||||
public int compareTo( MapIcon other )
|
||||
{
|
||||
return getName().compareTo( other.getName() );
|
||||
}
|
||||
}
|
||||
57
src/map/MapIconListCellRenderer.java
Normal file
57
src/map/MapIconListCellRenderer.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*******************************************************************************
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
183
src/map/MapMouseListener.java
Normal file
183
src/map/MapMouseListener.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*******************************************************************************
|
||||
* 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.Cursor;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
|
||||
import log.Log;
|
||||
|
||||
import org.jdesktop.swingx.JXMapViewer;
|
||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
||||
|
||||
import settings.SettingsManager;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class MapMouseListener extends MouseInputAdapter implements MouseWheelListener
|
||||
{
|
||||
private JXMapViewer mJXMapViewer;
|
||||
private SettingsManager mSettingsManager;
|
||||
private Point mPreviousPoint;
|
||||
private Point mCurrentPoint;
|
||||
|
||||
public MapMouseListener( JXMapViewer viewer, SettingsManager settingsManager )
|
||||
{
|
||||
mJXMapViewer = viewer;
|
||||
mSettingsManager = settingsManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged( MouseEvent event )
|
||||
{
|
||||
if ( !SwingUtilities.isLeftMouseButton( event ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Point current = event.getPoint();
|
||||
|
||||
double x = mJXMapViewer.getCenter().getX() -
|
||||
( current.getX() - mPreviousPoint.getX() );
|
||||
|
||||
double y = mJXMapViewer.getCenter().getY() -
|
||||
(current.getY() - mPreviousPoint.getY() );
|
||||
|
||||
if ( !mJXMapViewer.isNegativeYAllowed() )
|
||||
{
|
||||
if ( y < 0 )
|
||||
{
|
||||
y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int maxHeight = (int)( mJXMapViewer.getTileFactory()
|
||||
.getMapSize( mJXMapViewer.getZoom() ).getHeight() *
|
||||
mJXMapViewer.getTileFactory()
|
||||
.getTileSize( mJXMapViewer.getZoom() ) );
|
||||
|
||||
if (y > maxHeight)
|
||||
{
|
||||
y = maxHeight;
|
||||
}
|
||||
|
||||
mPreviousPoint = current;
|
||||
|
||||
mJXMapViewer.setCenter( new Point2D.Double( x, y ) );
|
||||
|
||||
mJXMapViewer.repaint();
|
||||
|
||||
/* Set cursor to dragging */
|
||||
mJXMapViewer.setCursor( Cursor.getPredefinedCursor( Cursor.MOVE_CURSOR ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased( MouseEvent event )
|
||||
{
|
||||
if ( !SwingUtilities.isLeftMouseButton( event ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mPreviousPoint = null;
|
||||
|
||||
/* Reset the curson */
|
||||
mJXMapViewer.setCursor(
|
||||
Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered( MouseEvent event )
|
||||
{
|
||||
SwingUtilities.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mJXMapViewer.requestFocusInWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed( MouseEvent event )
|
||||
{
|
||||
mCurrentPoint = event.getPoint();
|
||||
mPreviousPoint = event.getPoint();
|
||||
|
||||
boolean left = SwingUtilities.isLeftMouseButton( event );
|
||||
|
||||
boolean middle = SwingUtilities.isMiddleMouseButton( event );
|
||||
|
||||
boolean right = SwingUtilities.isRightMouseButton( event );
|
||||
|
||||
boolean doubleClick = ( event.getClickCount() == 2 );
|
||||
|
||||
if (middle || ( left && doubleClick ) )
|
||||
{
|
||||
recenterMap( event );
|
||||
}
|
||||
else if( right )
|
||||
{
|
||||
JPopupMenu popup = new JPopupMenu();
|
||||
|
||||
JMenuItem mapViewItem = new JMenuItem( "Set Default Location & Zoom" );
|
||||
mapViewItem.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
GeoPosition position = mJXMapViewer
|
||||
.convertPointToGeoPosition( mCurrentPoint );
|
||||
|
||||
mSettingsManager.setMapViewSetting( "Default", position,
|
||||
mJXMapViewer.getZoom() );
|
||||
}
|
||||
} );
|
||||
popup.add( mapViewItem );
|
||||
|
||||
popup.show( mJXMapViewer, event.getX(), event.getY() );
|
||||
}
|
||||
}
|
||||
|
||||
private void recenterMap( MouseEvent event )
|
||||
{
|
||||
Rectangle bounds = mJXMapViewer.getViewportBounds();
|
||||
|
||||
double x = bounds.getX() + event.getX();
|
||||
|
||||
double y = bounds.getY() + event.getY();
|
||||
|
||||
mJXMapViewer.setCenter( new Point2D.Double( x, y ) );
|
||||
|
||||
mJXMapViewer.setZoom( mJXMapViewer.getZoom() - 1 );
|
||||
|
||||
mJXMapViewer.repaint();
|
||||
}
|
||||
}
|
||||
148
src/map/MapPanel.java
Normal file
148
src/map/MapPanel.java
Normal file
@@ -0,0 +1,148 @@
|
||||
/*******************************************************************************
|
||||
* 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.EventQueue;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.jdesktop.swingx.JXMapViewer;
|
||||
import org.jdesktop.swingx.OSMTileFactoryInfo;
|
||||
import org.jdesktop.swingx.input.PanKeyListener;
|
||||
import org.jdesktop.swingx.input.ZoomMouseWheelListenerCursor;
|
||||
import org.jdesktop.swingx.mapviewer.DefaultTileFactory;
|
||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
||||
import org.jdesktop.swingx.mapviewer.TileFactoryInfo;
|
||||
|
||||
import settings.MapViewSetting;
|
||||
import settings.SettingsManager;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class MapPanel extends JPanel implements PlottableUpdateListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private SettingsManager mSettingsManager;
|
||||
private MapService mMapService;
|
||||
private JXMapViewer mMapViewer = new JXMapViewer();
|
||||
private PlottableEntityPainter mMapPainter;
|
||||
|
||||
public MapPanel( ResourceManager resourceManager )
|
||||
{
|
||||
mSettingsManager = resourceManager.getSettingsManager();
|
||||
mMapService = resourceManager.getMapService();
|
||||
mMapPainter = new PlottableEntityPainter( mSettingsManager );
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0",
|
||||
"[grow,fill]", "[grow,fill]") );
|
||||
|
||||
/**
|
||||
* Set the entity painter as the overlay painter and register this panel
|
||||
* to receive new messages (plots)
|
||||
*/
|
||||
mMapViewer.setOverlayPainter( mMapPainter );
|
||||
mMapService.addListener( this );
|
||||
|
||||
/**
|
||||
* Map image source
|
||||
*/
|
||||
TileFactoryInfo info = new OSMTileFactoryInfo();
|
||||
DefaultTileFactory tileFactory = new DefaultTileFactory( info );
|
||||
mMapViewer.setTileFactory( tileFactory );
|
||||
|
||||
/**
|
||||
* Defines how many threads will be used to fetch the background map
|
||||
* tiles (graphics)
|
||||
*/
|
||||
tileFactory.setThreadPoolSize( 8 );
|
||||
|
||||
/**
|
||||
* Set initial location and zoom for the map upon display
|
||||
*/
|
||||
GeoPosition syracuse = new GeoPosition( 43.048, -76.147 );
|
||||
int zoom = 7;
|
||||
|
||||
MapViewSetting view = mSettingsManager
|
||||
.getMapViewSetting( "Default", syracuse, zoom );
|
||||
|
||||
mMapViewer.setAddressLocation( view.getGeoPosition() );
|
||||
mMapViewer.setZoom( view.getZoom() );
|
||||
|
||||
/**
|
||||
* Add a mouse adapter for panning and scrolling
|
||||
*/
|
||||
MapMouseListener listener =
|
||||
new MapMouseListener( mMapViewer, mSettingsManager );
|
||||
mMapViewer.addMouseListener( listener );
|
||||
mMapViewer.addMouseMotionListener( listener );
|
||||
|
||||
/* Map zoom listener */
|
||||
mMapViewer.addMouseWheelListener(
|
||||
new ZoomMouseWheelListenerCursor( mMapViewer ) );
|
||||
|
||||
/* Keyboard panning listener */
|
||||
mMapViewer.addKeyListener( new PanKeyListener( mMapViewer ) );
|
||||
|
||||
/**
|
||||
* Add a selection listener
|
||||
*/
|
||||
SelectionAdapter sa = new SelectionAdapter( mMapViewer );
|
||||
mMapViewer.addMouseListener( sa );
|
||||
mMapViewer.addMouseMotionListener( sa );
|
||||
|
||||
/**
|
||||
* Map component
|
||||
*/
|
||||
add( mMapViewer, "span" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entitiesUpdated()
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mMapViewer.repaint();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPlottableEntity( PlottableEntity entity )
|
||||
{
|
||||
mMapPainter.addEntity( entity );
|
||||
|
||||
entitiesUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlottableEntity( PlottableEntity entity )
|
||||
{
|
||||
mMapPainter.removeEntity( entity );
|
||||
|
||||
entitiesUpdated();
|
||||
}
|
||||
}
|
||||
183
src/map/MapService.java
Normal file
183
src/map/MapService.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*******************************************************************************
|
||||
* 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.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import sample.Listener;
|
||||
import settings.SettingsManager;
|
||||
import alias.Alias;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class MapService implements Listener<Message>
|
||||
{
|
||||
private int mMaxHistory = 2;
|
||||
private int mCullThresholdMinutes = 60;
|
||||
|
||||
private static final Color sDEFAULT_COLOR = Color.BLACK;
|
||||
|
||||
private final ScheduledExecutorService scheduler =
|
||||
Executors.newScheduledThreadPool(1);
|
||||
|
||||
private ArrayList<PlottableUpdateListener> mListeners =
|
||||
new ArrayList<PlottableUpdateListener>();
|
||||
|
||||
private HashMap<String,PlottableEntity> mEntities =
|
||||
new HashMap<String,PlottableEntity>();
|
||||
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
public MapService( ResourceManager resourceManager )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
// scheduler.scheduleAtFixedRate( new CullThread(), 5, 5, TimeUnit.MINUTES );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the max plottables (locations) history setting that is applied
|
||||
* to all plottable entities
|
||||
*/
|
||||
public int getMaxHistory()
|
||||
{
|
||||
return mMaxHistory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the max history trail for entities. Value is applied to all newly
|
||||
* created PlottableEntity and all existing entities.
|
||||
*/
|
||||
public void setMaxHistory( int maxHistory )
|
||||
{
|
||||
mMaxHistory = maxHistory;
|
||||
|
||||
/**
|
||||
* Update any existing entities with the new max history value
|
||||
*/
|
||||
for( PlottableEntity entity: mEntities.values() )
|
||||
{
|
||||
entity.setMaxHistory( mMaxHistory );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
{
|
||||
Plottable plottable = message.getPlottable();
|
||||
|
||||
if( plottable != null )
|
||||
{
|
||||
PlottableEntity entity = mEntities.get( plottable.getID() );
|
||||
|
||||
if( entity == null )
|
||||
{
|
||||
Alias alias = plottable.getAlias();
|
||||
|
||||
Color color = null;
|
||||
MapIcon icon = null;
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
color = alias.getMapColor();
|
||||
|
||||
String iconName = alias.getIconName();
|
||||
|
||||
if( iconName == null )
|
||||
{
|
||||
iconName = SettingsManager.DEFAULT_ICON;
|
||||
}
|
||||
|
||||
icon = mResourceManager.getSettingsManager()
|
||||
.getMapIcon( iconName );
|
||||
}
|
||||
|
||||
if( color == null )
|
||||
{
|
||||
color = sDEFAULT_COLOR;
|
||||
}
|
||||
|
||||
entity = new PlottableEntity( plottable, color );
|
||||
|
||||
entity.setMaxHistory( mMaxHistory );
|
||||
|
||||
mEntities.put( plottable.getID(), entity );
|
||||
|
||||
for( PlottableUpdateListener listener: mListeners )
|
||||
{
|
||||
listener.addPlottableEntity( entity );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.addPlottable( plottable );
|
||||
|
||||
for( PlottableUpdateListener listener: mListeners )
|
||||
{
|
||||
listener.entitiesUpdated();;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener( PlottableUpdateListener listener )
|
||||
{
|
||||
mListeners.add( listener );
|
||||
}
|
||||
|
||||
public void removeListener( PlottableUpdateListener listener )
|
||||
{
|
||||
mListeners.remove( listener );
|
||||
}
|
||||
|
||||
public class CullThread implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
long cutoffTime = System.currentTimeMillis() -
|
||||
( mCullThresholdMinutes * 1000 );
|
||||
|
||||
Set<String> ids = Collections.unmodifiableSet( mEntities.keySet() );
|
||||
|
||||
for( String id: ids )
|
||||
{
|
||||
PlottableEntity entity = mEntities.get( id );
|
||||
|
||||
if( entity.getCurrentPlottable().getTimestamp() < cutoffTime )
|
||||
{
|
||||
mEntities.remove( id );
|
||||
|
||||
/**
|
||||
* Let all listeners know we've removed (culled) an entity
|
||||
*/
|
||||
for( PlottableUpdateListener listener: mListeners )
|
||||
{
|
||||
listener.removePlottableEntity( entity );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
139
src/map/Plottable.java
Normal file
139
src/map/Plottable.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*******************************************************************************
|
||||
* 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.util.HashMap;
|
||||
|
||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
||||
|
||||
import alias.Alias;
|
||||
|
||||
public class Plottable implements Comparable<Plottable>
|
||||
{
|
||||
private long mTimestamp;
|
||||
private GeoPosition mGeoPosition;
|
||||
private String mID;
|
||||
private Alias mAlias;
|
||||
|
||||
HashMap<String,String> mAttributes = new HashMap<String,String>();
|
||||
|
||||
public Plottable()
|
||||
{
|
||||
}
|
||||
|
||||
public Plottable( long timestamp,
|
||||
GeoPosition position,
|
||||
String id,
|
||||
Alias alias,
|
||||
HashMap<String,String> attributes )
|
||||
{
|
||||
this( timestamp, position, id, alias );
|
||||
mAttributes = attributes;
|
||||
}
|
||||
|
||||
public Plottable( long timestamp,
|
||||
GeoPosition position,
|
||||
String id,
|
||||
Alias alias )
|
||||
{
|
||||
mTimestamp = timestamp;
|
||||
mGeoPosition = position;
|
||||
mID = id;
|
||||
mAlias = alias;
|
||||
}
|
||||
|
||||
public long getTimestamp()
|
||||
{
|
||||
return mTimestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp( long timestamp )
|
||||
{
|
||||
mTimestamp = timestamp;
|
||||
}
|
||||
|
||||
public GeoPosition getGeoPosition()
|
||||
{
|
||||
return mGeoPosition;
|
||||
}
|
||||
|
||||
public void setGeoPosition( GeoPosition position )
|
||||
{
|
||||
mGeoPosition = position;
|
||||
}
|
||||
|
||||
public String getID()
|
||||
{
|
||||
return mID;
|
||||
}
|
||||
|
||||
public void setID( String id )
|
||||
{
|
||||
mID = id;
|
||||
}
|
||||
|
||||
public Alias getAlias()
|
||||
{
|
||||
return mAlias;
|
||||
}
|
||||
|
||||
public void setAlias( Alias alias )
|
||||
{
|
||||
mAlias = alias;
|
||||
}
|
||||
|
||||
public HashMap<String,String> getAttributes()
|
||||
{
|
||||
return mAttributes;
|
||||
}
|
||||
|
||||
public void addAttribute( String key, String value )
|
||||
{
|
||||
mAttributes.put( key, value );
|
||||
}
|
||||
|
||||
public void removeAttribute( String key )
|
||||
{
|
||||
mAttributes.remove( key );
|
||||
}
|
||||
|
||||
public void clearAttributes()
|
||||
{
|
||||
mAttributes.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparisons for sorting of plottables is based on timestamps
|
||||
*/
|
||||
@Override
|
||||
public int compareTo( Plottable o )
|
||||
{
|
||||
if( mTimestamp == o.mTimestamp )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if( mTimestamp < o.mTimestamp )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
171
src/map/PlottableEntity.java
Normal file
171
src/map/PlottableEntity.java
Normal file
@@ -0,0 +1,171 @@
|
||||
/*******************************************************************************
|
||||
* 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.Color;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
||||
|
||||
import alias.Alias;
|
||||
|
||||
public class PlottableEntity implements Comparable<PlottableEntity>
|
||||
{
|
||||
private TreeSet<Plottable> mPlottables = new TreeSet<Plottable>();
|
||||
|
||||
private Alias mAlias;
|
||||
private Color mColor;
|
||||
private String mID;
|
||||
|
||||
private int mMaxHistory = 2;
|
||||
|
||||
/**
|
||||
* Constructs the entity using the group and alias from the plottable and
|
||||
* adds the plottable as the first plottable entry in the history
|
||||
*/
|
||||
public PlottableEntity( Plottable plottable, Color color )
|
||||
{
|
||||
addPlottable( plottable );
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
public int getMaxHistory()
|
||||
{
|
||||
return mMaxHistory;
|
||||
}
|
||||
|
||||
public void setMaxHistory( int maxHistory )
|
||||
{
|
||||
if( maxHistory >= 1 )
|
||||
{
|
||||
mMaxHistory = maxHistory;
|
||||
}
|
||||
}
|
||||
|
||||
public Plottable getCurrentPlottable()
|
||||
{
|
||||
return mPlottables.last();
|
||||
}
|
||||
|
||||
public GeoPosition getCurrentGeoPosition()
|
||||
{
|
||||
return getCurrentPlottable().getGeoPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the plottable to this entity
|
||||
*/
|
||||
public void addPlottable( Plottable plottable )
|
||||
{
|
||||
/**
|
||||
* Grab the entity settings from the latest plot
|
||||
*/
|
||||
mAlias = plottable.getAlias();
|
||||
mID = plottable.getID();
|
||||
|
||||
/**
|
||||
* Add the plottable to the list
|
||||
*/
|
||||
mPlottables.add( plottable );
|
||||
|
||||
while( mPlottables.size() > mMaxHistory )
|
||||
{
|
||||
mPlottables.remove( mPlottables.first() );
|
||||
}
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
if( mAlias == null )
|
||||
{
|
||||
return mID;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mAlias.getName();
|
||||
}
|
||||
}
|
||||
|
||||
public String getMapIconName()
|
||||
{
|
||||
if( mAlias != null )
|
||||
{
|
||||
return mAlias.getIconName();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Color for rendering this entity (label, route, etc.)
|
||||
*/
|
||||
public Color getColor()
|
||||
{
|
||||
return mColor;
|
||||
}
|
||||
|
||||
public void setColor( Color color )
|
||||
{
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default id to use in the label
|
||||
*/
|
||||
public String getID()
|
||||
{
|
||||
return mID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the alias for this entity
|
||||
*/
|
||||
public Alias getAlias()
|
||||
{
|
||||
return mAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable sorted (time order) list of plottables
|
||||
*/
|
||||
public Set<Plottable> getPlottables()
|
||||
{
|
||||
return Collections.unmodifiableSet( mPlottables );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all plottables from this entity
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
mPlottables.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares by alias name
|
||||
*/
|
||||
@Override
|
||||
public int compareTo( PlottableEntity o )
|
||||
{
|
||||
return this.getAlias().getName().compareTo( o.getAlias().getName() );
|
||||
}
|
||||
}
|
||||
71
src/map/PlottableEntityPainter.java
Normal file
71
src/map/PlottableEntityPainter.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* WaypointMapOverlay.java
|
||||
*
|
||||
* Created on April 1, 2006, 4:59 PM
|
||||
*
|
||||
* To change this template, choose Tools | Template Manager
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package map;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jdesktop.swingx.JXMapViewer;
|
||||
import org.jdesktop.swingx.painter.AbstractPainter;
|
||||
|
||||
import settings.SettingsManager;
|
||||
|
||||
public class PlottableEntityPainter extends AbstractPainter<JXMapViewer>
|
||||
{
|
||||
private PlottableEntityRenderer mRenderer;
|
||||
private Set<PlottableEntity> mEntities = new HashSet<PlottableEntity>();
|
||||
|
||||
public PlottableEntityPainter( SettingsManager settingsManager )
|
||||
{
|
||||
mRenderer = new PlottableEntityRenderer( settingsManager );
|
||||
setAntialiasing( true );
|
||||
setCacheable( false );
|
||||
}
|
||||
|
||||
public void addEntity( PlottableEntity entity )
|
||||
{
|
||||
mEntities.add( entity );
|
||||
}
|
||||
|
||||
public void removeEntity( PlottableEntity entity )
|
||||
{
|
||||
mEntities.remove( entity );
|
||||
}
|
||||
|
||||
public void clearEntities()
|
||||
{
|
||||
mEntities.clear();
|
||||
}
|
||||
|
||||
private Set<PlottableEntity> getEntities()
|
||||
{
|
||||
return Collections.unmodifiableSet( mEntities );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPaint(Graphics2D g, JXMapViewer map, int width, int height)
|
||||
{
|
||||
Rectangle viewportBounds = map.getViewportBounds();
|
||||
|
||||
g.translate( -viewportBounds.getX(), -viewportBounds.getY() );
|
||||
|
||||
Set<PlottableEntity> entities = getEntities();
|
||||
|
||||
for (PlottableEntity entity: entities )
|
||||
{
|
||||
mRenderer.paintPlottableEntity( g, map, entity, true );
|
||||
}
|
||||
|
||||
g.translate( viewportBounds.getX(), viewportBounds.getY() );
|
||||
}
|
||||
}
|
||||
169
src/map/PlottableEntityRenderer.java
Normal file
169
src/map/PlottableEntityRenderer.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*******************************************************************************
|
||||
* 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.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import org.jdesktop.swingx.JXMapViewer;
|
||||
|
||||
import settings.SettingsManager;
|
||||
|
||||
public class PlottableEntityRenderer
|
||||
{
|
||||
private SettingsManager mSettingsManager;
|
||||
|
||||
public PlottableEntityRenderer( SettingsManager settingsManager )
|
||||
{
|
||||
mSettingsManager = settingsManager;
|
||||
}
|
||||
|
||||
public void paintPlottableEntity( Graphics2D g,
|
||||
JXMapViewer viewer,
|
||||
PlottableEntity entity,
|
||||
boolean antiAliasing )
|
||||
{
|
||||
Graphics2D graphics = (Graphics2D)g.create();
|
||||
|
||||
if( antiAliasing )
|
||||
{
|
||||
graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON );
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the entity's preferred color for lines and labels
|
||||
*/
|
||||
graphics.setColor( entity.getColor() );
|
||||
|
||||
/**
|
||||
* Convert the lat/long geoposition to an x/y point on the viewer
|
||||
*/
|
||||
Point2D point = viewer.getTileFactory().geoToPixel(
|
||||
entity.getCurrentGeoPosition(), viewer.getZoom() );
|
||||
|
||||
/**
|
||||
* Paint the route first, so the icon and label overlay it
|
||||
*/
|
||||
paintRoute( graphics, viewer, entity );
|
||||
|
||||
/**
|
||||
* Paint the icon at the current location
|
||||
*/
|
||||
ImageIcon icon = getIcon( entity ).getImageIcon();
|
||||
|
||||
paintIcon( graphics, point, icon );
|
||||
|
||||
/**
|
||||
* Paint the label offset to the right of the icon
|
||||
*/
|
||||
paintLabel( graphics, point, entity, (int)( icon.getIconWidth() / 2 ), 0 );
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*/
|
||||
graphics.dispose();
|
||||
}
|
||||
|
||||
private MapIcon getIcon( PlottableEntity entity )
|
||||
{
|
||||
return mSettingsManager.getMapIcon( entity.getMapIconName() );
|
||||
}
|
||||
|
||||
private void paintIcon( Graphics2D graphics,
|
||||
Point2D point,
|
||||
ImageIcon icon )
|
||||
{
|
||||
graphics.drawImage( icon.getImage(),
|
||||
(int)point.getX() - ( icon.getIconWidth() / 2 ),
|
||||
(int)point.getY() - ( icon.getIconHeight() / 2 ),
|
||||
null );
|
||||
|
||||
}
|
||||
|
||||
private void paintLabel( Graphics2D graphics,
|
||||
Point2D point,
|
||||
PlottableEntity entity,
|
||||
int xOffset,
|
||||
int yOffset )
|
||||
{
|
||||
graphics.drawString( entity.getLabel(),
|
||||
(int)point.getX() + xOffset,
|
||||
(int)point.getY() + yOffset );
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints a two-tone route from the entity's list of plottables (locations).
|
||||
* using black as a wider background route, and the entity's preferred color
|
||||
* as a narrower foreground route.
|
||||
*/
|
||||
private void paintRoute( Graphics2D graphics,
|
||||
JXMapViewer viewer,
|
||||
PlottableEntity entity )
|
||||
{
|
||||
Set<Plottable> plottables = entity.getPlottables();
|
||||
|
||||
if( plottables.size() > 1 )
|
||||
{
|
||||
// Draw the route with a black background line
|
||||
graphics.setColor( Color.BLACK );
|
||||
graphics.setStroke( new BasicStroke( 3 ) );
|
||||
|
||||
drawRoute( plottables, graphics, viewer );
|
||||
|
||||
// Draw the route again, in the entity's preferred color
|
||||
graphics.setColor( entity.getColor() );
|
||||
graphics.setStroke( new BasicStroke( 1 ) );
|
||||
|
||||
drawRoute( plottables, graphics, viewer );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a route from a list of plottables
|
||||
*/
|
||||
private void drawRoute( Set<Plottable> plottables,
|
||||
Graphics2D g,
|
||||
JXMapViewer viewer )
|
||||
{
|
||||
Point2D lastPoint = null;
|
||||
|
||||
for (Plottable plottable: plottables )
|
||||
{
|
||||
// convert geo-coordinate to world bitmap pixel
|
||||
Point2D currentPoint = viewer.getTileFactory()
|
||||
.geoToPixel( plottable.getGeoPosition(), viewer.getZoom() );
|
||||
|
||||
if( lastPoint != null )
|
||||
{
|
||||
g.drawLine( (int)lastPoint.getX(), (int)lastPoint.getY(),
|
||||
(int)currentPoint.getX(), (int)currentPoint.getY() );
|
||||
}
|
||||
|
||||
lastPoint = currentPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
27
src/map/PlottableUpdateListener.java
Normal file
27
src/map/PlottableUpdateListener.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
public interface PlottableUpdateListener
|
||||
{
|
||||
public void entitiesUpdated();
|
||||
|
||||
public void addPlottableEntity( PlottableEntity entity );
|
||||
|
||||
public void removePlottableEntity( PlottableEntity entity );
|
||||
}
|
||||
103
src/map/SelectionAdapter.java
Normal file
103
src/map/SelectionAdapter.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*******************************************************************************
|
||||
* 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.Rectangle;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import org.jdesktop.swingx.JXMapViewer;
|
||||
|
||||
/**
|
||||
* Creates a selection rectangle based on mouse input
|
||||
* Also triggers repaint events in the viewer
|
||||
* @author Martin Steiger
|
||||
*/
|
||||
public class SelectionAdapter extends MouseAdapter
|
||||
{
|
||||
private boolean dragging;
|
||||
private JXMapViewer viewer;
|
||||
|
||||
private Point2D startPos = new Point2D.Double();
|
||||
private Point2D endPos = new Point2D.Double();
|
||||
|
||||
/**
|
||||
* @param viewer the jxmapviewer
|
||||
*/
|
||||
public SelectionAdapter(JXMapViewer viewer)
|
||||
{
|
||||
this.viewer = viewer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
if (e.getButton() != MouseEvent.BUTTON3)
|
||||
return;
|
||||
|
||||
startPos.setLocation(e.getX(), e.getY());
|
||||
endPos.setLocation(e.getX(), e.getY());
|
||||
|
||||
dragging = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e)
|
||||
{
|
||||
if (!dragging)
|
||||
return;
|
||||
|
||||
endPos.setLocation(e.getX(), e.getY());
|
||||
|
||||
viewer.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e)
|
||||
{
|
||||
if (!dragging)
|
||||
return;
|
||||
|
||||
if (e.getButton() != MouseEvent.BUTTON3)
|
||||
return;
|
||||
|
||||
viewer.repaint();
|
||||
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the selection rectangle
|
||||
*/
|
||||
public Rectangle getRectangle()
|
||||
{
|
||||
if (dragging)
|
||||
{
|
||||
int x1 = (int) Math.min(startPos.getX(), endPos.getX());
|
||||
int y1 = (int) Math.min(startPos.getY(), endPos.getY());
|
||||
int x2 = (int) Math.max(startPos.getX(), endPos.getX());
|
||||
int y2 = (int) Math.max(startPos.getY(), endPos.getY());
|
||||
|
||||
return new Rectangle(x1, y1, x2-x1, y2-y1);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
58
src/map/SelectionPainter.java
Normal file
58
src/map/SelectionPainter.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* 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.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import org.jdesktop.swingx.painter.Painter;
|
||||
|
||||
/**
|
||||
* Paints a selection rectangle
|
||||
* @author Martin Steiger
|
||||
*/
|
||||
public class SelectionPainter implements Painter<Object>
|
||||
{
|
||||
private Color fillColor = new Color(128, 192, 255, 128);
|
||||
private Color frameColor = new Color(0, 0, 255, 128);
|
||||
|
||||
private SelectionAdapter adapter;
|
||||
|
||||
/**
|
||||
* @param adapter the selection adapter
|
||||
*/
|
||||
public SelectionPainter(SelectionAdapter adapter)
|
||||
{
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics2D g, Object t, int width, int height)
|
||||
{
|
||||
Rectangle rc = adapter.getRectangle();
|
||||
|
||||
if (rc != null)
|
||||
{
|
||||
g.setColor(frameColor);
|
||||
g.draw(rc);
|
||||
g.setColor(fillColor);
|
||||
g.fill(rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user