Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright (C) 2008-2013 LimeTri. All rights reserved.
*
* AgroSense 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.
*
* There are special exceptions to the terms and conditions of the GPLv3 as it
* is applied to this software, see the FLOSS License Exception
* .
*
* AgroSense 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
* AgroSense. If not, see .
*/
package eu.limetri.client.mapviewer.swing.jxmap.map;
import java.awt.Point;
import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.JPopupMenu;
import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.action.PopupMenuProvider;
import org.netbeans.api.visual.widget.Widget;
import org.openide.nodes.Node;
import org.openide.util.Utilities;
import eu.limetri.api.geo.Geographical;
import eu.limetri.api.geo.Geometrical;
import eu.limetri.api.geo.DataSet;
import eu.limetri.client.mapviewer.api.HasMapActions;
import eu.limetri.client.mapviewer.api.Layer;
import eu.limetri.client.mapviewer.api.Palette;
import eu.limetri.client.mapviewer.api.SplitGeometryHandler;
import eu.limetri.client.mapviewer.swing.jxmap.MapProperties;
import eu.limetri.client.mapviewer.swing.render.DataSetWidget;
import eu.limetri.client.mapviewer.swing.render.JXMapGeoTranslator;
import eu.limetri.client.mapviewer.swing.render.GeoTranslator;
import eu.limetri.client.mapviewer.swing.render.GeometricalWidget;
import eu.limetri.client.mapviewer.swing.render.GridCoverage2DWidget;
import eu.limetri.client.mapviewer.swing.render.IconWidget;
import java.util.Set;
import org.geotools.coverage.grid.GridCoverage2D;
import org.openide.util.actions.SystemAction;
/**
* factory class for the creation of map widgets
*
*
* @author Timon Veenstra
*/
public class MapWidgetFactory {
private static final Logger LOGGER = Logger.getLogger(MapWidgetFactory.class.getCanonicalName());
/**
* Create a widget from a node and a scene
*
* @param node node to create a widgets for
* @param scene scene to create the widget on
* @return the created widget
*/
public static Widget createWidgetFromNode(final Node node, MapScene scene) {
Geometrical geometrical = node.getLookup().lookup(Geometrical.class);
Layer layer = Layer.Finder.findLayer(node);
Palette palette = getPalette(node, layer);
if (layer == null) {
LOGGER.warning("FIXME:Attempt to create a widget from a node without a layer in its hierarchy.");
return null;
}
if (scene.getObjects().contains(node)) {
LOGGER.warning("FIXME:Attempt to create a widget from a node which is already present in the scene");
return null;
}
if (geometrical == null) {
Geographical geographical = node.getLookup().lookup(Geographical.class);
if (geographical == null) {
LOGGER.finest("Attempt to create a widget from a node without a geographical or geometrical, could be a parent node");
return null;
} else {
if (geographical.getBoundingBox() == null) {
LOGGER.finest("Geographical does not have a boundingbox, not able to process it");
return null;
}
if (DataSet.class.equals(geographical.getType())) {
LOGGER.finest("Creating DataSetWidget");
final DataSetWidget widget = new DataSetWidget(layer.getName(), geographical, palette, geographical.getBoundingBox(), new JXMapGeoTranslator(scene.getMapViewer()), scene);
if (palette.equals(layer.getPalette())) {
layer.addPropertyChangeListener(Layer.PROP_PALETTE, (PropertyChangeEvent evt) -> {
widget.setPalette((Palette) evt.getNewValue());
});
}
addActions(widget, node, scene);
return widget;
}
if (GridCoverage2D.class.equals(geographical.getType())) {
LOGGER.finest("Creating GridCoverage2DWidget");
final GridCoverage2DWidget widget = new GridCoverage2DWidget(layer.getName(), geographical, palette, geographical.getBoundingBox(), new JXMapGeoTranslator(scene.getMapViewer()), scene);
if (palette.equals(layer.getPalette())) {
layer.addPropertyChangeListener(Layer.PROP_PALETTE, (PropertyChangeEvent evt) -> {
widget.setPalette((Palette) evt.getNewValue());
});
}
addActions(widget, node, scene);
return widget;
}
}
}
// support empty geometries:
if (geometrical.getGeometry() == null) {
return null;
}
GeometricalWidget widget = new GeometricalWidget(scene, new JXMapGeoTranslator(scene.getMapViewer()), geometrical, palette, null);
addActions(widget, node, scene);
return widget;
}
private static Palette getPalette(Node node, Layer layer) {
// add palette is present in lookup of node, otherwise use the palette from the layer
Palette palette = node.getLookup().lookup(Palette.class);
if (palette == null) {
LOGGER.finest("using layers palette");
palette = layer.getPalette();
} else {
LOGGER.finest("using palette from node lookup");
}
return palette;
}
/**
* Tries to create and returns an icon widget for the given node. No widget is created if the node's lookup doesn't contain
* a geographical or the geographical doesn't have an icon.
*
* @param scene
* @param node The node (with a geometrical in its lookup)
* @return The created icon widget or null if none created.
*/
public static Widget createIconWidgetFromNode(final Node node, MapScene scene) {
Geometrical geometrical = node.getLookup().lookup(Geometrical.class);
Layer layer = Layer.Finder.findLayer(node);
GeoTranslator geoTranslator = new JXMapGeoTranslator(scene.getMapViewer());
Widget iconWidget = null;
if (geometrical != null && geometrical.getIcon() != null) {
iconWidget = new IconWidget(geometrical, getPalette(node, layer), geoTranslator, scene);
addActions(iconWidget, node, scene);
}
return iconWidget;
}
/**
* Adds hover, select and the node's actions to the given widget. Doesn't do anything if the given widget is null. Will
* first check with {@link MapProperties#getWidgetActionsEnabledValue()} if this actions should be added
*
* @param widget The widget to add the actions to. Can be n
* @param node The node to some of the actions from
* @param scene The scene the widget is on
*/
private static void addActions(Widget widget, final Node node, final MapScene scene) {
if (widget != null) {
if (MapProperties.getWidgetStateActionsEnabledValue()) {
widget.getActions().addAction(scene.createObjectHoverAction());
widget.getActions().addAction(scene.createWidgetHoverAction());
widget.getActions().addAction(scene.createSelectAction());
}
if (MapProperties.getNodeActionsAvailableOnWidgetValue()) {
widget.getActions().addAction(ActionFactory.createPopupMenuAction(new PopupMenuProvider() {
@Override
public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
List actionList = new ArrayList<>();
actionList.addAll(Arrays.asList(node.getActions(true)));
actionList.add(getSplitGeometryAction(node));
actionList.add(SystemAction.get(RemoveLayerAction.class));
actionList.add(null);
actionList.addAll(Arrays.asList(getMapActions(node, scene)));
//TODO: add LocationPicker for DynamicPoint
//FIXME: change action filtering, also see LayerListNode
Action actionToRemove = null;
for (Action action : actionList) {
if (action != null && "DelegateAction".equals(action.getClass().getSimpleName())) {
actionToRemove = action;
break;
}
}
if (actionToRemove != null) {
actionList.remove(actionToRemove);
}
Action[] actions = actionList.toArray(new Action[actionList.size()]);
JPopupMenu menu;
menu = Utilities.actionsToPopup(actions, node.getLookup());
menu = MapProperties.addTitleToPopup(menu, node.getDisplayName());
return menu;
}
}));
}
}
}
/**
* Creates and return a list of the map specific actions for the node. Adds the default actions for DynamicGeometrical
* (currently only PickLocationAction) and checks the DynamicGeometrial for the implementation's specific map actions.
* Returns an empty list if the node does not contain a DynamicGeometrical.
*
* @param node The node
* @param scene The scene the node's widget is rendered on
* @return The map specific actions for the node
*/
private static Action[] getMapActions(final Node node, final MapScene scene) {
HasMapActions object = node.getLookup().lookup(HasMapActions.class);
if (object != null) {
return object.getMapActions();
} else {
return new Action[0];
}
}
private static Action getSplitGeometryAction(Node node) {
Action action = null;
if (node.getLookup().lookup(SplitGeometryHandler.class) != null) {
action = new SplitGeometryAction(node);
}
return action;
}
}