Initial code check in continued

This commit is contained in:
dennis.sheirer
2014-04-26 19:48:24 +00:00
parent 960a6f9952
commit 3dfedcf8d1
474 changed files with 76613 additions and 0 deletions

36
src/map/DefaultIcon.java Normal file
View 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
View 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
View 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() );
}
}

View 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;
}
}

View 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
View 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
View 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
View 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;
}
}
}

View 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() );
}
}

View 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() );
}
}

View 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;
}
}
}

View 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 );
}

View 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;
}
}

View 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);
}
}
}