Java tutorial
/* * polymap.org Copyright (C) 2016, Falko Brutigam. All rights reserved. * * This is free software; you can redistribute it and/or modify it under the terms of * the GNU Lesser General Public License as published by the Free Software * Foundation; either version 3.0 of the License, or (at your option) any later * version. * * This software 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 Lesser General Public License for more details. */ package io.mapzone.arena.analytics.graph.ui; import static org.polymap.core.ui.FormDataFactory.on; import java.util.TreeMap; import java.io.IOException; import org.geotools.data.FeatureSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.google.common.collect.Maps; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; import org.polymap.core.catalog.resolve.IResolvableInfo; import org.polymap.core.catalog.resolve.IResourceInfo; import org.polymap.core.data.rs.catalog.RServiceInfo; import org.polymap.core.mapeditor.MapViewer; import org.polymap.core.project.IMap; import org.polymap.core.runtime.i18n.IMessages; import org.polymap.core.style.DefaultStyle; import org.polymap.core.style.model.FeatureStyle; import org.polymap.core.style.model.feature.AttributeValue; import org.polymap.core.style.model.feature.TextStyle; import org.polymap.core.ui.FormDataFactory; import org.polymap.core.ui.FormLayoutFactory; import org.polymap.core.ui.SelectionAdapter; import org.polymap.core.ui.StatusDispatcher; import org.polymap.core.ui.UIUtils; import org.polymap.rhei.batik.Context; import org.polymap.rhei.batik.Mandatory; import org.polymap.rhei.batik.PanelIdentifier; import org.polymap.rhei.batik.Scope; import org.polymap.rhei.batik.toolkit.ActionItem; import org.polymap.rhei.batik.toolkit.IPanelSection; import org.polymap.rhei.batik.toolkit.ItemContainer; import org.polymap.rhei.batik.toolkit.md.MdToolbar2; import org.polymap.p4.P4Panel; import org.polymap.p4.P4Plugin; import org.polymap.p4.catalog.AllResolver; import org.polymap.p4.style.LayerStylePanel; import org.polymap.p4.style.FeatureStyleEditorInput; import org.polymap.rap.openlayers.base.OlEventListener; import org.polymap.rap.openlayers.control.MousePositionControl; import io.mapzone.arena.analytics.graph.Graph; import io.mapzone.arena.analytics.graph.GraphFunction; import io.mapzone.arena.analytics.graph.GraphPlugin; import io.mapzone.arena.analytics.graph.Messages; import io.mapzone.arena.analytics.graph.Node; import io.mapzone.arena.analytics.graph.SingleSourceNodeGraphFunction; import io.mapzone.arena.analytics.graph.algo.GephiGraph; /** * Proof-of-concept for generated geometries and graph displayed in an OL map. * * @author Steffen Stundzig */ public class GraphPanel extends P4Panel { private static final Log log = LogFactory.getLog(GraphPanel.class); public static final PanelIdentifier ID = PanelIdentifier.parse("graph"); private static final IMessages i18n = Messages.forPrefix("GraphPanel"); // XXX replace with extension point public static final Class<GraphFunction>[] AVAILABLE_FUNCTIONS = new Class[] { // HiddenOrganisationPersonGraphFunction.class, // OrganisationPersonGraphFunction.class, SingleSourceNodeGraphFunction.class }; private static final String NODE_STYLE_IDENTIFIER = "nodeStyleIdentifier"; private static final String EDGE_STYLE_IDENTIFIER = "edgeStyleIdentifier"; // instance ******************************************* @Scope(P4Plugin.Scope) protected Context<IMap> mainMap; @Scope(P4Plugin.Scope) protected Context<Node> nodeSelection; private MapViewer<LayerInput> mapViewer; private Composite mapContainer; private FeatureSource fs; private OlEventListener selectFeatureListener; private Graph graph; private GraphLayerProvider graphLayerProvider; @Mandatory @Scope(P4Plugin.StyleScope) protected Context<FeatureStyleEditorInput> styleEditorInput; @Override public boolean wantsToBeShown() { if (site().path().size() == 2) { site().icon.set(GraphPlugin.images().svgImage("chart-bubble.svg", P4Plugin.HEADER_ICON_CONFIG)); site().tooltip.set(i18n.get("tooltip")); site().title.set(""); return true; } return false; } @Override public void init() { site().title.set(i18n.get("title")); site().preferredWidth.set(650); if (!site().memento().optString(NODE_STYLE_IDENTIFIER).isPresent()) { FeatureStyle featureStyle = P4Plugin.styleRepo().newFeatureStyle(); DefaultStyle.fillPointStyle(featureStyle); TextStyle textStyle = DefaultStyle.fillTextStyle(featureStyle, null); textStyle.property.createValue(AttributeValue.defaults("name", null, null)); featureStyle.store(); site().memento().putString(NODE_STYLE_IDENTIFIER, featureStyle.id()); } if (!site().memento().optString(EDGE_STYLE_IDENTIFIER).isPresent()) { FeatureStyle featureStyle = P4Plugin.styleRepo().newFeatureStyle(); DefaultStyle.fillLineStyle(featureStyle); featureStyle.store(); site().memento().putString(EDGE_STYLE_IDENTIFIER, featureStyle.id()); } } @Override public void dispose() { super.dispose(); if (graphLayerProvider != null) { graphLayerProvider.dispose(); } } @Override public void createContents(final Composite parent) { try { if (!featureLayer.isPresent()) { tk().createFlowText(parent, i18n.get("noFeatures")); return; } // this.parent = parent; parent.setLayout(FormLayoutFactory.defaults().create()); MdToolbar2 toolbar = tk().createToolbar(parent, SWT.TOP); new NodeStylerItem(toolbar); new EdgeStylerItem(toolbar); final TreeMap<String, GraphFunction> functions = Maps.newTreeMap(); for (Class<GraphFunction> cl : AVAILABLE_FUNCTIONS) { try { GraphFunction function = cl.newInstance(); functions.put(function.title(), function); } catch (Exception e) { throw new RuntimeException(e); } } final Composite functionContainer = tk().createComposite(parent, SWT.NONE); final ComboViewer combo = new ComboViewer(parent, SWT.SINGLE | SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY); combo.setContentProvider(new ArrayContentProvider()); combo.setInput(functions.keySet()); combo.addSelectionChangedListener(ev -> { String selected = SelectionAdapter.on(ev.getSelection()).first(String.class).get(); GraphFunction function = functions.get(selected); FormDataFactory.on(functionContainer).top(combo.getCombo(), 5).height(function.preferredHeight()) .left(0).right(100); UIUtils.disposeChildren(functionContainer); // create panel // Section section = tk().createSection( functionContainer, function.description(), ExpandableComposite.TREE_NODE, Section.SHORT_TITLE_BAR, Section.FOCUS_TITLE, SWT.BORDER ); // section.setBackground( UIUtils.getColor( 235, 235, 235) ); // ((Composite)section.getClient()).setLayout( FormLayoutFactory.defaults().create() ); IPanelSection section = tk().createPanelSection(functionContainer, function.description(), SWT.Expand, IPanelSection.EXPANDABLE); section.getControl().setBackground(UIUtils.getColor(235, 235, 235)); section.getBody().setBackground(UIUtils.getColor(235, 235, 235)); section.setExpanded(true); section.getBody().setLayout(FormLayoutFactory.defaults().create()); // graph.clear(); function.createContents(tk(), section.getBody(), graph); if (!section.isExpanded()) { section.setExpanded(true); } FormDataFactory.on(section.getBody()).fill(); // functionContainer.layout(); parent.layout(); }); // // mapContainer mapContainer = tk().createComposite(parent, SWT.NONE); mapContainer.setLayout(new FillLayout()); if (mapViewer != null) { mapViewer.dispose(); } createMapViewer(); // layout on(toolbar.getControl()).left(0, 3).right(100, -3).top(0, 5); final Label selectLabel = tk().createLabel(parent, i18n.get("selectFunction"), SWT.NONE); on(selectLabel).top(toolbar.getControl(), 8).left(1); on(combo.getCombo()).top(selectLabel, 2).left(1); on(functionContainer).top(combo.getCombo(), 5).height(0).left(0).right(100); on(mapContainer).fill().top(functionContainer, 5); } catch (Exception e) { StatusDispatcher.handleError("", e); } } protected void createMapViewer() { mapViewer = new MapViewer<LayerInput>(mapContainer); // must be global, because its used as eventlistener // ImageLayerProvider and VectorLayerProvider are supported graphLayerProvider = new ImageLayerProvider(tk(), mapViewer, featureLayer.get().layer(), id -> { try { // xxx add a filter for all features with a distance of 1 to the // current feature Node selectedNode = graph.getNode(id); if (selectedNode != null) { nodeSelection.set(selectedNode); getContext().openPanel(site().path(), SelectedNodePanel.ID); } } catch (Exception e) { StatusDispatcher.handleError("", e); } }, site().memento().getString(NODE_STYLE_IDENTIFIER), site().memento().getString(EDGE_STYLE_IDENTIFIER)); mapViewer.layerProvider.set(graphLayerProvider); mapViewer.contentProvider.set(new ArrayContentProvider()); mapViewer.maxExtent.set(graphLayerProvider.referenceEnvelope()); mapViewer.addMapControl(new MousePositionControl()); // mapViewer.addMapControl( new ScaleLineControl() ); mapViewer.setInput(graphLayerProvider.layers()); mapViewer.getControl().setBackground(UIUtils.getColor(0xff, 0xff, 0xff)); mapContainer.layout(); graph = new GephiGraph(graphLayerProvider.graphUi()); // graph = new GraphStreamGraph( graphLayerProvider.graphUi() ); } class NodeStylerItem extends ActionItem { public NodeStylerItem(ItemContainer container) { super(container); // XXX we need a text icon here icon.set(P4Plugin.images().svgImage("palette.svg", P4Plugin.TOOLBAR_ICON_CONFIG)); tooltip.set(i18n.get("nodeStylerTooltip")); action.set(ev -> { FeatureStyleEditorInput input = new FeatureStyleEditorInput(); input.styleIdentifier.set(site().memento().getString(NODE_STYLE_IDENTIFIER)); input.featureStore.set(new FeatureCollectionStore(graphLayerProvider.graphUi().nodeCollection())); // FIXME input.featureType.set( ); styleEditorInput.set(input); getContext().openPanel(site().path(), LayerStylePanel.ID); }); } } class EdgeStylerItem extends ActionItem { public EdgeStylerItem(ItemContainer container) { super(container); // XXX we need a text icon here icon.set(P4Plugin.images().svgImage("palette.svg", P4Plugin.TOOLBAR_ICON_CONFIG)); tooltip.set(i18n.get("edgeStylerTooltip")); action.set(ev -> { FeatureStyleEditorInput input = new FeatureStyleEditorInput(); input.styleIdentifier.set(site().memento().getString(EDGE_STYLE_IDENTIFIER)); input.featureStore.set(new FeatureCollectionStore(graphLayerProvider.graphUi().edgeCollection())); // FIXME input.featureType.set( ); styleEditorInput.set(input); getContext().openPanel(site().path(), LayerStylePanel.ID); }); } } private String resourceIdentifier(final FeatureSource selectedFeatureSource) throws IOException { IResolvableInfo info = P4Plugin.localCatalog().localFeaturesStoreInfo(); IResourceInfo res = ((RServiceInfo) info.getServiceInfo()).resource(selectedFeatureSource); return AllResolver.resourceIdentifier(res); } }