/* * Copyright (C) 2015 Alec Dhuse * * 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 co.foldingmap.GUISupport; import co.foldingmap.map.MapObjectList; import co.foldingmap.map.MapObject; import co.foldingmap.map.DigitalMap; import co.foldingmap.map.Visibility; import co.foldingmap.map.MapUtilities; import co.foldingmap.map.vector.LinearRing; import co.foldingmap.map.vector.MultiGeometry; import co.foldingmap.map.vector.VectorObject; import co.foldingmap.map.vector.VectorObjectList; import co.foldingmap.map.vector.MapPoint; import co.foldingmap.map.vector.LineString; import co.foldingmap.map.vector.Polygon; import co.foldingmap.actions.Actions; import co.foldingmap.actions.ChangeMapObjectName; import co.foldingmap.actions.SelectObjects; import co.foldingmap.actions.ChangeNameAction; import co.foldingmap.actions.ChangeMapName; import co.foldingmap.GUISupport.components.PopupMenuButton; import co.foldingmap.GUISupport.components.RangeSlider; import co.foldingmap.Logger; import co.foldingmap.MainWindow; import co.foldingmap.ResourceHelper; import co.foldingmap.map.themes.ColorStyle; import co.foldingmap.map.themes.MapTheme; import co.foldingmap.map.themes.MapThemeManager; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.Collections; import javax.swing.*; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * This class bundles the setup and actions of theObjectDetailsToolBar. * * @author Alec */ public class ObjectDetailsToolBar extends JToolBar implements ActionListener, CaretListener, ChangeListener, Updateable { private Actions actions; // private ArrayList<Updateable> updates; private boolean mapSelected; private ChangeNameAction changeNameAction; private DefaultComboBoxModel comboModel; private DigitalMap mapData; private ImageIcon iconBlank, iconLinearRing, iconLineString, iconMap; private ImageIcon iconMapPoint, iconMultiGeometry, iconPolygon; private JComboBox comboObjectClassType; private JLabel labelObjectDetailSpacer, labelObjectType; private JTextField textObjectName; private RangeSlider visibilityRange; private VectorObject mapObject; private final MainWindow parentWindow; private PopupMenuButton buttonFilterPoints, buttonFilterLines, buttonFilterPolygons, buttonFilterMulti; private ResourceHelper helper; private SelectObjects selectPoints, selectLines, selectPolygons, selectMulti; public ObjectDetailsToolBar(MainWindow parentWindow) { super("Object Details",JToolBar.HORIZONTAL); this.parentWindow = parentWindow; init(); } /** * Handles the action preformed event for objects on this tool bar. * * @param ae */ @Override public void actionPerformed(ActionEvent ae) { if (ae.getSource() == comboObjectClassType) { if (comboModel.getSelectedItem() instanceof MapTheme) { changeTheme(); parentWindow.update(); } else { changeStyle(); } } else if (ae.getSource() instanceof PopupMenuButton) { if (ae.getActionCommand().equalsIgnoreCase(PopupMenuButton.MENU_ACTIVATION)) { //load the currently used clesses as menu options for these buttons updateFilterButton((PopupMenuButton) ae.getSource()); } else { if (ae.getSource() == buttonFilterPoints) { selectPoints.execute(); } else if (ae.getSource() == buttonFilterLines) { selectLines.execute(); } else if (ae.getSource() == buttonFilterPolygons) { selectPolygons.execute(); } else if (ae.getSource() == buttonFilterMulti) { selectMulti.execute(); } this.update(); this.parentWindow.update(); } } } /** * Adds a KeyListener to objects on this ToolBar. * * @param kl */ @Override public void addKeyListener(KeyListener kl) { comboObjectClassType.addKeyListener(kl); textObjectName.addKeyListener(kl); } // public void addUpdateable(Updateable updateable) { // updates.add(updateable); // } @Override public void caretUpdate(CaretEvent ce) { if (ce.getSource() == textObjectName && changeNameAction != null) { if (changeNameAction.hasExecuted()) { changeNameAction = new ChangeMapName(mapData, textObjectName.getText()); } else { changeNameAction.setNameText(textObjectName.getText()); } } } /** * Changes the style of the selected object(s). * */ private void changeStyle() { ColorStyle newStyle; VectorObjectList<VectorObject> vectorObjects; vectorObjects = new VectorObjectList<VectorObject>(mapData.getSelectedObjects()); newStyle = (ColorStyle) comboModel.getSelectedItem(); actions.changeObjectStyle(vectorObjects, mapData.getTheme(), newStyle); } /** * Changes the map's theme. */ private void changeTheme() { MapTheme newTheme; newTheme = (MapTheme) comboModel.getSelectedItem(); actions.changeTheme(mapData, newTheme, parentWindow, parentWindow.getProgressBarPanel()); } /** * Returns the VisibilityObject for an MapObject's style, if there is one. * * @param object * @return */ private Visibility getObjectStyleVisibility(MapObject object) { ColorStyle cs = null; Visibility vis = null; if (object instanceof MapPoint) { cs = mapData.getTheme().getIconStyle(((VectorObject)object).getObjectClass()); } else if (object instanceof LineString) { cs = mapData.getTheme().getLineStyle(((VectorObject)object).getObjectClass()); } else if (object instanceof Polygon) { cs = mapData.getTheme().getPolygonStyle(((VectorObject)object).getObjectClass()); } if (cs != null) vis = cs.getVisibility(); return vis; } private void init() { try { initFilters(); helper = ResourceHelper.getInstance(); //Object Icons iconBlank = helper.getImage("blank.png"); iconLinearRing = helper.getImage("linear_ring.png"); iconLineString = helper.getImage("polyline.png"); iconMap = helper.getImage("new_map.png"); iconMapPoint = helper.getImage("marker.png"); iconMultiGeometry = helper.getImage("multi-geometry.png"); iconPolygon = helper.getImage("polygon.png"); buttonFilterPoints = new PopupMenuButton(iconMapPoint, actions, PopupMenuButton.RIGHT_CLICK); buttonFilterLines = new PopupMenuButton(iconLineString, actions, PopupMenuButton.RIGHT_CLICK); buttonFilterPolygons = new PopupMenuButton(iconPolygon, actions, PopupMenuButton.RIGHT_CLICK); buttonFilterMulti = new PopupMenuButton(iconMultiGeometry, actions, PopupMenuButton.RIGHT_CLICK); comboModel = new DefaultComboBoxModel(); comboObjectClassType = new JComboBox(comboModel); labelObjectDetailSpacer = new JLabel(""); labelObjectType = new JLabel(" ", iconMap, SwingConstants.LEFT); visibilityRange = new RangeSlider(0, 23); textObjectName = new JTextField(16); visibilityRange.setMaximumSize(new Dimension(150, 20)); visibilityRange.setPreferredSize(new Dimension(150, 20)); visibilityRange.setToolTipText("Object's Zoom Level Visibility"); this.add(labelObjectDetailSpacer); this.add(labelObjectType); this.add(textObjectName); this.add(comboObjectClassType); //this.add(buttonObjectVisibility); this.add(visibilityRange); this.addSeparator(); this.add(buttonFilterPoints); this.add(buttonFilterLines); this.add(buttonFilterPolygons); this.add(buttonFilterMulti); //Setup Display properties // buttonObjectVisibility.setEnabled(false); visibilityRange.setEnabled(false); comboObjectClassType.setEnabled(false); comboObjectClassType.setMaximumSize(new Dimension(250, 50)); textObjectName.setMaximumSize(new Dimension(250, 50)); //Add Listeners // buttonObjectVisibility.addActionListener(this); visibilityRange.addChangeListener(this); comboObjectClassType.addActionListener(this); textObjectName.addCaretListener(this); textObjectName.addKeyListener(parentWindow.getMapPanel()); //filter buttons buttonFilterPoints.addActionListener(this); buttonFilterLines.addActionListener(this); buttonFilterPolygons.addActionListener(this); buttonFilterMulti.addActionListener(this); buttonFilterPoints.addUpdate(parentWindow); buttonFilterLines.addUpdate(parentWindow); buttonFilterPolygons.addUpdate(parentWindow); buttonFilterMulti.addUpdate(parentWindow); buttonFilterPoints.addUpdate(this); buttonFilterLines.addUpdate(this); buttonFilterPolygons.addUpdate(this); buttonFilterMulti.addUpdate(this); } catch (Exception e) { Logger.log(Logger.ERR, "Error in ObjectDetailsToolBar.init() - " + e); } } /** * Initiates filter objects for the quick filter buttons */ private void initFilters() { selectPoints = new SelectObjects(mapData, SelectObjects.MAP_POINT, SelectObjects.ALL_CLASSES, false); selectLines = new SelectObjects(mapData, SelectObjects.LINE_STRING, SelectObjects.ALL_CLASSES, false); selectPolygons = new SelectObjects(mapData, SelectObjects.POLYGON, SelectObjects.ALL_CLASSES, false); selectMulti = new SelectObjects(mapData, SelectObjects.MULTIGEOMETRY, SelectObjects.ALL_CLASSES, false); } /** * Sets the map being used. * * @param mapData */ public void setMap(DigitalMap mapData) { this.mapData = mapData; this.actions = mapData.getActions(); buttonFilterPoints.setActions(actions); buttonFilterLines.setActions(actions); buttonFilterPolygons.setActions(actions); buttonFilterMulti.setActions(actions); selectPoints.setMap(mapData); selectLines.setMap(mapData); selectPolygons.setMap(mapData); selectMulti.setMap(mapData); textObjectName.setText(mapData.getName()); } /** * Catches state changed events for objects on the listen list. * * @param ce */ @Override public void stateChanged(ChangeEvent ce) { if (ce.getSource() == this.visibilityRange) { int min = visibilityRange.getLowValue(); int max = visibilityRange.getHighValue(); for (MapObject object: mapData.getSelectedObjects()) { Visibility v = object.getVisibility(); if (v == null && (min > 0 || max < 23)) { v = new Visibility(max, min); object.setVisibility(v); } else if (v != null) { v = new Visibility(max, min); object.setVisibility(v); } else { object.setVisibility(null); } } parentWindow.getMapPanel().update(); } } /** * Updates the selection of objects. */ @Override public void update() { ArrayList availableStyles; VectorObject selectedObject; MapObjectList<MapObject> selectedObjects; MapTheme mapTheme; MapThemeManager themeManager; try { selectedObjects = (mapData.getSelectedObjects()); mapSelected = (selectedObjects.size() == 0); //Update name, if it has changed before we update the toolbar. updateName(); if (mapData != null) { mapObject = null; mapTheme = mapData.getTheme(); themeManager = mapData.getMapThemeManager(); if (selectedObjects.size() == 0) { //No objects selected, display info about the map. textObjectName.setText(mapData.getName()); labelObjectType.setIcon(iconMap); textObjectName.setEnabled(true); comboModel = new DefaultComboBoxModel(themeManager.getAllThemes().toArray()); comboModel.setSelectedItem(mapTheme); comboObjectClassType.setModel(comboModel); comboObjectClassType.setEnabled(true); visibilityRange.setEnabled(false); visibilityRange.setValues(0, 23); changeNameAction = new ChangeMapName(mapData, textObjectName.getText()); } else if (selectedObjects.size() == 1) { if (selectedObjects.get(0) instanceof VectorObject) { selectedObject = (VectorObject) selectedObjects.get(0); mapObject = selectedObject; textObjectName.setText(selectedObject.getName()); textObjectName.setEnabled(true); visibilityRange.setEnabled(true); Visibility vis = selectedObjects.get(0).getVisibility(); Visibility objVis = getObjectStyleVisibility(selectedObjects.get(0)); if (vis != null) { visibilityRange.setValues((int) vis.getMinTileZoomLevel(), (int) vis.getMaxTileZoomLevel()); } else { if (objVis != null) { visibilityRange.setValues((int) objVis.getMinTileZoomLevel(), (int) objVis.getMaxTileZoomLevel()); } else { visibilityRange.setValues(0, 23); } } if (selectedObject instanceof MapPoint) { labelObjectType.setIcon(this.iconMapPoint); availableStyles = mapTheme.getAllIconStyles(); Collections.sort(availableStyles); comboModel = new DefaultComboBoxModel(availableStyles.toArray()); comboModel.setSelectedItem(mapTheme.getIconStyle(selectedObject.getObjectClass())); comboObjectClassType.setModel(comboModel); comboObjectClassType.setEnabled(true); } else if (selectedObject instanceof LinearRing) { labelObjectType.setIcon(this.iconLinearRing); availableStyles = mapTheme.getAllLineStyles(); Collections.sort(availableStyles); comboModel = new DefaultComboBoxModel(availableStyles.toArray()); comboModel.setSelectedItem(mapTheme.getLineStyle(selectedObject.getObjectClass())); comboObjectClassType.setModel(comboModel); comboObjectClassType.setEnabled(true); } else if (selectedObject instanceof LineString) { labelObjectType.setIcon(this.iconLineString); availableStyles = mapTheme.getAllLineStyles(); Collections.sort(availableStyles); comboModel = new DefaultComboBoxModel(availableStyles.toArray()); comboModel.setSelectedItem(mapTheme.getLineStyle(selectedObject.getObjectClass())); comboObjectClassType.setModel(comboModel); comboObjectClassType.setEnabled(true); } else if (selectedObject instanceof Polygon) { labelObjectType.setIcon(this.iconPolygon); availableStyles = mapTheme.getAllPolygonStyles(); Collections.sort(availableStyles); comboModel = new DefaultComboBoxModel(availableStyles.toArray()); comboModel.setSelectedItem(mapTheme.getPolygonStyle(selectedObject.getObjectClass())); comboObjectClassType.setModel(comboModel); comboObjectClassType.setEnabled(true); } else if (selectedObject instanceof MultiGeometry) { labelObjectType.setIcon(this.iconMultiGeometry); comboObjectClassType.setEnabled(false); } changeNameAction = new ChangeMapObjectName(selectedObject, textObjectName.getText()); } } else { //more than one object selected textObjectName.setText(""); //Find the biggest max and smallest min and set the range slider to those vals. int max = 23; int min = 0; for (MapObject obj: selectedObjects) { Visibility v = obj.getVisibility(); if (v != null) { max = (v.getMaxTileZoomLevel() > max ? (int) v.getMaxTileZoomLevel() : max); min = (v.getMinTileZoomLevel() < min ? (int) v.getMinTileZoomLevel() : min); } } visibilityRange.setValues(min, max); if (selectedObjects.areAllVectorObjects()) { VectorObjectList<VectorObject> vectorObjects; vectorObjects = new VectorObjectList<VectorObject>(selectedObjects); visibilityRange.setEnabled(true); if (vectorObjects.getMapPoints().size() == selectedObjects.size()) { labelObjectType.setIcon(this.iconMapPoint); availableStyles = mapTheme.getAllIconStyles(); Collections.sort(availableStyles); comboModel = new DefaultComboBoxModel(availableStyles.toArray()); comboModel.setSelectedItem(mapTheme.getIconStyle(null)); comboObjectClassType.setModel(comboModel); comboObjectClassType.setEnabled(true); textObjectName.setEnabled(false); } else if (vectorObjects.getLineStrings().size() == selectedObjects.size()) { labelObjectType.setIcon(this.iconLineString); availableStyles = mapTheme.getAllLineStyles(); Collections.sort(availableStyles); comboModel = new DefaultComboBoxModel(availableStyles.toArray()); comboModel.setSelectedItem(mapTheme.getLineStyle(null)); comboObjectClassType.setModel(comboModel); comboObjectClassType.setEnabled(true); textObjectName.setEnabled(false); } else if (vectorObjects.getPolygons().size() == selectedObjects.size()) { labelObjectType.setIcon(this.iconPolygon); availableStyles = mapTheme.getAllPolygonStyles(); Collections.sort(availableStyles); comboModel = new DefaultComboBoxModel(availableStyles.toArray()); comboModel.setSelectedItem(mapTheme.getPolygonStyle(null)); comboObjectClassType.setModel(comboModel); comboObjectClassType.setEnabled(true); textObjectName.setEnabled(false); } else if (vectorObjects.getMultiGeometries().size() == selectedObjects.size()) { labelObjectType.setIcon(this.iconMultiGeometry); comboObjectClassType.setEnabled(false); textObjectName.setEnabled(false); } else { //Multiple Tyles of objects labelObjectType.setIcon(this.iconBlank); textObjectName.setText("Multiple Object Types"); textObjectName.setEnabled(false); comboObjectClassType.setEnabled(false); } changeNameAction = null; }//end VectorObject test } } //end mapData != null check // for (Updateable update: updates) // update.update(); parentWindow.repaint(); } catch (Exception e) { Logger.log(Logger.ERR, "Error in ObjectDetailsToolBar.update() - " + e); } } /** * Updates the quick filter button with all used object classes for that * object type. * * @param buttonToUpdate */ private void updateFilterButton(PopupMenuButton buttonToUpdate) { ArrayList<String> classNames; int objectType; JMenuItem menuItem; SelectObjects selectObjects; VectorObjectList<VectorObject> vectorObjects; buttonToUpdate.removeAllMenuItems(); vectorObjects = new VectorObjectList<VectorObject>(mapData.getAllMapObjects()); if (buttonToUpdate == buttonFilterPoints) { classNames = MapUtilities.getObjectClasses(vectorObjects.getMapPoints()); objectType = SelectObjects.MAP_POINT; } else if (buttonToUpdate == buttonFilterLines) { classNames = MapUtilities.getObjectClasses(vectorObjects.getLineStrings()); objectType = SelectObjects.LINE_STRING; } else if (buttonToUpdate == buttonFilterPolygons) { classNames = MapUtilities.getObjectClasses(vectorObjects.getPolygons()); objectType = SelectObjects.POLYGON; } else if (buttonToUpdate == buttonFilterMulti) { classNames = MapUtilities.getObjectClasses(vectorObjects.getMultiGeometries()); objectType = SelectObjects.MULTIGEOMETRY; } else { classNames = new ArrayList<String>(); objectType = 0; } for (String name: classNames) { menuItem = new JMenuItem(name); selectObjects = new SelectObjects(mapData, objectType, name, false); buttonToUpdate.add(menuItem, selectObjects); } } /** * Forces an update of the Map or the Selected Object's name. */ public void updateName() { if (changeNameAction != null) { if (mapSelected) { //Change Map Name, if it has changed. if (!changeNameAction.getNameText().equals(mapData.getName())) actions.performAction(changeNameAction); } else if (mapObject != null) { //Change Object Name if (!changeNameAction.getNameText().equals(mapObject.getName())) actions.performAction(changeNameAction); } } //end changeNameAction != null check } }