eu.limetri.client.mapviewer.nb.jxmap.DrawingPanel Maven / Gradle / Ivy
/**
* Copyright (C) 2008-2012 AgroSense Foundation.
*
* 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.nb.jxmap;
import eu.limetri.client.mapviewer.nb.jxmap.RootMapPanel;
import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.JComponent;
import org.jdesktop.swingx.JXPanel;
import org.netbeans.api.visual.widget.LayerWidget;
import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.NodeListener;
import eu.limetri.client.mapviewer.swing.JXMapViewer;
import eu.limetri.client.mapviewer.swing.jxmap.map.DrawingContext;
import eu.limetri.client.mapviewer.swing.jxmap.map.MapScene;
import eu.limetri.client.mapviewer.swing.render.JXMapGeoTranslator;
import eu.limetri.client.mapviewer.swing.render.DrawingRenderer;
import eu.limetri.client.mapviewer.swing.render.GeoTranslator;
/**
* Panel on which drawn widgets are shown.
*
* @author johan
*/
public class DrawingPanel extends JXPanel {
private static final Logger LOGGER = Logger.getLogger(DrawingPanel.class.getCanonicalName());
private final MapScene scene;
private final JComponent view;
private final JXMapViewer mapViewer; // needed to create widgets which need to be aware of the map
private final LayerWidget mainLayer;
private final RootMapPanel.LayerGroup group = RootMapPanel.LayerGroup.LAYER_DRAWING;
private final GeoTranslator translator;
private final PropertyChangeListener contextListener;
private ExplorerManager explorer;
private List listeners = new ArrayList<>();
public DrawingPanel(JXMapViewer mapViewer) {
//
// initalize the scene, view and main layer which map objects are drawn on
//
this.scene = new MapScene(mapViewer);
this.view = scene.createView();
this.mainLayer = new LayerWidget(scene);
this.mapViewer = mapViewer;
this.translator = new JXMapGeoTranslator(mapViewer);
this.scene.setOpaque(false);
this.scene.addChild(this.mainLayer);
this.scene.setMaximumBounds(new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE));
setOpaque(false);
setLayout(new BorderLayout());
add(view, BorderLayout.CENTER);
contextListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
view.repaint();
}
};
}
@Override
public void addNotify() {
super.addNotify();
for (NodeListener listener : listeners) {
getExplorerManager().getRootContext().addNodeListener(listener);
}
listeners.clear();
}
private ExplorerManager getExplorerManager() {
if (explorer == null) {
explorer = ExplorerManager.find(this);
assert explorer != null : "This component needs a parent wich is an ExplorerManager.Provider";
}
return explorer;
}
/**
* Adds a {@link NodeListener} to the {@link ExplorerManager#getRootContext()}
* one of the parents of this panel should provide If this panels {@link JComponent#addNotify()}
* method is not yet called the listener is put on hold till it is called.
*
* @param nodeListener
*/
public void addNodeListener(NodeListener nodeListener) {
if (explorer == null) {
listeners.add(nodeListener);
} else {
getExplorerManager().getRootContext().addNodeListener(nodeListener);
}
}
/**
* Removes a {@link NodeListener} from the {@link ExplorerManager#getRootContext()}
* one of the parents of this panel should provide
* @param nodeListener
*/
public void removeNodeListener(NodeListener nodeListener){
if (explorer == null) {
listeners.remove(nodeListener);
} else {
getExplorerManager().getRootContext().removeNodeListener(nodeListener);
}
}
public GeoTranslator getTranslator() {
return translator;
}
public JXMapViewer getMapViewer() {
return mapViewer;
}
public void addContext(DrawingContext context) {
DrawingWidget drawingWidget = new DrawingWidget(scene, context.getRenderer());
mainLayer.addChild(drawingWidget);
scene.addObject(context, drawingWidget);
scene.validate();
context.addPropertyChangeListener(contextListener);
}
public void removeContext(DrawingContext context) {
Widget widget = scene.findWidget(context);
if (widget != null) {
mainLayer.removeChild(widget);
scene.removeObject(context);
scene.validate();
}
context.removePropertyChangeListener(contextListener);
}
//single widget for now. TODO: child widgets per coordinate + connectors.
public class DrawingWidget extends Widget {
private DrawingRenderer renderer;
public DrawingWidget(Scene scene, DrawingRenderer renderer) {
super(scene);
this.renderer = renderer;
}
@Override
protected void paintWidget() {
Graphics2D g = (Graphics2D) getGraphics().create();
renderer.render(g, getScene().getClientArea(), getTranslator());
g.dispose();
}
}
}