@Before public void init() { when(consumer.getOwner()).thenReturn(owner); i18n = I18nFactory.getI18n( getClass(), Locale.US, I18nFactory.READ_PROPERTIES | I18nFactory.FALLBACK); translator = new EntitlementRulesTranslator(i18n); entitler = new Entitler( pm, cc, i18n, ef, sink, translator, entitlementCurator, config, ownerProductCurator, poolCurator, productCurator, productManager, productAdapter, contentManager); }
@Before public void setUp() { i18n = I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK); when(eventBuilder.setOldEntity(any(Consumer.class))).thenReturn(eventBuilder); when(eventBuilder.setNewEntity(any(Consumer.class))).thenReturn(eventBuilder); when(eventFactory.getEventBuilder(any(Target.class), any(Type.class))).thenReturn(eventBuilder); }
@Before public void setupTest() { this.i18n = I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK); this.hypervisorType = new ConsumerType(ConsumerTypeEnum.HYPERVISOR); this.consumerResource = new ConsumerResource( this.consumerCurator, this.consumerTypeCurator, null, this.subscriptionService, null, this.idCertService, null, this.i18n, this.sink, this.eventFactory, null, null, this.userService, null, null, null, null, this.ownerCurator, this.activationKeyCurator, null, this.complianceRules, this.deletedConsumerCurator, null, new CandlepinCommonTestConfig()); hypervisorResource = new HypervisorResource( consumerResource, poolManager, consumerCurator, this.deletedConsumerCurator, i18n); // Ensure that we get the consumer that was passed in back from the create call. when(consumerCurator.create(any(Consumer.class))) .thenAnswer( new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { return invocation.getArguments()[0]; } }); when(complianceRules.getStatus(any(Consumer.class), any(Date.class))) .thenReturn(new ComplianceStatus(new Date())); }
/** * The {@code ValueReference} implementation of {@code ColorParameter}. That means that this class * is used to retrieve color values by using a table {@code DataSet} as specified in {@link * ValueReference ValueReference}. * * <p>Note that the {@code DataSet} is not directly attached to the class, and must be specified * each time you call {@code getValue}. * * @author Maxence Laurent * @author Alexis Guéganno * @author Erwan Bocher */ public class ColorAttribute extends ValueReference implements ColorParameter { private static final I18n I18N = I18nFactory.getI18n(ColorAttribute.class); /** * Instanciates the attribute with the name of the column where to search. * * @param fieldName */ public ColorAttribute(String fieldName) { super(fieldName); } /** * Build a <code>colorAttribute</code> from its JAXB representation. * * @param expr * @throws org.orbisgis.coremap.renderer.se.SeExceptions.InvalidStyle */ public ColorAttribute(JAXBElement<String> expr) throws InvalidStyle { super(expr); } @Override public Color getColor(ResultSet rs, long fid) throws ParameterException { try { return Color.getColor(getFieldValue(rs, fid).toString()); } catch (SQLException e) { throw new ParameterException( I18N.tr("Could not fetch feature attribute \"{0}\"", getColumnName()), e); } } @Override public Color getColor(Map<String, Object> map) throws ParameterException { try { return Color.getColor(getFieldValue(map).toString()); } catch (ParameterException e) { throw new ParameterException( I18N.tr("Could not fetch feature attribute \"{0}\"", getColumnName()), e); } } }
@Before public void init() { i18n = I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK); cc = mock(ContentCurator.class); envContentCurator = mock(EnvironmentContentCurator.class); poolManager = mock(PoolManager.class); oc = mock(OwnerCurator.class); productCurator = mock(ProductCurator.class); ocr = new OwnerContentResource( cc, i18n, new DefaultUniqueIdGenerator(), envContentCurator, poolManager, productCurator, oc); }
/** * Cancel button on the Drawing ToolBar * * @author Nicolas Fortin */ public class ActionUndo extends ActionDataSource { private static final I18n I18N = I18nFactory.getI18n(ActionUndo.class); private static final Logger LOGGER = Logger.getLogger(ActionUndo.class); /** * Constructor * * @param extension MapEditor instance */ public ActionUndo(MapEditorExtension extension) { super(ToolBarAction.DRAW_UNDO, I18N.tr("Undo"), extension, OrbisGISIcon.getIcon("edit-undo")); putValue(SHORT_DESCRIPTION, I18N.tr("Undo the last modification")); setLogicalGroup(ToolBarAction.DRAWING_GROUP); } @Override protected void checkActionState() { super.checkActionState(); // Active only if the DataSource is modified if (ActionTools.isVisible(this)) { DataSource dataSource = getExtension().getMapElement().getMapContext().getActiveLayer().getDataSource(); setEnabled(dataSource != null && dataSource.canUndo()); } } @Override public void actionPerformed(ActionEvent ae) { MapElement loadedMap = getExtension().getMapElement(); if (loadedMap != null) { try { loadedMap.getMapContext().getActiveLayer().getDataSource().undo(); } catch (DriverException ex) { LOGGER.error(ex.getLocalizedMessage(), ex); } } } }
/** * A "AreaSymbolizer" specifies the rendering of a polygon or other area/surface geometry, including * its interior fill and border stroke. * * <p>In addition of the properties inherited from <code>VectorSymbolizer</code> an <code> * AreaSymbolizer</code> is defined with a perpendicular offset, a <code>Stroke</code> (to draw its * limit, and as a <code>StrokeNode</code>) and a <code>Fill</code> (to paint its interior, and as a * <code>FillNode</code>). * * @author Maxence Laurent, Alexis Guéganno */ public final class AreaSymbolizer extends VectorSymbolizer implements FillNode, StrokeNode { private Translate translate; private RealParameter perpendicularOffset; private Stroke stroke; private Fill fill; private static final I18n I18N = I18nFactory.getI18n(AreaSymbolizer.class, Locale.getDefault(), I18nFactory.FALLBACK); /** * Build a new AreaSymbolizer, named "Area Symbolizer". It is defined with a <code>SolidFill * </code> and a <code>PenStroke</code> */ public AreaSymbolizer() { super(); name = I18N.tr("Area Symbolizer"); this.setFill(new SolidFill()); this.setStroke(new PenStroke()); } /** * Build a new <code>AreaSymbolizer</code>, using a JAXB element to fill its properties. * * @param st * @throws org.orbisgis.coremap.renderer.se.SeExceptions.InvalidStyle */ public AreaSymbolizer(JAXBElement<AreaSymbolizerType> st) throws InvalidStyle { super(st); AreaSymbolizerType ast = st.getValue(); if (ast.getGeometry() != null) { this.setGeometryAttribute(new GeometryAttribute(ast.getGeometry())); } if (ast.getUom() != null) { setUom(Uom.fromOgcURN(ast.getUom())); } if (ast.getPerpendicularOffset() != null) { this.setPerpendicularOffset( SeParameterFactory.createRealParameter(ast.getPerpendicularOffset())); } if (ast.getDisplacement() != null) { this.setTranslate(new Translate(ast.getDisplacement())); } if (ast.getFill() != null) { this.setFill(Fill.createFromJAXBElement(ast.getFill())); } if (ast.getStroke() != null) { this.setStroke(Stroke.createFromJAXBElement(ast.getStroke())); } } @Override public void setStroke(Stroke stroke) { if (stroke != null) { stroke.setParent(this); } this.stroke = stroke; } @Override public Stroke getStroke() { return stroke; } @Override public void setFill(Fill fill) { if (fill != null) { fill.setParent(this); } this.fill = fill; } @Override public Fill getFill() { return fill; } /** * Retrieve the geometric transformation that must be applied to the geometries. * * @return The transformation associated to this Symbolizer. */ public Translate getTranslate() { return translate; } /** * Get the geometric transformation that must be applied to the geometries. * * @param translate */ public void setTranslate(Translate translate) { this.translate = translate; // translate.setParent(this); } /** * Get the current perpendicular offset associated to this Symbolizer. It allows to draw polygons * larger or smaller than their actual geometry. The meaning of the value is dependant of the * <code>Uom</code> instance associated to this <code>Symbolizer</code>. * * @return The offset as a <code>RealParameter</code>. A positive value will cause the polygons to * be drawn larger than their original size, while a negative value will cause the drawing of * smaller polygons. */ public RealParameter getPerpendicularOffset() { return perpendicularOffset; } /** * Set the current perpendicular offset associated to this Symbolizer. It allows to draw polygons * larger or smaller than their actual geometry. The meaning of the value is dependant of the * <code>Uom</code> instance associated to this <code>Symbolizer</code>. * * @param perpendicularOffset The offset as a <code>RealParameter</code>. A positive value will * cause the polygons to be drawn larger than their original size, while a negative value will * cause the drawing of smaller polygons. */ public void setPerpendicularOffset(RealParameter perpendicularOffset) { this.perpendicularOffset = perpendicularOffset; if (this.perpendicularOffset != null) { this.perpendicularOffset.setContext(RealParameterContext.REAL_CONTEXT); this.perpendicularOffset.setParent(this); } } /** * @param g2 * @param rs * @param fid * @throws ParameterException * @throws IOException error while accessing external resource * @throws java.sql.SQLException */ @Override public void draw( Graphics2D g2, ResultSet rs, long fid, boolean selected, MapTransform mt, Geometry the_geom) throws ParameterException, IOException, SQLException { List<Shape> shapes = new LinkedList<Shape>(); shapes.add(mt.getShape(the_geom, true)); Map<String, Object> map = getFeaturesMap(rs, fid); for (Shape shp : shapes) { if (this.getTranslate() != null) { shp = getTranslate() .getAffineTransform( map, getUom(), mt, (double) mt.getWidth(), (double) mt.getHeight()) .createTransformedShape(shp); } if (shp != null) { if (fill != null) { fill.draw(g2, map, shp, selected, mt); } if (stroke != null) { double offset = 0.0; if (perpendicularOffset != null) { offset = Uom.toPixel( perpendicularOffset.getValue(rs, fid), getUom(), mt.getDpi(), mt.getScaleDenominator(), null); } stroke.draw(g2, map, shp, selected, mt, offset); } } } } @Override public JAXBElement<AreaSymbolizerType> getJAXBElement() { ObjectFactory of = new ObjectFactory(); AreaSymbolizerType s = of.createAreaSymbolizerType(); this.setJAXBProperty(s); if (this.getGeometryAttribute() != null) { s.setGeometry(getGeometryAttribute().getJAXBGeometryType()); } if (getUom() != null) { s.setUom(this.getUom().toURN()); } if (getTranslate() != null) { s.setDisplacement(getTranslate().getJAXBType()); } if (this.perpendicularOffset != null) { s.setPerpendicularOffset(perpendicularOffset.getJAXBParameterValueType()); } if (fill != null) { s.setFill(fill.getJAXBElement()); } if (stroke != null) { s.setStroke(stroke.getJAXBElement()); } return of.createAreaSymbolizer(s); } @Override public List<SymbolizerNode> getChildren() { List<SymbolizerNode> ls = new ArrayList<SymbolizerNode>(4); if (this.getGeometryAttribute() != null) { ls.add(this.getGeometryAttribute()); } if (translate != null) { ls.add(translate); } if (fill != null) { ls.add(fill); } if (perpendicularOffset != null) { ls.add(perpendicularOffset); } if (stroke != null) { ls.add(stroke); } return ls; } }
/** * Display a UI with the name of all supported legends and their coresponding representation. * * @author ebocher */ public class LegendUIChooser implements UIPanel { private static final I18n I18N = I18nFactory.getI18n(Toc.class); private static final Logger LOGGER = Logger.getLogger(LegendUIChooser.class); private final String[] names; private final ILegendPanel[] ids; private JPanel mainPanel; private JList lst; private JLabel imageLabel; /** * Set the names for supported legends and their UIPanels * * @param names * @param ids */ public LegendUIChooser(String[] names, ILegendPanel[] ids) { this.names = Arrays.copyOf(names, names.length); this.ids = Arrays.copyOf(ids, ids.length); init(); } /** Create the UI */ private void init() { mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); lst = new JList(); DefaultListModel model = new DefaultListModel(); for (int i = 0; i < names.length; i++) { model.addElement(names[i]); } lst.setModel(model); lst.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); lst.addListSelectionListener( new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent lse) { onThumbnailChange(lse); } }); lst.setSelectedIndex(0); mainPanel.add(new JScrollPane(lst), BorderLayout.WEST); mainPanel.add(imageLabel, BorderLayout.EAST); } /** Change the thumbnail according the type of legend. */ public void onThumbnailChange(ListSelectionEvent lse) { if (imageLabel == null) { imageLabel = new JLabel(); } imageLabel.setIcon(getThumbnail()); } @Override public String getTitle() { return I18N.tr("Legend selection"); } @Override public String validateInput() { if (lst.getSelectedIndex() == -1) { return UIFactory.getI18n().tr("A legend must be selected."); } return null; } @Override public Component getComponent() { return mainPanel; } /** * Create the thumbnail image * * @return */ public ImageIcon getThumbnail() { ILegendPanel legendPanel = (ILegendPanel) getSelected(); String legendId = legendPanel.getLegend().getLegendTypeId(); if (legendId.equals("org.orbisgis.legend.thematic.proportional.ProportionalPoint")) { return createImageIcon("thumbnail_proportionnal_point.png"); } else if (legendId.equals("org.orbisgis.legend.thematic.proportional.ProportionalLine")) { return createImageIcon("thumbnail_proportionnal_line.png"); } else if (legendId.equals("org.orbisgis.legend.thematic.constant.UniqueSymbolPoint")) { return createImageIcon("thumbnail_unique_point.png"); } else if (legendId.equals("org.orbisgis.legend.thematic.constant.UniqueSymbolLine")) { return createImageIcon("thumbnail_unique_line.png"); } else if (legendId.equals("org.orbisgis.legend.thematic.constant.UniqueSymbolArea")) { return createImageIcon("thumbnail_unique_area.png"); } else if (legendId.equals("org.orbisgis.legend.thematic.recode.RecodedLine")) { return createImageIcon("thumbnail_recoded_line.png"); } else if (legendId.equals("org.orbisgis.legend.thematic.recode.RecodedArea")) { return createImageIcon("thumbnail_recoded_area.png"); } else if (legendId.equals("org.orbisgis.legend.thematic.recode.RecodedPoint")) { return createImageIcon("thumbnail_recoded_point.png"); } else { return createImageIcon("thumbnail_not_found.png"); } } /** Returns an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(String path) { java.net.URL imgURL = LegendUIChooser.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { LOGGER.error(I18N.tr("Couldn't find file") + ": " + path); return null; } } public Object getSelected() { return ids[lst.getSelectedIndex()]; } public int getSelectedIndex() { return lst.getSelectedIndex(); } public Object[] getSelectedElements() { ArrayList<Object> ret = new ArrayList<Object>(); int[] indexes = lst.getSelectedIndices(); for (int index : indexes) { ret.add(ids[index]); } return ret.toArray(); } @Override public URL getIconURL() { return UIFactory.getDefaultIcon(); } }
/** * "Proportional Point" UI. * * @author Alexis Guéganno * @author Adam Gouge */ public final class PnlProportionalPointSE extends PnlProportional { private static final I18n I18N = I18nFactory.getI18n(PnlProportionalPointSE.class); private ProportionalPoint proportionalPoint; private int geometryType = SimpleGeometryType.ALL; private MouseListener l; /** * Builds a panel based on a new legend. * * @param lc LegendContext */ public PnlProportionalPointSE(LegendContext lc) { this(lc, new ProportionalPoint()); } /** * Builds a panel based on the given legend. * * @param lc LegendContext * @param legend Legend */ public PnlProportionalPointSE(LegendContext lc, ProportionalPoint legend) { super(lc); this.proportionalPoint = legend; this.geometryType = lc.getGeometryType(); initPreview(); buildUI(); } @Override public ProportionalPoint getLegend() { return proportionalPoint; } @Override public void buildUI() { JPanel glob = new JPanel(new MigLayout("wrap 2")); glob.add( new ProportionalPointPanel( proportionalPoint, getPreview(), I18N.tr(MARK_SETTINGS), ds, table, geometryType)); // The preview is created only once while the other panels are // created twice, currently. Adds a locally stored listener to // avoid having it twice because of this double call of // buildUI. CanvasSE prev = getPreview(); if (l == null || prev.getMouseListeners().length == 0) { l = EventHandler.create(MouseListener.class, this, "onClickOnPreview", "", "mouseClicked"); prev.addMouseListener(l); } glob.add(new PreviewPanel(getPreview())); this.add(glob); } /** Opens a OK - Cancel window used to edit the symbol configuration, size excepted. */ public void onClickOnPreview(MouseEvent mouseEvent) { // We create a copy of the constant part of the symbol PointParameters pp = new PointParameters( proportionalPoint.getPenStroke().getLineColor(), proportionalPoint.getPenStroke().getLineOpacity(), proportionalPoint.getPenStroke().getLineWidth(), proportionalPoint.getPenStroke().getDashArray(), proportionalPoint.getFillLegend().getColor(), proportionalPoint.getFillLegend().getOpacity(), 3.0, 3.0, proportionalPoint.getWellKnownName()); UniqueSymbolPoint usp = new UniqueSymbolPoint(pp); if (proportionalPoint.getPenStroke() instanceof NullPenStrokeLegend) { usp.setPenStroke(new NullPenStrokeLegend()); } if (proportionalPoint.getFillLegend() instanceof NullSolidFillLegend) { usp.setFillLegend(new NullSolidFillLegend()); } usp.setStrokeUom(proportionalPoint.getStrokeUom()); usp.setSymbolUom(proportionalPoint.getSymbolUom()); ConfigPanel cp = new ConfigPanel(usp); if (UIFactory.showDialog(cp)) { affectValues(usp); getPreview().imageChanged(); } } /** * Uses the configuration found in the given {@link UniqueSymbolPoint} to configure the Stroke, * Fill and WKN of the attached ProportionalPoint. * * @param usp The input {@link UniqueSymbolPoint}. */ private void affectValues(UniqueSymbolPoint usp) { boolean strokeNotNull = !(usp.getPenStroke() instanceof NullPenStrokeLegend); boolean fillNotNull = !(usp.getFillLegend() instanceof NullSolidFillLegend); if (strokeNotNull) { if (proportionalPoint.getPenStroke() instanceof NullPenStrokeLegend) { proportionalPoint.setPenStroke(new ConstantPenStrokeLegend()); } proportionalPoint.getPenStroke().setLineColor(usp.getPenStroke().getLineColor()); proportionalPoint.getPenStroke().setLineOpacity(usp.getPenStroke().getLineOpacity()); proportionalPoint.getPenStroke().setLineWidth(usp.getPenStroke().getLineWidth()); proportionalPoint.getPenStroke().setDashArray(usp.getPenStroke().getDashArray()); } else { proportionalPoint.setPenStroke(new NullPenStrokeLegend()); } if (fillNotNull) { if (proportionalPoint.getFillLegend() instanceof NullSolidFillLegend) { proportionalPoint.setFillLegend(new ConstantSolidFillLegend(new SolidFill())); } proportionalPoint.getFillLegend().setColor(usp.getFillLegend().getColor()); proportionalPoint.getFillLegend().setOpacity(usp.getFillLegend().getOpacity()); } else { proportionalPoint.setFillLegend(new NullSolidFillLegend()); } proportionalPoint.setWellKnownName(usp.getWellKnownName()); } private class ConfigPanel extends JPanel implements UIPanel { private UniqueSymbolPoint usp; public ConfigPanel(UniqueSymbolPoint point) { usp = point; } // ************************* UIPanel *************************** @Override public URL getIconURL() { return UIFactory.getDefaultIcon(); } @Override public String getTitle() { return I18N.tr("Stroke and fill settings"); } @Override public String validateInput() { return null; } @Override public Component getComponent() { JPanel glob = new JPanel(new MigLayout("wrap 1")); // Update only a local preview until the changes are applied. // About #497 CanvasSE localPreview = new CanvasSE(usp.getSymbolizer()); glob.add(new LinePanel(usp, localPreview, I18N.tr(BORDER_SETTINGS), true, true)); glob.add(new AreaPanel(usp, localPreview, I18N.tr(FILL_SETTINGS), true)); glob.add(new PreviewPanel(localPreview)); return glob; } } }
public class Scanner extends FieldEditorPreferencePage implements IWorkbenchPreferencePage, SelectionListener { private final Map<String, IntegerFieldEditor> intFieldMap = new HashMap<String, IntegerFieldEditor>(); private static final I18n i18n = I18nFactory.getI18n(Scanner.class); Button selectScannerBtn; AdvancedRadioGroupFieldEditor driverTypeRadio; IntegerFieldEditor brightnessInputField, contrastInputField; public Scanner() { super(GRID); setPreferenceStore(ScannerConfigPlugin.getDefault().getPreferenceStore()); } @Override public void init(IWorkbench workbench) { setPreferenceStore(ScannerConfigPlugin.getDefault().getPreferenceStore()); } @SuppressWarnings("nls") @Override public void createFieldEditors() { selectScannerBtn = new Button(getFieldEditorParent(), SWT.NONE); selectScannerBtn.setText(i18n.tr("Select Scanner")); selectScannerBtn.setImage( ScannerConfigPlugin.getDefault().getImageRegistry().get(ScannerConfigPlugin.IMG_SCANNER)); selectScannerBtn.addSelectionListener(this); driverTypeRadio = new AdvancedRadioGroupFieldEditor( PreferenceConstants.SCANNER_DRV_TYPE, i18n.tr("Driver Type"), 2, new String[][] { {"WIA", PreferenceConstants.SCANNER_DRV_TYPE_WIA}, {"TWAIN", PreferenceConstants.SCANNER_DRV_TYPE_TWAIN} }, getFieldEditorParent(), true); addField(driverTypeRadio); brightnessInputField = new IntegerFieldEditor( PreferenceConstants.SCANNER_BRIGHTNESS, i18n.tr("Brightness:"), getFieldEditorParent()); brightnessInputField.setValidRange(-1000, 1000); addField(brightnessInputField); intFieldMap.put(brightnessInputField.getPreferenceName(), brightnessInputField); contrastInputField = new IntegerFieldEditor( PreferenceConstants.SCANNER_CONTRAST, i18n.tr("Contrast:"), getFieldEditorParent()); contrastInputField.setValidRange(-1000, 1000); addField(contrastInputField); intFieldMap.put(contrastInputField.getPreferenceName(), contrastInputField); } private void setEnableAllWidgets(boolean enableSettings) { selectScannerBtn.setEnabled(true); driverTypeRadio.setEnabled(enableSettings, getFieldEditorParent()); brightnessInputField.setEnabled(enableSettings, getFieldEditorParent()); contrastInputField.setEnabled(enableSettings, getFieldEditorParent()); } @SuppressWarnings("nls") @Override public void widgetSelected(SelectionEvent e) { if (e.getSource() != selectScannerBtn) return; ScanLibResult scanlibResult = ScanLib.getInstance().selectSourceAsDefault(); if (scanlibResult.getResultCode() != ScanLibResult.Result.SUCCESS) { return; } ScanLibResult scannerCapResult = ScanLib.getInstance().getScannerCapability(); int scannerCap = scannerCapResult.getValue(); if (scanlibResult.getResultCode() != ScanLibResult.Result.SUCCESS) { // just stay with the last selected source if ((scannerCap & ScanLib.CAP_IS_SCANNER) != 0) { return; } setEnableAllWidgets(false); BgcPlugin.openError(i18n.tr("Scanning Source Error"), scanlibResult.getMessage()); return; } IPreferenceStore prefs = ScannerConfigPlugin.getDefault().getPreferenceStore(); String drvSetting = null; boolean[] drvRadioSettings = new boolean[] {false, false}; if ((scannerCap & ScanLib.CAP_IS_WIA) != 0) { drvSetting = PreferenceConstants.SCANNER_DRV_TYPE_WIA; drvRadioSettings[1] = true; } else { drvSetting = PreferenceConstants.SCANNER_DRV_TYPE_TWAIN; drvRadioSettings[0] = true; } prefs.setValue(PreferenceConstants.SCANNER_DRV_TYPE, drvSetting); driverTypeRadio.setSelectionArray(drvRadioSettings); driverTypeRadio.doLoad(); setEnableAllWidgets(true); } @Override public void widgetDefaultSelected(SelectionEvent e) { // do nothing } }
/** * Check for a valid GDMS value. * * @author Nicolas Fortin */ public class ValueInputVerifier extends InputVerifier { private DataSource ds; private int fieldIndex; private static final Logger LOGGER = Logger.getLogger(ValueInputVerifier.class); private static final I18n I18N = I18nFactory.getI18n(ValueInputVerifier.class); /** * @param ds DataSource * @param fieldIndex Field index */ public ValueInputVerifier(DataSource ds, int fieldIndex) { this.ds = ds; this.fieldIndex = fieldIndex; } @Override public boolean shouldYieldFocus(JComponent jComponent) { return false; } /** * @param value String representation of the field * @return The corresponding value or null value if constraints are not respected. * @throws ParseException Unable to parse provided string * @throws DriverException The driver throw this exception */ public Value getValue(Object value) throws ParseException, DriverException { Type fieldType = ds.getMetadata().getFieldType(fieldIndex); Value inputValue; if (value != null && (fieldType.getTypeCode() == Type.STRING || !value.toString().isEmpty())) { inputValue = ValueFactory.createValueByType(value.toString(), fieldType.getTypeCode()); } else { inputValue = ValueFactory.createNullValue(); } String error = ds.check(fieldIndex, inputValue); if (error == null || error.isEmpty()) { return inputValue; } else { throw new ParseException(error, 0); } } @Override public boolean verify(JComponent jComponent) { if (jComponent instanceof JTextComponent) { String value = ((JTextComponent) jComponent).getText(); try { getValue(value); return true; } catch (ParseException ex) { LOGGER.error(I18N.tr("The entered value cannot be parsed"), ex); return false; } catch (Exception ex) { LOGGER.error(ex.getLocalizedMessage(), ex); return false; } } else { throw new IllegalArgumentException("This verifier is only valid on Text field component"); } } }
public abstract class World { private boolean isDelayed = false; // whether we display interactively or not private boolean isAnswer = false; private int delay = 100; // delay between two instruction executions of an entity. protected List<Entity> entities = new ArrayList<Entity>(); private String name; public I18n i18n = I18nFactory.getI18n( getClass(), "org.plm.i18n.Messages", Game.getInstance().getLocale(), I18nFactory.FALLBACK); public World(String name) { this.name = name; } public World(World w2) { this(w2.getName()); reset(w2); } public World copy() { World res = null; try { res = this.getClass().getConstructor(this.getClass()).newInstance(this); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } return res; } public String getDebugInfo() { return ""; } /** * Reset the content of a world to be the same than the one passed as argument * * @param initialWorld */ public void reset(World initialWorld) { entities = new ArrayList<Entity>(); for (Entity oldEntity : initialWorld.entities) { try { Entity newEntity = oldEntity.getClass().newInstance(); newEntity.copy(oldEntity); addEntity(newEntity); } catch (Exception e) { throw new RuntimeException( "Cannot copy entity of class " + oldEntity.getClass().getName(), e); } } this.isDelayed = initialWorld.isDelayed; this.delay = initialWorld.delay; this.parameters = (initialWorld.parameters != null ? initialWorld.parameters.clone() : null); notifyEntityUpdateListeners(); notifyWorldUpdatesListeners(); } public String getName() { return this.name; } public void setName(String n) { name = n; } public boolean isDelayed() { return isDelayed; } /** returns the delay to apply */ public int getDelay() { return this.delay; } /** * set the value of the UI delay which will be used on doDelay() * * <p>Default value: 100ms */ public void setDelay(int d) { this.delay = d; notifyWorldUpdatesListeners(); // notify the speed slider model } /** set current UI delay to what was defined as max UI delay with setDelayUI() */ public void doDelay() { isDelayed = true; } /** set current UI delay to 0 */ public void doneDelay() { isDelayed = false; } public void setAnswerWorld() { isAnswer = true; } public boolean isAnswerWorld() { return isAnswer; } public void addEntity(Entity b) { if (b.getWorld() != this) b.setWorld(this); entities.add(b); notifyEntityUpdateListeners(); } public void removeEntity(Entity b) { if (!entities.remove(b)) System.out.println("Ignoring a request to remove an unknown entity"); notifyEntityUpdateListeners(); } public void emptyEntities() { entities = new ArrayList<Entity>(); notifyEntityUpdateListeners(); } public void setEntities(List<Entity> l) { entities = l; notifyEntityUpdateListeners(); } public int getEntityCount() { return entities.size(); } public Entity getEntity(int i) { return entities.get(i); } public List<Entity> getEntities() { return entities; } public void runEntities(List<Thread> runnerVect, final ExecutionProgress progress) { final ProgrammingLanguage pl = Game.getProgrammingLanguage(); if (Game.getInstance().isDebugEnabled()) Logger.log("World:runEntities", "Programming language: " + pl); for (final Entity b : entities) { Thread runner = new Thread( new Runnable() { public void run() { Game.getInstance().statusArgAdd(getName()); pl.runEntity(b, progress); Game.getInstance().statusArgRemove(getName()); } }); Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread th, Throwable ex) { if (ex instanceof ThreadDeath) { String msg = "You interrupted the execution, did you fall into an infinite loop ?\n" + "Your program must stop by itself to successfully pass the exercise.\n"; progress.setExecutionError(Game.i18n.tr(msg)); progress.outcome = ExecutionProgress.outcomeKind.FAIL; } } }; // So that we can still stop it from the AWT Thread, even if an infinite loop occurs runner.setPriority(Thread.MIN_PRIORITY); runner.setUncaughtExceptionHandler(h); runner.start(); runnerVect.add(runner); } } /* who's interested in every details of the world changes */ private ArrayList<IWorldView> worldUpdatesListeners = new ArrayList<IWorldView>(); /* who's only interested in entities creation and destructions */ private ArrayList<IWorldView> entitiesUpdateListeners = new ArrayList<IWorldView>(); public void addWorldUpdatesListener(IWorldView v) { synchronized (this.worldUpdatesListeners) { this.worldUpdatesListeners.add(v); } } public void removeWorldUpdatesListener(IWorldView v) { synchronized (this.worldUpdatesListeners) { this.worldUpdatesListeners.remove(v); } } public void notifyWorldUpdatesListeners() { if (worldUpdatesListeners.isEmpty()) return; synchronized (this.worldUpdatesListeners) { for (IWorldView v : this.worldUpdatesListeners) { v.worldHasMoved(); } } } public void addEntityUpdateListener(IWorldView v) { synchronized (this.entitiesUpdateListeners) { this.entitiesUpdateListeners.add(v); } } public void removeEntityUpdateListener(IWorldView v) { synchronized (this.entitiesUpdateListeners) { this.entitiesUpdateListeners.remove(v); } } public void notifyEntityUpdateListeners() { synchronized (this.entitiesUpdateListeners) { for (IWorldView v : this.entitiesUpdateListeners) { v.worldHasChanged(); } } } /* IO related */ /** Returns whether this universe implements world I/O */ public boolean haveIO() { return false; } public World readFromFile(String path) throws IOException, BrokenWorldFileException { throw new RuntimeException("This universe does not implement world I/O"); } public void writeToFile(BufferedWriter f) throws IOException {} public void writeToFile(File outputFile) throws IOException { BufferedWriter bw = null; FileWriter fw = null; try { fw = new FileWriter(outputFile); bw = new BufferedWriter(fw); this.writeToFile(bw); } catch (IOException e) { throw e; } finally { if (bw != null) bw.close(); } } /* Find my UI */ public WorldView getView() { return new WorldView(this) { private static final long serialVersionUID = 1L; @Override public boolean isWorldCompatible(World world) { return false; } }; } public EntityControlPanel getEntityControlPanel() { return new EntityControlPanel() { private static final long serialVersionUID = 1L; @Override public void setEnabledControl(boolean enabled) {} }; } public abstract ImageIcon getIcon(); @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((entities == null) ? 0 : entities.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } /** * Checks whether the receiver world wins the exercise * * <p>https://www.youtube.com/watch?v=9QS0q3mGPGg * * @param standard a correction world that should be used to compare the receiver state */ public boolean winning(World standard) { return this.equals(standard); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof World)) return false; World other = (World) obj; if (entities == null) { if (other.entities != null) return false; } else if (!entities.equals(other.entities)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } String about = null; public String getAbout() { if (about == null) { String filename = getClass().getCanonicalName().replace('.', File.separatorChar); StringBuffer sb = null; try { sb = FileUtils.readContentAsText(filename, "html", true); } catch (IOException ex) { about = "File " + filename + ".html not found."; return about; } /* read it */ about = sb.toString(); } return "<html>\n" + PlmHtmlEditorKit.getCSS() + "<body>\n" + PlmHtmlEditorKit.filterHTML(about, Game.getInstance().isDebugEnabled()) + "</body>\n</html>\n"; } /** Set about to null in order to allows it to be reloaded in the right language */ public void resetAbout() { this.about = null; } protected Object[] parameters = null; public void setParameter(Object[] parameters) { this.parameters = parameters; } public Object[] getParameters() { return parameters; } public Object getParameter(int i) { return parameters[i]; } public void setSelectedEntity(Entity e) { notifyWorldUpdatesListeners(); // EntityUpdateListeners(); } /** * Returns the script except that must be injected within the environment before running user code * * <p>It should pass all order to the java entity, which were injected independently * * @throws ScriptException */ public abstract void setupBindings(ProgrammingLanguage lang, ScriptEngine engine) throws ScriptException; /** * Returns a textual representation of the differences from the receiver world to the one in * parameter */ public abstract String diffTo(World world); }
/** * The Simple Style Editor user interface. * * @author Alexis Guéganno * @author Adam Gouge * @author others */ public class SimpleStyleEditor extends JPanel implements UIPanel, LegendContext { /** Tree to display legends. */ private LegendTree legendTree; // ********** GRAPHICS ************** /** Used to switch between legend instances. */ private CardLayout cardLayout; /** Dialog panel. */ private JPanel dialogContainer; // ********** INITIALIZATION VARIABLES ************** /** Represents the current state of the map. */ private MapTransform mt; /** The type of the DataSource of the legend's layer currently being modified. */ private Type type; /** The layer we are editing. */ private ILayer layer; // ********** INITIALIZATION-LIKE VARIABLES ********** /** {@link SimpleGeometryType}. */ private int geometryType; /** {@link StyleWrapper} for the {@link Style}s of the layer we are editing. */ private StyleWrapper styleWrapper; // ********** IDS ************** /** Id for the {@link CardLayout} panel to be shown when there is no legend. */ private static final String NO_LEGEND_ID = "no-legend"; /** Id of the most recently added {@link CardLayout} panel. */ private static String lastUID = ""; // ********** OTHER ************** /** Translator. */ private static final I18n I18N = I18nFactory.getI18n(SimpleStyleEditor.class); /** Scroll increment (To fix slow scrolling). */ private static final int INCREMENT = 16; private static final Logger LOGGER = Logger.getLogger(SimpleStyleEditor.class); /** * Constructor * * @param mt Map transform * @param type Layer geometry type * @param layer Layer * @param style Style */ public SimpleStyleEditor(MapTransform mt, Type type, ILayer layer, Style style) { // Set the layout. super(new BorderLayout()); // Recover the first three paramters. this.mt = mt; this.type = type; this.layer = layer; // Get the geometry type and available legends. this.geometryType = (type == null) ? SimpleGeometryType.ALL : SimpleGeometryType.getSimpleType(type); // Initialize the dialog container, adding the empty dialog. cardLayout = new CardLayout(); dialogContainer = new JPanel(cardLayout); dialogContainer.setPreferredSize(new Dimension(640, 420)); addEmptyDialog(); // Add all panels. styleWrapper = addAllPanels(style); // Initialize the legend tree. legendTree = new LegendTree(this); // Put everything inside a split pane. JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, legendTree, dialogContainer); // Should be just wide enough for "Interval classification - Point" splitPane.setDividerLocation(260); Dimension minimumSize = new Dimension(100, 50); legendTree.setMinimumSize(minimumSize); dialogContainer.setMinimumSize(minimumSize); add(splitPane, BorderLayout.CENTER); } /** Adds the empty dialog to the card layout. */ private void addEmptyDialog() { JPanel textHolder = new JPanel(new BorderLayout()); JLabel text = new JLabel(I18N.tr("Add or select a legend.")); text.setHorizontalAlignment(SwingConstants.CENTER); textHolder.add(text, BorderLayout.CENTER); dialogContainer.add(NO_LEGEND_ID, textHolder); } /** * Adds the style, rule and symbol panels for the given style and returns the corresponding {@link * StyleWrapper}. * * @param style Style * @return The {@link StyleWrapper} corresponding to the style panel * @see #addRuleAndSymbolPanels(org.orbisgis.core.renderer.se.Style) */ private StyleWrapper addAllPanels(Style style) { // Get a style wrapper based on this style and the previous list // of rule wrappers constructed in addRuleAndSymbolPanels. StyleWrapper sw = new StyleWrapper(style, addRuleAndSymbolPanels(style)); addStylePanel(sw); return sw; } /** * Adds the style panel attached to the given {@link StyleWrapper}. * * @param sw StyleWrapper */ private void addStylePanel(StyleWrapper sw) { PnlStyle stylePanel = sw.getPanel(); stylePanel.setId(createNewID()); stylePanel.addPropertyChangeListener( EventHandler.create(PropertyChangeListener.class, this, "onNodeNameChange", "")); dialogContainer.add(stylePanel.getId(), getJScrollPane(stylePanel)); } /** * Gets a new {@link JScrollPane} on the given panel, setting the scroll increments appropriately. * * @param panel Panel * @return A new {@link JScrollPane} on the given panel */ private JScrollPane getJScrollPane(ISELegendPanel panel) { JScrollPane jsp = new JScrollPane(panel.getComponent()); jsp.getHorizontalScrollBar().setUnitIncrement(INCREMENT); jsp.getVerticalScrollBar().setUnitIncrement(INCREMENT); return jsp; } /** * Adds the rule and symbol panels for the rules and symbols attached to the given style and * returns a list of the corresponding {@link RuleWrapper}s. * * @param style Style * @return A list of {@link RuleWrapper}s corresponding to the newly added rule panels. * @see #addSymbolPanels(org.orbisgis.core.renderer.se.Rule) */ private List<RuleWrapper> addRuleAndSymbolPanels(Style style) { List<Rule> rules = style.getRules(); List<RuleWrapper> ruleWrapperList = new LinkedList<RuleWrapper>(); for (int i = 0; i < rules.size(); i++) { // Get the rule. Rule rule = rules.get(i); // Get a new RuleWrapper based on this rule and the list of // symbol panels constructed in addSymbolPanels. RuleWrapper ruleWrapper = new RuleWrapper(this, rule, addSymbolPanels(rule)); addRulePanel(ruleWrapper); // Add the rule wrapper panel to the list of rule wrapper panels. ruleWrapperList.add(ruleWrapper); } return ruleWrapperList; } /** * Adds the rule panel attached to the given {@link RuleWrapper}. * * @param ruleWrapper RuleWrapper */ private void addRulePanel(RuleWrapper ruleWrapper) { // Get the panel associated to this RuleWrapper, set its id, // initialize it and add a listener for when its node name changes. PnlRule rulePanel = ruleWrapper.getPanel(); rulePanel.setId(createNewID()); rulePanel.addPropertyChangeListener( EventHandler.create(PropertyChangeListener.class, this, "onNodeNameChange", "")); // Add the rule wrapper panel to the container after putting it in // a new JScrollPane. dialogContainer.add(rulePanel.getId(), getJScrollPane(rulePanel)); } /** * Adds the symbol panels for the legends (=symbols) attached to the given rule and returns a list * of the corresponding {@link ILegendPanel}s. * * @param rule Rule * @return A list of {@link ILegendPanel}s corresponding to the newly added symbol panels. */ private List<ILegendPanel> addSymbolPanels(Rule rule) { List<ILegendPanel> symbolPanelList = new LinkedList<ILegendPanel>(); // For each symbol in this rule, add its symbol panel to the list of // symbol panels. for (Symbolizer symb : rule.getCompositeSymbolizer().getSymbolizerList()) { symbolPanelList.add(addSymbolPanel(symb)); } return symbolPanelList; } /** * Adds the symbol panel attached to the given {@link Symbolizer} and returns the panel. * * @param symb Symbolizer * @return The newly generated symbol panel */ private ILegendPanel addSymbolPanel(Symbolizer symb) { // Get the legend corresponding to this symbolizer. Legend legend = LegendFactory.getLegend(symb); if (legend instanceof AbstractRecodedLegend) { DataSource dataSource = layer.getDataSource(); AbstractRecodedLegend leg = (AbstractRecodedLegend) legend; try { Metadata metadata = dataSource.getMetadata(); String f = leg.getLookupFieldName(); int in = metadata.getFieldIndex(f); leg.setComparator(AbstractRecodedLegend.getComparator(metadata.getFieldType(in))); } catch (DriverException e) { LOGGER.warn("Can't retrieve an accurate Comparator for this classification"); } } // Initialize a panel for this legend. ILegendPanel panel = ILegendPanelFactory.getILegendPanel(this, legend); // Give it a new id. panel.setId(createNewID()); // Add the symbol panel to the container after putting it in a // new JScrollPane. dialogContainer.add(panel.getId(), getJScrollPane(panel)); return panel; } /** * Creates a new unique ID for retrieving panels in the card layout. * * @return A new unique ID */ public static String createNewID() { String name = "gdms" + System.currentTimeMillis(); while (name.equals(lastUID)) { name = "" + System.currentTimeMillis(); } lastUID = name; return name; } /** Shows the dialog for the given legend in the card layout. */ protected void showDialogForLegend(ISELegendPanel selected) { cardLayout.show(dialogContainer, selected.getId()); } /** * Retrieves the currently selected legend in the tree and shows the corresponding dialog in the * card layout; shows the empty panel if no legend is selected. */ protected void showDialogForCurrentlySelectedLegend() { ISELegendPanel selected = legendTree.getSelectedPanel(); if (selected != null) { cardLayout.show(dialogContainer, selected.getId()); } else { cardLayout.show(dialogContainer, NO_LEGEND_ID); } } // ******************* EventHandler methods ********************** /** * Updates the name of the selected element when it changes. * * @param pce The original event */ public void onNodeNameChange(PropertyChangeEvent pce) { if (pce.getPropertyName().equals(PnlRule.NAME_PROPERTY)) { legendTree.selectedNameChanged(); } } /** * Initialize the given panel with this as {@link LegendContext}, set its id, add it to the * container inside a {@link JScrollPane} and show its dialog. * * @param panel The panel to initialize and show */ // TODO: Should this method be moved to LegendTree? public void legendAdded(ISELegendPanel panel) { panel.setId(createNewID()); dialogContainer.add(panel.getId(), getJScrollPane(panel)); showDialogForCurrentlySelectedLegend(); } /** * Remove the given panel from the card layout and refresh the display. * * @param panel Panel */ public void legendRemoved(ISELegendPanel panel) { cardLayout.removeLayoutComponent(panel.getComponent()); showDialogForCurrentlySelectedLegend(); } // TODO: Find usages / Document. public void legendRenamed(int idx, String newName) { showDialogForCurrentlySelectedLegend(); } // TODO: Find usages / Document. public void legendSelected() { showDialogForCurrentlySelectedLegend(); } // ************************* Getters ***************************** /** * Gets the style wrapper. * * @return The style wrapper */ public StyleWrapper getStyleWrapper() { return styleWrapper; } // ****************** LegendContext methods ********************** @Override public int getGeometryType() { return geometryType; } @Override public boolean isPoint() { return (geometryType & SimpleGeometryType.POINT) > 0; } @Override public boolean isLine() { return (geometryType & SimpleGeometryType.LINE) > 0; } @Override public boolean isPolygon() { return (geometryType & SimpleGeometryType.POLYGON) > 0; } @Override public ILayer getLayer() { return layer; } @Override public MapTransform getCurrentMapTransform() { return mt; } // ********************** UIPanel methods ************************ @Override public URL getIconURL() { return UIFactory.getDefaultIcon(); } @Override public String getTitle() { return I18N.tr("Simple Style Editor - {0}", layer.getName()); } @Override public String validateInput() { if (!legendTree.hasLegend()) { return I18N.tr("You must create at least one legend"); } List<String> errors = styleWrapper.validateInput(); StringBuilder sb = new StringBuilder(); for (String message : errors) { if (message != null && !message.isEmpty()) { sb.append(message); sb.append("\n"); } } String err = sb.toString(); if (err != null && !err.isEmpty()) { return err; } return null; } @Override public Component getComponent() { return this; } }
/** * OSGI Shell command GUI. GUI access to the Apache Felix Shell service. * * @url http://felix.apache.org/site/apache-felix-shell.html * @author Nicolas Fortin */ public class PluginShell extends JPanel implements DockingPanel { private static final Logger LOGGER = Logger.getLogger("gui." + PluginShell.class); private static final String SHELL_SERVICE_REFERENCE = "org.apache.felix.shell.ShellService"; private DockingPanelParameters parameters = new DockingPanelParameters(); private static final I18n I18N = I18nFactory.getI18n(PluginShell.class); private final BundleContext hostBundle; private JTextField commandField = new JTextField(); private JTextPane outputField = new JTextPane(); private TextDocumentOutputStream info = new TextDocumentOutputStream(outputField, Color.BLACK); private TextDocumentOutputStream error = new TextDocumentOutputStream(outputField, Color.RED.darker()); public PluginShell(final BundleContext hostBundle) { super(new BorderLayout()); this.hostBundle = hostBundle; parameters.setName("plugin-shell"); parameters.setTitle(I18N.tr("Plugin Shell")); parameters.setTitleIcon(new ImageIcon(PluginShell.class.getResource("panel_icon.png"))); outputField.setEditable(false); outputField.setText(I18N.tr("Plugin shell, type \"help\" for command list.\n")); // Initialising components // The shell is composed by a logging part and a command line part add(new JScrollPane(outputField), BorderLayout.CENTER); add(commandField, BorderLayout.SOUTH); commandField.addActionListener( EventHandler.create(ActionListener.class, this, "onValidateCommand")); } /** User type enter on command input */ public void onValidateCommand() { final String command = commandField.getText(); SwingUtilities.invokeLater( new Runnable() { public void run() { executeCommand(command); } }); commandField.setText(""); } private void executeCommand(String command) { // Get shell service. ServiceReference ref = hostBundle.getServiceReference(SHELL_SERVICE_REFERENCE); if (ref == null) { LOGGER.error(I18N.tr("No shell service is available.")); return; } ShellService shell = (ShellService) hostBundle.getService(ref); try { // Print the command line in the output window. try { outputField .getDocument() .insertString(outputField.getDocument().getLength(), "osgi> " + command + "\n", null); } catch (BadLocationException ex) { LOGGER.debug(ex.getLocalizedMessage(), ex); // ignore } try { shell.executeCommand(command, new PrintStream(info), new PrintStream(error)); } catch (Exception ex) { LOGGER.error(ex.getLocalizedMessage(), ex); } finally { try { // Send messages to the window info.flush(); error.flush(); outputField.setCaretPosition(outputField.getDocument().getLength()); } catch (IOException ex) { LOGGER.error(ex.getLocalizedMessage(), ex); } } } finally { hostBundle.ungetService(ref); } } @Override public DockingPanelParameters getDockingParameters() { return parameters; } @Override public JComponent getComponent() { return this; } private class TextDocumentOutputStream extends OutputStream { private JTextComponent textComponent; private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); // Current text Attribute for insertion, change whith style update private AttributeSet aset; public TextDocumentOutputStream(JTextComponent textComponent, Color textColor) { this.textComponent = textComponent; changeAttribute(textColor); } @Override public void write(int i) throws IOException { buffer.write(i); } @Override public void flush() throws IOException { super.flush(); // Fetch lines in the byte array String messages = buffer.toString(); if (!messages.isEmpty()) { Document doc = textComponent.getDocument(); try { doc.insertString(doc.getLength(), messages, aset); } catch (BadLocationException ex) { LOGGER.error(I18N.tr("Cannot show the log message"), ex); } } buffer.reset(); } private void changeAttribute(Color color) { StyleContext sc = StyleContext.getDefaultStyleContext(); aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, color); } } }
/** * A panel embedding a JTree representing the legend structure (as well as some buttons to manage * it). * * @author Alexis Guéganno * @author Adam Gouge */ public class LegendTree extends JPanel { private static final I18n I18N = I18nFactory.getI18n(LegendTree.class); private JTree tree; private SimpleStyleEditor simpleStyleEditor; private JToolBar toolBar; private JButton jButtonMenuDel; private JButton jButtonMenuDown; private JButton jButtonMenuRename; private JButton jButtonMenuUp; public LegendTree(final SimpleStyleEditor simpleEditor) { simpleStyleEditor = simpleEditor; StyleWrapper style = simpleStyleEditor.getStyleWrapper(); // We create our tree tree = new JTree(); // We don't want to display the root. tree.setRootVisible(true); // We have a custom model to provide... Listeners on the TreeModel // are added by the tree when calling setModel. LegendTreeModel ltm = new LegendTreeModel(tree, style); tree.setModel(ltm); // ..A custom cell editor... LegendTreeCellEditor editor = new LegendTreeCellEditor(); editor.setClickCountToStart(2); tree.setCellEditor(editor); // ...and a custom TreeCellRenderer. LegendCellRenderer lcr = new LegendCellRenderer(tree); tree.setCellRenderer(lcr); // We want to select only one element at a time. tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); selectAndShowFirstLegend(style); // We refresh icons when the selection changes. TreeSelectionListener tsl = EventHandler.create(TreeSelectionListener.class, this, "refreshIcons"); tree.addTreeSelectionListener(tsl); // We refresh the CardLayout of the associated SimpleStyleEditor TreeSelectionListener select = EventHandler.create(TreeSelectionListener.class, simpleStyleEditor, "legendSelected"); tree.addTreeSelectionListener(select); expandAll(tree); // We want an editable tree tree.setEditable(true); initButtons(); this.setLayout(new BorderLayout()); this.add(toolBar, BorderLayout.PAGE_START); JScrollPane scrollPane = new JScrollPane(tree); this.add(scrollPane, BorderLayout.CENTER); refreshIcons(); } /** * Removes the currently selected element from the tree. If it is an inner node, all its children * will be lost. */ public void removeSelectedElement() { TreePath tp = tree.getSelectionPath(); Object select = tp.getLastPathComponent(); LegendTreeModel tm = (LegendTreeModel) tree.getModel(); if (select instanceof ILegendPanel) { RuleWrapper rw = (RuleWrapper) tp.getPath()[tp.getPath().length - 2]; tree.setSelectionPath(null); tm.removeElement(rw, select); // We refresh the legend container simpleStyleEditor.showDialogForCurrentlySelectedLegend(); // We refresh the icons } else if (select instanceof RuleWrapper) { tree.setSelectionPath(null); tm.removeElement(tm.getRoot(), select); simpleStyleEditor.showDialogForCurrentlySelectedLegend(); } refreshIcons(); } /** * Adds an element to the tree. It will open a window to let the user choose which type of element * (legend or rule) it must be. */ public void addElement() { TreePath tp = tree.getSelectionPath(); if (tp == null) { addRule(); } else { Object select = tp.getLastPathComponent(); if (select instanceof StyleWrapper) { addRule(); } else { addLegend(); } } refreshIcons(); } /** Move the currently selected element (if any) up in the model. */ public void moveSelectedElementUp() { TreePath tp = tree.getSelectionPath(); Object select = tp.getLastPathComponent(); if (select instanceof RuleWrapper) { LegendTreeModel tm = (LegendTreeModel) tree.getModel(); tm.moveElementUp(tm.getRoot(), select); refreshIcons(); } else if (select instanceof ILegendPanel) { RuleWrapper rw = (RuleWrapper) tp.getPath()[tp.getPath().length - 2]; LegendTreeModel tm = (LegendTreeModel) tree.getModel(); tm.moveElementUp(rw, select); refreshIcons(); } } /** Move the currently selected element (if any) down in its structure. */ public void moveSelectedElementDown() { TreePath tp = tree.getSelectionPath(); Object select = tp.getLastPathComponent(); if (select instanceof RuleWrapper) { LegendTreeModel tm = (LegendTreeModel) tree.getModel(); tm.moveElementDown(tm.getRoot(), select); refreshIcons(); } else if (select instanceof ILegendPanel) { RuleWrapper rw = (RuleWrapper) tp.getPath()[tp.getPath().length - 2]; LegendTreeModel tm = (LegendTreeModel) tree.getModel(); tm.moveElementDown(rw, select); refreshIcons(); } } /** * Start editing the name of the currently selected element. * * @param evt The initial event. */ public final void renameElement(ActionEvent evt) { TreePath tp = tree.getSelectionPath(); tree.startEditingAtPath(tp); } /** * Get the currently selected Legend, if any. If we find it, we return it. Otherwise, we return * null. * * @return The currently selected panel, or null if none is selected. */ public ILegendPanel getSelectedLegend() { TreePath tp = tree.getSelectionPath(); if (tp != null) { Object last = tp.getLastPathComponent(); if (last instanceof ILegendPanel) { return (ILegendPanel) last; } } return null; } /** * Gets the {@code ISELegendPanel} that is associated to the currently selected element in the * tree. * * @return The currently selected panel, or null if none is selected. */ public ISELegendPanel getSelectedPanel() { TreePath tp = tree.getSelectionPath(); if (tp != null) { Object last = tp.getLastPathComponent(); if (last instanceof ILegendPanel) { return (ILegendPanel) last; } else if (last instanceof RuleWrapper) { return ((RuleWrapper) last).getPanel(); } else if (last instanceof StyleWrapper) { return ((StyleWrapper) last).getPanel(); } } return null; } /** Refreshes the state of the icons contained in the toolbar of this panel. */ public final void refreshIcons() { // We must retrieve the index of the currently selected item in its // parent to decide if we display the buttons or not. TreePath tp = tree.getSelectionPath(); if (tp == null) { jButtonMenuDel.setEnabled(false); jButtonMenuRename.setEnabled(false); jButtonMenuDown.setEnabled(false); jButtonMenuUp.setEnabled(false); } else { jButtonMenuRename.setEnabled(true); Object last = tp.getLastPathComponent(); int index = -1; int max = -1; if (last instanceof StyleWrapper) { max = 0; index = 0; } else if (last instanceof RuleWrapper) { StyleWrapper sw = simpleStyleEditor.getStyleWrapper(); index = sw.indexOf((RuleWrapper) last); max = sw.getSize() - 1; } else if (last instanceof ILegendPanel) { RuleWrapper rw = getSelectedRule(); index = rw.indexOf((ILegendPanel) last); max = rw.getSize() - 1; } if (index == 0) { jButtonMenuUp.setEnabled(false); } else { jButtonMenuUp.setEnabled(true); } if (index < max) { jButtonMenuDown.setEnabled(true); } else { jButtonMenuDown.setEnabled(false); } if (max < 1) { jButtonMenuDel.setEnabled(false); } else { jButtonMenuDel.setEnabled(true); } } } /** * Tests if we have a legend in our tree. * * @return */ public boolean hasLegend() { LegendTreeModel ltm = (LegendTreeModel) tree.getModel(); return ltm.hasLegend(); } void refresh() { refreshIcons(); refreshModel(); } /** Initialize all the buttons that can be used to manage the tree content. */ private void initButtons() { toolBar = new JToolBar(); toolBar.setFloatable(false); jButtonMenuUp = new JButton(); jButtonMenuUp.setIcon(OrbisGISIcon.getIcon("go-up")); jButtonMenuUp.setToolTipText(I18N.tr("Up")); ActionListener alu = EventHandler.create(ActionListener.class, this, "moveSelectedElementUp"); jButtonMenuUp.addActionListener(alu); toolBar.add(jButtonMenuUp); jButtonMenuDown = new JButton(); jButtonMenuDown.setIcon(OrbisGISIcon.getIcon("go-down")); jButtonMenuDown.setToolTipText(I18N.tr("Down")); ActionListener ald = EventHandler.create(ActionListener.class, this, "moveSelectedElementDown"); jButtonMenuDown.addActionListener(ald); toolBar.add(jButtonMenuDown); JButton jButtonMenuAdd = new JButton(); jButtonMenuAdd.setIcon(OrbisGISIcon.getIcon("picture_add")); jButtonMenuAdd.setToolTipText(I18N.tr("Add")); ActionListener aladd = EventHandler.create(ActionListener.class, this, "addElement"); jButtonMenuAdd.addActionListener(aladd); jButtonMenuAdd.setFocusPainted(false); toolBar.add(jButtonMenuAdd); jButtonMenuDel = new JButton(); jButtonMenuDel.setIcon(OrbisGISIcon.getIcon("picture_delete")); jButtonMenuDel.setToolTipText(I18N.tr("Delete")); ActionListener alrem = EventHandler.create(ActionListener.class, this, "removeSelectedElement"); jButtonMenuDel.addActionListener(alrem); toolBar.add(jButtonMenuDel); jButtonMenuRename = new JButton(); jButtonMenuRename.setIcon(OrbisGISIcon.getIcon("picture_edit")); jButtonMenuRename.setToolTipText(I18N.tr("Rename")); jButtonMenuRename.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { renameElement(evt); } }); toolBar.add(jButtonMenuRename); } /** * Add a legend to the tree, in the currently selected RuleWrapper, after the currently selected * Legend (if any in both case). A RuleWrapper will be added in the case there is none. */ private void addLegend() { LegendUIChooser legendPicker = new LegendUIChooser(simpleStyleEditor); if (UIFactory.showDialog(legendPicker)) { // Recover the panel that was selected when the user clicked OK. ILegendPanel ilp = legendPicker.getSelectedPanel(); // Get the currently selected RuleWrapper, or the last one in this // style if none is currently selected. RuleWrapper currentrw = getSelectedRule(); StyleWrapper sw = simpleStyleEditor.getStyleWrapper(); if (currentrw == null) { if (sw.getSize() == 0) { addRule(); } currentrw = sw.getRuleWrapper(sw.getSize() - 1); } // Set the Legend's name. Legend legend = ilp.getLegend(); legend .getSymbolizer() .setName(getUniqueName(legend.getLegendTypeName(), currentrw.getRule(), 0)); // Add the panel to the LegendTree. ((LegendTreeModel) tree.getModel()).addElement(currentrw, ilp, getSelectedLegend()); // Automatically select the newly added legend in the tree. TreePath selectionPath = tree.getSelectionPath(); TreePath parent; if (selectionPath.getLastPathComponent() instanceof RuleWrapper) { parent = selectionPath; } else { parent = selectionPath.getParentPath(); } tree.setSelectionPath(parent.pathByAddingChild(ilp)); // Notify the SimpleStyleEditor that a Legend has been added. simpleStyleEditor.legendAdded(ilp); } } /** * Get a name for a Symbolizer that is not already contained in the rule. * * @param n The base name * @param r the rule where we search * @param i An int we'll try to had to reach unicity * @return The unique name. */ private String getUniqueName(String n, Rule r, int i) { int a = i < 0 ? 0 : i; String ret = n; if (a > 0) { ret = n + " " + a; } boolean contained = false; List<Symbolizer> symbolizerList = r.getCompositeSymbolizer().getSymbolizerList(); for (int p = 0; p < symbolizerList.size() && !contained; p++) { Symbolizer s = symbolizerList.get(p); if (s.getName().equals(ret)) { contained = true; } } if (!contained) { return ret; } else { return getUniqueName(n, r, a + 1); } } private void addRule() { // We must add it just after the currently selected Rule. // Let's find which one it is. If there is none, we add it at the // end of the list. MultiInputPanel mip = new MultiInputPanel(I18N.tr("Choose a name for your rule")); mip.addInput("RuleName", I18N.tr("Name of the Rule : "), new TextBoxType(10)); mip.addValidation( new MIPValidation() { @Override public String validate(MultiInputPanel mid) { String ruleName = mid.getInput("RuleName"); return ruleName.isEmpty() ? I18N.tr("Rule name cannot be null or empty.") : null; } }); if (UIFactory.showDialog(mip)) { String s = mip.getInput("RuleName"); LegendTreeModel tm = (LegendTreeModel) tree.getModel(); // We need to link our new RuleWrapper with the layer we are editing. Rule temp = new Rule(simpleStyleEditor.getStyleWrapper().getStyle().getLayer()); temp.setName(s); Legend leg = LegendFactory.getLegend(temp.getCompositeSymbolizer().getSymbolizerList().get(0)); // Initialize a panel for this legend. ILegendPanel ilp = ILegendPanelFactory.getILegendPanel(simpleStyleEditor, leg); List<ILegendPanel> list = new ArrayList<ILegendPanel>(); list.add(ilp); RuleWrapper nrw = new RuleWrapper(simpleStyleEditor, temp, list); tm.addElement(tm.getRoot(), nrw, getSelectedRule()); simpleStyleEditor.legendAdded(nrw.getPanel()); } } /** * Get the currently selected Rule, if any. If we find it, we return it. Otherwise, we return * null. */ private RuleWrapper getSelectedRule() { TreePath tp = tree.getSelectionPath(); if (tp != null) { Object[] path = tp.getPath(); for (int i = path.length - 1; i >= 0; i--) { if (path[i] instanceof RuleWrapper) { return (RuleWrapper) path[i]; } } } return null; } private void refreshModel() { ((LegendTreeModel) tree.getModel()).refresh(); } /** * Selects the first legend attached to the given style in this {@link LegendTree} and displays it * in the Simple Style Editor's card layout. * * @param style Style */ private void selectAndShowFirstLegend(StyleWrapper style) { RuleWrapper firstRW = style.getRuleWrapper(0); ILegendPanel firstPanel = firstRW.getLegend(0); TreePath tp = new TreePath(style).pathByAddingChild(firstRW).pathByAddingChild(firstPanel); tree.setSelectionPath(tp); simpleStyleEditor.showDialogForLegend(firstPanel); } /** * A TreeCellRenderer dedicated to our tree. Paints text in red if the cell is selected, in black * otherwise. */ private static class LegendCellRenderer extends TreeLaFRenderer { public LegendCellRenderer(JTree tree) { super(tree); } @Override public Component getTreeCellRendererComponent( JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { Component comp = lookAndFeelRenderer.getTreeCellRendererComponent( tree, value, selected, expanded, leaf, row, hasFocus); if (comp instanceof JLabel) { JLabel lab = (JLabel) comp; if (value instanceof StyleWrapper) { return getComponent((StyleWrapper) value, lab); } else if (value instanceof RuleWrapper) { return getComponent((RuleWrapper) value, lab); } else if (value instanceof ILegendPanel) { return getComponent((ILegendPanel) value, lab); } else { lab.setText("root"); } } return comp; } private Component getComponent(ILegendPanel legend, JLabel lab) { lab.setText(legend.getLegend().getName()); return lab; } private Component getComponent(RuleWrapper rw, JLabel lab) { String s = rw.getRule().getName(); if (s == null || s.isEmpty()) { s = "Unknown"; } lab.setText(s); return lab; } private Component getComponent(StyleWrapper sw, JLabel lab) { String s = sw.getStyle().getName(); if (s == null || s.isEmpty()) { s = "Unknown"; } lab.setText(s); return lab; } } /** The name of the selected element changed ! */ public void selectedNameChanged() { LegendTreeModel model = (LegendTreeModel) tree.getModel(); model.refresh(); } /** * Expand configuration tree * * @param tree The tree we want to process. */ private void expandAll(JTree tree) { for (int row = 0; row < tree.getRowCount(); row++) { tree.expandRow(row); } } }
/** Class that contains the status of the map view. */ public final class OwsMapContext extends BeanMapContext { private static final I18n I18N = I18nFactory.getI18n(OwsMapContext.class, Locale.getDefault(), I18nFactory.FALLBACK); private static final Logger LOGGER = LoggerFactory.getLogger(OwsMapContext.class); private ArrayList<MapContextListener> listeners = new ArrayList<MapContextListener>(); private OpenerListener openerListener; private boolean open = false; private OWSContextType jaxbMapContext = null; // Persistent form of the MapContext private long idTime; private DataManager dataManager; /** Default constructor */ public OwsMapContext(DataManager dataManager) { openerListener = new OpenerListener(); setRootLayer(createLayerCollection("root")); // Create an empty map context jaxbMapContext = createJaxbMapContext(); idTime = System.currentTimeMillis(); this.dataManager = dataManager; } @Override public DataManager getDataManager() { return dataManager; } @Override public ILayer createLayer(String layerName, String tableRef) throws LayerException { try { try (Connection connection = dataManager.getDataSource().getConnection()) { List<String> geoFields = SFSUtilities.getGeometryFields(connection, TableLocation.parse(tableRef)); if (!geoFields.isEmpty()) { return new Layer(layerName, tableRef, dataManager); } else { throw new LayerException(I18N.tr("The source contains no spatial info")); } } } catch (SQLException ex) { throw new LayerException("Cannot retrieve spatial metadata", ex); } } @Override public ILayer createLayer(String tableRef) throws LayerException { return createLayer(TableLocation.parse(tableRef).getTable(), tableRef); } @Override public ILayer createLayer(String layerName, URI source) throws LayerException { return new Layer(layerName, source, dataManager); } @Override public ILayer createLayer(URI source) throws LayerException { if (!source.isAbsolute()) { // If URI is not absolute ex URI.create("../folder/myfile.shp"), then create a canonical URI try { source = new File(location != null ? new File(location) : new File("./"), source.toString()) .getCanonicalFile() .toURI(); } catch (IOException ex) { throw new LayerException(ex); } } String layerName; try { layerName = FileUtils.getNameFromURI(source); } catch (UnsupportedOperationException ex) { try { layerName = dataManager.findUniqueTableName(I18N.tr("Layer")); } catch (SQLException ex2) { throw new LayerException(ex2); } } return createLayer(layerName, source); } @Override public ILayer createLayerCollection(String layerName) { return new LayerCollection(layerName); } private void setRootLayer(ILayer newRoot) { if (layerModel != null) { layerModel.removeLayerListenerRecursively(openerListener); } super.setLayerModel(newRoot); layerModel.addLayerListenerRecursively(openerListener); } @Override protected void setLayerModel(ILayer newRoot) { setRootLayer(newRoot); } @Override public void addMapContextListener(MapContextListener listener) { listeners.add(listener); } @Override public void removeMapContextListener(MapContextListener listener) { listeners.remove(listener); } @Override public ILayer getLayerModel() { checkIsOpen(); return super.getLayerModel(); } @Override public long getIdTime() { return idTime; } @Override public ILayer[] getLayers() { checkIsOpen(); return getLayerModel().getLayersRecursively(); } @Override public Style[] getSelectedStyles() { checkIsOpen(); return super.getSelectedStyles(); } @Override public ILayer[] getSelectedLayers() { checkIsOpen(); return super.getSelectedLayers(); } @Override public void setSelectedStyles(Style[] selectedStyles) { checkIsOpen(); super.setSelectedStyles(selectedStyles); // DEPRECATED LISTENERS for (MapContextListener listener : listeners) { listener.layerSelectionChanged(this); } } @Override public void setSelectedLayers(ILayer[] selectedLayers) { checkIsOpen(); ArrayList<ILayer> filtered = new ArrayList<ILayer>(); for (ILayer layer : selectedLayers) { if (layerModel.getLayerByName(layer.getName()) != null) { filtered.add(layer); } } super.setSelectedLayers(filtered.toArray(new ILayer[filtered.size()])); // DEPRECATED LISTENERS for (MapContextListener listener : listeners) { listener.layerSelectionChanged(this); } } private final class OpenerListener extends LayerListenerAdapter { @Override public void layerAdded(LayerCollectionEvent e) { if (isOpen()) { for (final ILayer layer : e.getAffected()) { try { layer.open(); layer.addLayerListenerRecursively(openerListener); // checking & possibly setting SRID // checkSRID(layer); } catch (LayerException ex) { LOGGER.error(I18N.tr("Cannot open layer : {0} ", layer.getName()), ex); try { layer.getParent().remove(layer); } catch (LayerException e1) { LOGGER.error(I18N.tr("Cannot remove the layer {0}", layer.getName()), ex); } } } } } @Override public void layerRemoved(LayerCollectionEvent e) { HashSet<ILayer> newSelection = new HashSet<ILayer>(); newSelection.addAll(Arrays.asList(selectedLayers)); ILayer[] affected = e.getAffected(); for (final ILayer layer : affected) { // Check active if (activeLayer == layer) { setActiveLayer(null); } // Check selection newSelection.remove(layer); layer.removeLayerListenerRecursively(openerListener); if (isOpen()) { try { layer.close(); } catch (LayerException e1) { LOGGER.warn(I18N.tr("Cannot close layer {0}", layer.getName()), e1); } } } setSelectedLayers(newSelection.toArray(new ILayer[newSelection.size()])); // checkIfHasToResetSRID(); } } @Override public boolean isLayerModelSpatial() { ILayer[] layers = getLayers(); for (ILayer l : layers) { if (!l.acceptsChilds()) { return true; } } return false; } /** * Implementation of public draw method * * @param mt Contain the extent and the image to draw on * @param pm Object to report process and check the cancelled condition * @param layer Draw recursively this layer * @throws IllegalStateException If the map is closed */ private void drawImpl(MapTransform mt, ProgressMonitor pm, ILayer layer) throws IllegalStateException { checkIsOpen(); Renderer renderer = new ImageRenderer(); renderer.draw(mt, layer, pm); } @Override public void draw(MapTransform mt, ProgressMonitor pm, ILayer layer) { // Layer must be from this layer model if (!isLayerFromThisLayerModel(layer)) { throw new IllegalStateException( I18N.tr("Layer provided for drawing is not from the map context layer model.")); } drawImpl(mt, pm, layer); } @Override public void draw(MapTransform mt, ProgressMonitor pm) { drawImpl(mt, pm, getLayerModel()); } /** * Search recursively for the specified layer in the layer model * * @param layer Searched layer * @return True if the layer is in the map context layer model */ private boolean isLayerFromThisLayerModel(ILayer layer) { ILayer[] allLayers = getLayerModel().getLayersRecursively(); return Arrays.asList(allLayers).contains(layer); } private void checkIsOpen() { if (!isOpen()) { throw new IllegalStateException(I18N.tr("The map is not open")); // $NON-NLS-1$ } } @Override public ILayer getActiveLayer() { checkIsOpen(); return activeLayer; } @Override public void setActiveLayer(ILayer activeLayer) { checkIsOpen(); ILayer lastActive = this.activeLayer; this.activeLayer = activeLayer; propertyChangeSupport.firePropertyChange(PROP_ACTIVELAYER, lastActive, activeLayer); } private OWSContextType createJaxbMapContext() { // Create jaxbcontext data ObjectFactory ows_context_factory = new ObjectFactory(); net.opengis.ows._2.ObjectFactory ows_factory = new net.opengis.ows._2.ObjectFactory(); OWSContextType mapContextSerialisation = ows_context_factory.createOWSContextType(); // GeneralType mapContextSerialisation.setGeneral(ows_context_factory.createGeneralType()); // GeneralType:Bounding Box if (boundingBox != null) { BoundingBoxType bbox = ows_factory.createBoundingBoxType(); bbox.getLowerCorner().add(boundingBox.getMinX()); bbox.getLowerCorner().add(boundingBox.getMinY()); bbox.getUpperCorner().add(boundingBox.getMaxX()); bbox.getUpperCorner().add(boundingBox.getMaxY()); mapContextSerialisation.getGeneral().setBoundingBox(ows_factory.createBoundingBox(bbox)); } // GeneralType:Title Map<Locale, String> titles = description.getTitles(); if (!titles.isEmpty()) { // Take the first one for (Entry<Locale, String> entry : titles.entrySet()) { LanguageStringType title = ows_factory.createLanguageStringType(); title.setLang(LocalizedText.toLanguageTag(entry.getKey())); title.setValue(entry.getValue()); mapContextSerialisation.getGeneral().setTitle(title); break; // Ows-context does not support multi-lingual } } // GeneralType:Abstract Map<Locale, String> abstracts = description.getAbstractTexts(); if (!abstracts.isEmpty()) { // Take the first one for (Entry<Locale, String> entry : abstracts.entrySet()) { LanguageStringType mapAbstract = ows_factory.createLanguageStringType(); mapAbstract.setLang(LocalizedText.toLanguageTag(entry.getKey())); mapAbstract.setValue(entry.getValue()); mapContextSerialisation.getGeneral().setAbstract(mapAbstract); break; // Ows-context does not support multi-lingual } } // ResourceList ResourceListType rs = ows_context_factory.createResourceListType(); mapContextSerialisation.setResourceList(rs); // LayerList if (layerModel != null) { List<LayerType> rootLayerList = rs.getLayer(); ILayer[] rootLayers = layerModel.getChildren(); for (ILayer layer : rootLayers) { if (layer.isSerializable()) { rootLayerList.add(createJAXBFromLayer(layer, this)); } } } return mapContextSerialisation; } private static LayerType createJAXBFromLayer(ILayer layer, MapContext mapContext) { ObjectFactory ows_context_factory = new ObjectFactory(); LayerType layerType = ows_context_factory.createLayerType(); Description description = layer.getDescription(); description.initJAXBType(layerType); layerType.setHidden(!layer.isVisible()); ILayer[] childrens = layer.getChildren(); for (ILayer child : childrens) { if (child.isSerializable()) { layerType.getLayer().add(createJAXBFromLayer(child, mapContext)); } } // If not a Layer Collection if (!(layer instanceof LayerCollection) && layer.getStyles() != null) { StyleListType slt = ows_context_factory.createStyleListType(); layerType.setStyleList(slt); for (Style style : layer.getStyles()) { StyleType st = ows_context_factory.createStyleType(); slt.getStyle().add(st); SLDType sltType = ows_context_factory.createSLDType(); st.setSLD(sltType); sltType.setAbstractStyle(style.getJAXBElement()); } } // Serialisation of dataSource as a DataUrl string // Create jaxb instances URLType dataURL = ows_context_factory.createURLType(); if (!(layer instanceof LayerCollection)) { OnlineResourceType resource = ows_context_factory.createOnlineResourceType(); dataURL.setOnlineResource(resource); String resourceSerialisation = ""; URI srcUri = layer.getDataUri(); if (srcUri != null) { // If file, use MapContext relative path if (srcUri.getScheme().equalsIgnoreCase("file") && mapContext.getLocation() != null) { srcUri = URIUtility.relativize(mapContext.getLocation(), srcUri); } resourceSerialisation = srcUri.toString(); } resource.setHref(resourceSerialisation); if (resource.isSetHref()) { layerType.setDataURL(dataURL); } } return layerType; } @Override public void read(InputStream in) throws IllegalArgumentException { try { Unmarshaller unMarsh = org.orbisgis.coremap.map.JaxbContainer.JAXBCONTEXT.createUnmarshaller(); JAXBElement<OWSContextType> importedOwsContextType = (JAXBElement<OWSContextType>) unMarsh.unmarshal(in); setJAXBObject(importedOwsContextType.getValue()); } catch (JAXBException ex) { throw new IllegalArgumentException(I18N.tr("Unable to read the provided map context"), ex); } } @Override public void write(OutputStream out) { ObjectFactory owsFactory = new ObjectFactory(); try { JAXBElement<OWSContextType> exportedOwsContextType = owsFactory.createOWSContext(getJAXBObject()); Marshaller marshaller = org.orbisgis.coremap.map.JaxbContainer.JAXBCONTEXT.createMarshaller(); marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE); marshaller.marshal(exportedOwsContextType, out); } catch (JAXBException ex) { throw new IllegalArgumentException( I18N.tr("Error raised while exporting the map context"), ex); } } /** @return The internal serialisation objects of the Map Context */ public OWSContextType getJAXBObject() { if (jaxbMapContext == null) { return createJaxbMapContext(); } return jaxbMapContext; } private void setJAXBObject(OWSContextType jaxbObject) { if (isOpen()) { throw new IllegalStateException( I18N.tr("The map must be closed to invoke this method")); // $NON-NLS-1$ } this.jaxbMapContext = (OWSContextType) jaxbObject; } @Override public void close(ProgressMonitor pm) { checkIsOpen(); // Backup Consistent data jaxbMapContext = getJAXBObject(); // Close the layers if (pm == null) { pm = new NullProgressMonitor(); } ILayer[] layers = layerModel.getLayersRecursively(); for (int i = 0; i < layers.length; i++) { pm.progressTo(i * 100 / layers.length); if (!layers[i].acceptsChilds()) { try { layers[i].close(); } catch (LayerException e) { LOGGER.error(I18N.tr("Cannot close layer {0}", layers[i].getName())); } } } layerModel.removeLayerListenerRecursively(openerListener); this.open = false; } /** * Recursive function to parse a layer tree * * @param lt * @param parentLayer */ private void parseJaxbLayer(LayerType lt, ILayer parentLayer) throws LayerException { // Test if lt is a group if (!lt.getLayer().isEmpty() || (lt.getDataURL() == null)) { // it will create a LayerCollection parseJaxbLayerCollection(lt, parentLayer); } else { // it corresponding to a leaf layer // We need to read the data declaration and create the layer URLType dataUrl = lt.getDataURL(); if (dataUrl != null) { OnlineResourceType resType = dataUrl.getOnlineResource(); try { URI layerURI = new URI(resType.getHref()); // The resource is given as relative to MapContext location if (!layerURI.isAbsolute() && getLocation() != null) { try { // Resolve the relative resource ex: new Uri("myFile.shp") layerURI = getLocation().resolve(layerURI); } catch (IllegalArgumentException ex) { LOGGER.warn( "Error while trying to find an absolute path for an external resource", ex); } } // Get table name ILayer leafLayer = createLayer(layerURI); leafLayer.setDescription(new Description(lt)); leafLayer.setVisible(!lt.isHidden()); // Parse styles if (lt.isSetStyleList()) { for (StyleType st : lt.getStyleList().getStyle()) { if (st.isSetSLD()) { if (st.getSLD().isSetAbstractStyle()) { leafLayer.addStyle( new Style( (JAXBElement<net.opengis.se._2_0.core.StyleType>) st.getSLD().getAbstractStyle(), leafLayer)); } } } } parentLayer.addLayer(leafLayer); } catch (URISyntaxException ex) { throw new LayerException( I18N.tr("Unable to parse the href URI {0}.", resType.getHref()), ex); } catch (InvalidStyle ex) { throw new LayerException( I18N.tr("Unable to load the description of the layer {0}", lt.getTitle().toString()), ex); } } } } /** * Recursive function to parse a layer tree * * @param lt * @param parentLayer */ private void parseJaxbLayerCollection(LayerType lt, ILayer parentLayer) throws LayerException { LayerCollection layerCollection = new LayerCollection(lt); for (LayerType ltc : lt.getLayer()) { try { parseJaxbLayer(ltc, layerCollection); } catch (LayerException ex) { // The layer is not created if a layer exception is thrown // Create a warning, because the MapContext is loaded LOGGER.warn(I18N.tr("The layer has not been imported"), ex); } } parentLayer.addLayer(layerCollection); } private void loadOwsContext() throws LayerException { if (jaxbMapContext != null) { // Load bounding box if (jaxbMapContext.getGeneral().getBoundingBox() != null) { List<Double> lowerCorner = jaxbMapContext.getGeneral().getBoundingBox().getValue().getLowerCorner(); List<Double> upperCorner = jaxbMapContext.getGeneral().getBoundingBox().getValue().getUpperCorner(); if (lowerCorner.size() >= 2 && upperCorner.size() >= 2) { setBoundingBox( new Envelope( lowerCorner.get(0), upperCorner.get(0), lowerCorner.get(1), upperCorner.get(1))); } } // Load title Description nextDescription = new Description(); if (jaxbMapContext.getGeneral().getTitle() != null) { LanguageStringType title = jaxbMapContext.getGeneral().getTitle(); Locale locale; if (title.getLang() != null) { locale = LocalizedText.forLanguageTag(title.getLang()); } else { locale = Locale.getDefault(); } nextDescription.addTitle(locale, title.getValue()); } // Load abstract if (jaxbMapContext.getGeneral().getAbstract() != null) { LanguageStringType mapAbstract = jaxbMapContext.getGeneral().getAbstract(); Locale locale; if (mapAbstract.getLang() != null) { locale = LocalizedText.forLanguageTag(mapAbstract.getLang()); } else { locale = Locale.getDefault(); } nextDescription.addAbstract(locale, mapAbstract.getValue()); } setDescription(nextDescription); // Collect DataSource URI already loaded // Load layers and DataSource // Root layer correspond to ResourceList setRootLayer(createLayerCollection("root")); for (LayerType lt : jaxbMapContext.getResourceList().getLayer()) { try { parseJaxbLayer(lt, getLayerModel()); } catch (LayerException ex) { // The layer is not created if a layer exception is thrown LOGGER.error(I18N.tr("The layer has not been imported"), ex); } } } } @Override public void open(ProgressMonitor pm) throws LayerException { if (isOpen()) { throw new IllegalStateException(I18N.tr("The map is already open")); } open = true; this.activeLayer = null; // Read the specified jaxbMapContext setSelectedLayers(new ILayer[0]); setSelectedStyles(new Style[0]); loadOwsContext(); jaxbMapContext = null; } @Override public boolean isOpen() { return open; } /* * A mapcontext must have only one {@link CoordinateReferenceSystem} By * default the crs is set to null. */ /* * public CoordinateReferenceSystem getCoordinateReferenceSystem() { * return crs; } * * /** Set a {@link CoordinateReferenceSystem} to the mapContext * * @param crs */ /* * public void setCoordinateReferenceSystem(CoordinateReferenceSystem * crs) { this.crs = crs; } */ }
/** The core manage the view of the application. This is the main UIContext */ public class Core { private static final I18n I18N = I18nFactory.getI18n(Core.class); private static final Logger LOGGER = Logger.getLogger("gui.popup." + Core.class); /** Buffer to copy resource to file */ private static final int BUFFER_LENGTH = 4096; ///////////////////// // view package private EditorManagerImpl editors; /*!< Management of editors */ private MainFrame mainFrame; /*!< The main window */ private Catalog geoCatalog = null; /*!< The GeoCatalog frame */ private ViewWorkspace viewWorkspace; private OutputManager loggerCollection; /*!< Loggings panels */ public static final Dimension MAIN_VIEW_SIZE = new Dimension(800, 600); /*!< Bounds of mainView, x,y and width height*/ private DockingManager dockManager = null; /*!< The DockStation manager */ ///////////////////// // base package : private MainContext mainContext; /*!< The larger surrounding part of OrbisGis base */ //////////////////// // Plugins private PluginHost pluginFramework; private DockingPanelTracker singleFrameTracker; private EditorFactoryTracker editorFactoryTracker; private EditorPanelTracker editorTracker; private MenuItemServiceTracker<MainWindow, ToolBarAction> toolBarTracker; /** * Core constructor, init Model instances * * @param debugMode Show additional information for debugging purposes * @note Call startup() to init Swing */ public Core(CoreWorkspaceImpl coreWorkspace, boolean debugMode, LoadingFrame splashScreen) throws InvocationTargetException, InterruptedException { ProgressMonitor parentProgress = splashScreen.getProgressMonitor(); ProgressMonitor progressInfo = parentProgress.startTask(I18N.tr("Loading Workspace.."), 100); MainContext.initConsoleLogger(debugMode); // Declare empty main frame mainFrame = new MainFrame(); // Set the main frame position and size mainFrame.setSize(MAIN_VIEW_SIZE); // Try to set the frame at the center of the default screen try { GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); Rectangle screenBounds = device.getDefaultConfiguration().getBounds(); mainFrame.setLocation( screenBounds.x + screenBounds.width / 2 - MAIN_VIEW_SIZE.width / 2, screenBounds.y + screenBounds.height / 2 - MAIN_VIEW_SIZE.height / 2); } catch (Throwable ex) { LOGGER.error(ex.getLocalizedMessage(), ex); } UIFactory.setMainFrame(mainFrame); initMainContext(debugMode, coreWorkspace, splashScreen); progressInfo.progressTo(10); this.viewWorkspace = new ViewWorkspace(this.mainContext.getCoreWorkspace()); Services.registerService( ViewWorkspace.class, I18N.tr("Contains view folders path"), viewWorkspace); progressInfo.setTaskName(I18N.tr("Register GUI Sql functions..")); addSQLFunctions(); progressInfo.progressTo(11); // Load plugin host progressInfo.setTaskName(I18N.tr("Load the plugin framework..")); startPluginHost(); progressInfo.progressTo(18); progressInfo.setTaskName(I18N.tr("Connecting to the database..")); // Init database try { mainContext.initDataBase( coreWorkspace.getDataBaseUser(), coreWorkspace.getDataBasePassword()); } catch (SQLException ex) { throw new RuntimeException(ex.getLocalizedMessage(), ex); } initSIF(); progressInfo.progressTo(20); } private void startPluginHost() { try { mainContext.startBundleHost(BundleFromResources.SPECIFIC_BEHAVIOUR_BUNDLES); pluginFramework = mainContext.getPluginHost(); pluginFramework .getHostBundleContext() .registerService(org.orbisgis.viewapi.workspace.ViewWorkspace.class, viewWorkspace, null); } catch (Exception ex) { LOGGER.error(I18N.tr("Loading of plugins is aborted"), ex); } } /** Find the workspace folder or addDockingPanel a dialog to select one */ private void initMainContext( boolean debugMode, CoreWorkspaceImpl coreWorkspace, LoadingFrame splashScreen) throws InterruptedException, InvocationTargetException, RuntimeException { String workspaceFolder = coreWorkspace.getWorkspaceFolder(); if (workspaceFolder == null) { File defaultWorkspace = coreWorkspace.readDefaultWorkspacePath(); if (defaultWorkspace == null || !ViewWorkspace.isWorkspaceValid(defaultWorkspace)) { try { PromptUserForSelectingWorkspace dial = new PromptUserForSelectingWorkspace(coreWorkspace, splashScreen); SwingUtilities.invokeAndWait(dial); if (!dial.isOk()) { throw new InterruptedException("Canceled by user."); } } catch (InvocationTargetException ex) { mainFrame.dispose(); throw ex; } } else { coreWorkspace.setWorkspaceFolder(defaultWorkspace.getAbsolutePath()); } } this.mainContext = new MainContext(debugMode, coreWorkspace, true); } /** Add new menu to the OrbisGIS core */ private void addCoreMenu() { DefaultAction def = new DefaultAction( MainFrameAction.MENU_SAVE, I18N.tr("&Save"), OrbisGISIcon.getIcon("save"), EventHandler.create(ActionListener.class, this, "onMenuSaveApplication")); def.setParent(MainFrameAction.MENU_FILE).setBefore(MainFrameAction.MENU_EXIT); mainFrame.addMenu(def); def.setToolTipText(I18N.tr("Save the workspace")); JButton saveBt = new CustomButton(def); saveBt.setHideActionText(true); mainFrame.addToolBarComponent(saveBt, "align left"); } private static class PromptUserForSelectingWorkspace implements Runnable { private CoreWorkspaceImpl coreWorkspace; private JFrame mainFrame; /** User do not cancel workspace selection */ private boolean ok = false; public PromptUserForSelectingWorkspace(CoreWorkspaceImpl coreWorkspace, JFrame mainFrame) { this.coreWorkspace = coreWorkspace; this.mainFrame = mainFrame; } /** * Does the user accept a new workspace folder. * * @return False if action is canceled by user */ private boolean isOk() { return ok; } @Override public void run() { // Ask the user to select a workspace folder if (WorkspaceSelectionDialog.showWorkspaceFolderSelection(mainFrame, coreWorkspace)) { ok = true; } } } /** * For UnitTest purpose * * @return The Catalog instance */ public Catalog getGeoCatalog() { return geoCatalog; } /** Init the SIF ui factory */ private void initSIF() { UIFactory.setDefaultImageIcon(OrbisGISIcon.getIcon("orbisgis")); // Load SIF properties try { UIFactory.loadState(new File(viewWorkspace.getSIFPath())); } catch (IOException ex) { LOGGER.error(I18N.tr("Error while loading dialogs informations."), ex); } } /** @return Instance of main context */ public MainContext getMainContext() { return mainContext; } /** * Instance of main frame, null if startup() has not be called. * * @return MainFrame instance */ public MainFrame getMainFrame() { return mainFrame; } /** Create the Instance of the main frame */ private void makeMainFrame() { mainFrame.init(pluginFramework.getHostBundleContext()); // When the user ask to close OrbisGis it call // the shutdown method here, // Link the Swing Events with the MainFrame event // Thanks to EventHandler we don't have to build a listener class mainFrame.addWindowListener( EventHandler.create( WindowListener.class, // The listener class this, // The event target object "onMainWindowClosing", // The event target method to call null, // the event parameter to pass(none) "windowClosing")); // The listener method to use } /** Create the logging panels All,Info,Warning,Error */ private void makeLoggingPanels() { loggerCollection = new OutputManager(mainContext.isDebugMode()); // Show Panel dockManager.addDockingPanel(loggerCollection.getPanel()); } /** Create the GeoCatalog view */ private void makeGeoCatalogPanel() { // The geo-catalog view content is read from the SourceContext geoCatalog = new Catalog(mainContext.getDataManager(), editors); // Catalog extensions geoCatalog.registeTrackers(pluginFramework.getHostBundleContext()); // Add the view as a new Docking Panel dockManager.addDockingPanel(geoCatalog); } /** Load the built-ins editors factories */ private void loadEditorFactories() { TableEditorFactory tableEditorFactory = new TableEditorFactory(); tableEditorFactory.setDataManager(mainContext.getDataManager()); editors.addEditorFactory(tableEditorFactory); } /** The user want to close the main window Then the application has to be closed */ public void onMainWindowClosing() { this.shutdown(true); } /** * Create the central place for editor factories. This manager will retrieve panel editors and use * the docking manager to addDockingPanel them * * @param dm Instance of docking manager */ private void makeEditorManager(DockingManager dm) { editors = new EditorManagerImpl(dm); Services.registerService( org.orbisgis.viewapi.edition.EditorManager.class, I18N.tr("Use this instance to open an editable element (map,data source..)"), editors); pluginFramework .getHostBundleContext() .registerService(org.orbisgis.viewapi.edition.EditorManager.class, editors, null); editorFactoryTracker = new EditorFactoryTracker(pluginFramework.getHostBundleContext(), editors); editorFactoryTracker.open(); editorTracker = new EditorPanelTracker(pluginFramework.getHostBundleContext(), editors); editorTracker.open(); } /** * Starts the application. This method creates the {@link MainFrame}, and manage the Look And Feel * declarations */ public void startup(ProgressMonitor progress) throws Exception { // Show the application when Swing will be ready try { initialize(progress); } catch (Exception ex) { mainFrame.dispose(); throw ex; } SwingUtilities.invokeLater(new ShowSwingApplication(progress, mainFrame)); } /** * For unit test purpose, expose the plugin framework * * @return */ public PluginHost getPluginFramework() { return pluginFramework; } private void initialize(ProgressMonitor parentProgress) { ProgressMonitor progress = parentProgress.startTask(I18N.tr("Loading the main window"), 100); makeMainFrame(); progress.endTask(); progress.setTaskName(I18N.tr("Loading docking system and frames")); // Initiate the docking management system DockingManagerImpl dockManagerImpl = new DockingManagerImpl(mainFrame); dockManager = dockManagerImpl; mainFrame.setDockingManager(dockManager); // Initiate the docking panel tracker singleFrameTracker = new DockingPanelTracker(pluginFramework.getHostBundleContext(), dockManager); singleFrameTracker.open(); toolBarTracker = new MenuItemServiceTracker<MainWindow, ToolBarAction>( pluginFramework.getHostBundleContext(), ToolBarAction.class, dockManagerImpl, mainFrame); toolBarTracker.open(); progress.endTask(); // Load the log panels makeLoggingPanels(); progress.endTask(); // Load the editor factories manager makeEditorManager(dockManager); progress.endTask(); // Load the GeoCatalog makeGeoCatalogPanel(); progress.endTask(); // Load Built-ins Editors loadEditorFactories(); progress.endTask(); progress.setTaskName(I18N.tr("Restore the former layout..")); // Load the docking layout and editors opened in last OrbisGis instance File savedDockingLayout = new File(viewWorkspace.getDockingLayoutPath()); if (!savedDockingLayout.exists()) { // Copy the default docking layout // First OrbisGIS start copyDefaultDockingLayout(savedDockingLayout); } dockManager.setDockingLayoutPersistanceFilePath(viewWorkspace.getDockingLayoutPath()); progress.endTask(); addCoreMenu(); } /** * Copy the default docking layout to the specified file path. * * @param savedDockingLayout */ private void copyDefaultDockingLayout(File savedDockingLayout) { InputStream xmlFileStream = DockingManagerImpl.class.getResourceAsStream("default_docking_layout.xml"); if (xmlFileStream != null) { try { FileOutputStream writer = new FileOutputStream(savedDockingLayout); try { byte[] buffer = new byte[BUFFER_LENGTH]; for (int n; (n = xmlFileStream.read(buffer)) != -1; ) { writer.write(buffer, 0, n); } } finally { writer.close(); } } catch (FileNotFoundException ex) { LOGGER.error(I18N.tr("Unable to save the docking layout."), ex); } catch (IOException ex) { LOGGER.error(I18N.tr("Unable to save the docking layout."), ex); } finally { try { xmlFileStream.close(); } catch (IOException ex) { LOGGER.error(I18N.tr("Unable to save the docking layout."), ex); } } } } /** Add SQL functions to interact with OrbisGIS UI */ private void addSQLFunctions() { // mainContext.getDataSourceFactory().getFunctionManager().addFunction(MapContext_AddLayer.class); // mainContext.getDataSourceFactory().getFunctionManager().addFunction(MapContext_BBox.class); // mainContext.getDataSourceFactory().getFunctionManager().addFunction(MapContext_ZoomTo.class); // mainContext.getDataSourceFactory().getFunctionManager().addFunction(MapContext_Share.class); } /** Change the state of the main frame in the swing thread */ private class ShowSwingApplication implements Runnable { private ProgressMonitor progress; private MainFrame mainFrame; public ShowSwingApplication(ProgressMonitor progress, MainFrame mainFrame) { this.progress = progress; this.mainFrame = mainFrame; } /** Change the state of the main frame in the swing thread */ @Override public void run() { try { mainFrame.setVisible(true); } catch (Exception ex) { LOGGER.error(ex.getLocalizedMessage(), ex); dispose(); } finally { progress.setCancelled(true); } } } /** * Return the docking manager. This function is used by Unit Tests. * * @return The Docking Manager */ public DockingManager getDockManager() { return dockManager; } /** Free all resources allocated by this object */ public void dispose() { // Close all running jobs final AppContext appContext = AppContext.getAppContext(); ExecutorService executorService = (ExecutorService) appContext.get(SwingWorker.class); if (executorService != null) { executorService.shutdown(); } // Free UI resources if (editors != null) { editors.dispose(); } if (geoCatalog != null) { geoCatalog.dispose(); } if (mainFrame != null) { mainFrame.dispose(); } if (singleFrameTracker != null) { singleFrameTracker.close(); } if (editorFactoryTracker != null) { editorFactoryTracker.close(); } if (editorTracker != null) { editorTracker.close(); } if (toolBarTracker != null) { toolBarTracker.close(); } dockManager.dispose(); loggerCollection.dispose(); // Free libraries resources mainContext.dispose(); UIFactory.setMainFrame(null); } /** * Save or discard editable element modification. Show a dialog if there is at least one unsaved * editable element. * * @return True if the application must cancel the close shutdown operation */ private boolean isShutdownVetoed() { List<EditableElement> modifiedElements = new ArrayList<EditableElement>(); Collection<EditableElement> editableElement = editors.getEditableElements(); for (EditableElement editable : editableElement) { if (editable.isModified()) { modifiedElements.add(editable); } } if (!modifiedElements.isEmpty()) { SaveDocuments.CHOICE userChoice = SaveDocuments.showModal(mainFrame, modifiedElements); // If the user do not want to save the editable elements // Then cancel the modifications if (userChoice == SaveDocuments.CHOICE.SAVE_NONE) { for (EditableElement element : modifiedElements) { element.setModified(false); } } return userChoice == SaveDocuments.CHOICE.CANCEL; } else { return false; } } private void saveSIFState() { // Load SIF properties try { UIFactory.saveState(new File(viewWorkspace.getSIFPath())); } catch (IOException ex) { LOGGER.error(I18N.tr("Error while saving dialogs informations."), ex); } } /** * Stops this application, closes the {@link MainFrame} and saves all properties. This method is * called through the MainFrame.MAIN_FRAME_CLOSING event listener. */ public boolean shutdown(boolean stopVM) { if (!isShutdownVetoed()) { try { mainFrame.setVisible(false); // Hide the main panel mainContext.saveStatus(); // Save the services status // Save dialogs status saveSIFState(); // Save layout dockManager.saveLayout(); this.dispose(); } finally { // While public Plugins are not implemented do not close the VM in finally clause if (stopVM) { SwingUtilities.invokeLater( new Runnable() { /** * If an error occur while unload resources, java machine may continue to run. In * this case, the following command would terminate the application. */ public void run() { System.exit(0); } }); } } return true; } else { return false; } } /** A method to save the workspace : documents and layout */ public void onMenuSaveApplication() { if (!isShutdownVetoed()) { mainContext.saveStatus(); // Save the services status // Save dialogs status saveSIFState(); // Save layout dockManager.saveLayout(); LOGGER.info(I18N.tr("The workspace has been saved.")); } else { LOGGER.info(I18N.tr("The workspace hasn't been saved.")); } } }
/** * A {@code ProportionalPoint} is a {@link ConstantFormPoint} whose {@code ViewBox} is defined so * that it can be recognized as a {@code MonovariateProportionalViewBox}. * * @author Alexis Guéganno */ public class ProportionalPoint extends ConstantFormPoint implements IUniqueSymbolArea, IInterpolationLegend { private ProportionalWKNLegend markGraphic; private static final I18n I18N = I18nFactory.getI18n(ProportionalPoint.class); public static final String NAME = I18N.tr("Proportional Point"); /** * Builds a new {@code ProportionalPoint}. It has default {@code MarkGraphic} parameters except * for the {@code ViewBox}, of course. */ public ProportionalPoint() { super(); markGraphic = new ProportionalWKNLegend(); PointSymbolizer ps = (PointSymbolizer) getSymbolizer(); ps.getGraphicCollection().delGraphic(0); ps.getGraphicCollection().addGraphic(markGraphic.getMarkGraphic()); } /** * Tries to build an instance of {@code ProportionalPoint} using the given {@code * PointSymbolizer}. * * @param pointSymbolizer * @throws IllegalArgumentException If {@code pointSymbolizer} can't be recognized as a valid * {@code UniqueSymbolPoint}. */ public ProportionalPoint(PointSymbolizer pointSymbolizer) { super(pointSymbolizer); if (pointSymbolizer.getGraphicCollection().getNumGraphics() == 1) { Graphic gr = pointSymbolizer.getGraphicCollection().getGraphic(0); if (gr instanceof MarkGraphic) { markGraphic = new ProportionalWKNLegend((MarkGraphic) gr); } } else { throw new IllegalArgumentException( "We can't analyze symbolizers with" + "graphic collections."); } } /** * Create a new {@code ProportionalPoint}. As the associated analysis is given in parameter, it is * up to the calling method to be sure that * * @param symbolizer * @param graphicLegend */ public ProportionalPoint(PointSymbolizer symbolizer, ProportionalWKNLegend graphicLegend) { super(symbolizer); markGraphic = graphicLegend; } @Override public ConstantFormWKN getMarkGraphic() { return markGraphic; } /** * Gets the Fill analysis embedded in this {@code IUniqueSymbolArea}. * * @return */ @Override public ConstantSolidFill getFillLegend() { return markGraphic.getSolidFill(); } /** * Sets the Fill analysis embedded in this {@code IUniqueSymbolArea}. * * @param csf */ @Override public void setFillLegend(ConstantSolidFill csf) { markGraphic.setFillLegend(csf); } /** * Gets the analysis associated to the inner {@code PenStroke}. * * @return */ @Override public ConstantPenStroke getPenStroke() { return markGraphic.getPenStroke(); } /** * Sets the analysis associated to the inner {@code PenStroke}. * * @param cpsl */ @Override public void setPenStroke(ConstantPenStroke cpsl) { markGraphic.setPenStroke(cpsl); } @Override public String getLookupFieldName() { return markGraphic.getLookupFieldName(); } @Override public void setLookupFieldName(String name) { markGraphic.setLookupFieldName(name); } @Override public double getFirstData() { return markGraphic.getFirstData(); } @Override public void setFirstData(double d) { markGraphic.setFirstData(d); } @Override public double getSecondData() { return markGraphic.getSecondData(); } @Override public void setSecondData(double d) { markGraphic.setSecondData(d); } @Override public double getFirstValue() throws ParameterException { return markGraphic.getFirstValue(); } @Override public void setFirstValue(double d) { markGraphic.setFirstValue(d); } @Override public double getSecondValue() throws ParameterException { return markGraphic.getSecondValue(); } @Override public void setSecondValue(double d) { markGraphic.setSecondValue(d); } @Override public String getLegendTypeName() { return NAME; } @Override public String getLegendTypeId() { return "org.orbisgis.legend.thematic.proportional.ProportionalPoint"; } }
/** * Remove selected rows in the DataSource. * * @author Nicolas Fortin * @author Sylvain PALOMINOS */ public class ActionRemoveRow extends AbstractAction { /** Title of the wps process to use. */ private static final String PROCESS_TITLE = "RemoveRow"; /** Name of the process input containing the table name. */ private static final String INPUT_TABLE = "Table"; /** Name of the process input containing the primary key field name. */ private static final String INPUT_PK_FIELD = "PKField"; /** Name of the process input containing the primary key array. */ private static final String INPUT_PK_ARRAY = "PKArray"; private final TableEditableElement editable; private static final I18n I18N = I18nFactory.getI18n(ActionRemoveRow.class); private TableEditor tableEditor; private static final Logger LOGGER = LoggerFactory.getLogger(ActionRemoveRow.class); private WpsServer wpsServer; /** * Constructor * * @param editable Table editable instance */ public ActionRemoveRow( TableEditableElement editable, TableEditor tableEditor, WpsServer wpsServer) { super(I18N.tr("Delete selected rows"), TableEditorIcon.getIcon("delete_row")); this.tableEditor = tableEditor; putValue(ActionTools.LOGICAL_GROUP, TableEditorActions.LGROUP_MODIFICATION_GROUP); putValue(ActionTools.MENU_ID, TableEditorActions.A_REMOVE_ROW); this.editable = editable; updateEnabledState(); editable.addPropertyChangeListener( EventHandler.create(PropertyChangeListener.class, this, "onEditableUpdate", "")); this.wpsServer = wpsServer; } /** Enable this action only if edition is enabled */ public void onEditableUpdate(PropertyChangeEvent evt) { if (TableEditableElement.PROP_SELECTION.equals(evt.getPropertyName()) || TableEditableElement.PROP_EDITING.equals(evt.getPropertyName())) { updateEnabledState(); } } private void updateEnabledState() { setEnabled(editable.isEditing() && !editable.getSelection().isEmpty()); } @Override public void actionPerformed(ActionEvent actionEvent) { if (editable.isEditing()) { Set<Long> selectedRows = editable.getSelection(); int response = JOptionPane.showConfirmDialog( tableEditor, I18N.tr("Are you sure to remove the {0} selected rows ?", selectedRows.size()), I18N.tr("Delete selected rows"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (response == JOptionPane.YES_OPTION) { if (wpsServer != null) { /** Would be updates later once the WPS client will be fully updated * */ /*Process p = null; for(ProcessIdentifier pi : wpsService.getCapabilities()){ if(pi.getProcess().getTitle().equals(PROCESS_TITLE)){ p = pi.getProcess(); break; } } if(p != null){ try(Connection connection = editable.getDataManager().getDataSource().getConnection()) { //Gets the pk column name int columnId = JDBCUtilities.getIntegerPrimaryKey(connection, editable.getTableReference()); String pkColumnName = JDBCUtilities.getFieldName(connection.getMetaData(), editable.getTableReference(), columnId); //Gets the pk list as a String[] String[] pkList = new String[editable.getSelection().size()]; SortedSet<Long> selection = editable.getSelection(); int i = 0; for (Long l : selection) { pkList[i] = l.toString(); i++; } //Build the dataMap Map<URI, Object> dataMap = new HashMap<>(); for (Input input : p.getInput()) { if (input.getTitle().equals(INPUT_TABLE)) { URI uri = DataStoreOld.buildUriDataStore(DataStoreOld.DATASTORE_TYPE_GEOCATALOG, editable.getTableReference(), editable.getTableReference()); dataMap.put(input.getIdentifier(), uri); } if (input.getTitle().equals(INPUT_PK_ARRAY)) { dataMap.put(input.getIdentifier(), pkList); } if (input.getTitle().equals(INPUT_PK_FIELD)) { dataMap.put(input.getIdentifier(), pkColumnName); } } //Run the service wpsService.execute(p, dataMap, null); //Indicates to the tableEditor that a change occurred. tableEditor.tableChange(new TableEditEvent(editable.getTableReference(), TableModelEvent.ALL_COLUMNS, null, null, TableModelEvent.UPDATE)); } catch (SQLException e) { LOGGER.error(I18N.tr("Unable to get the connection to remove rows.\n")+e.getMessage()); } } else{ LOGGER.error(I18N.tr("Unable to get the process '{0}' from the WpsService.", PROCESS_TITLE)); }*/ } } } } }
/** * Displays a UI with a list of the legends supported by the layer being edited in the * SimpleStyleEditor and a preview of each legend. * * @author Erwan Bocher * @author Adam Gouge */ public class LegendUIChooser implements UIPanel { private static final I18n I18N = I18nFactory.getI18n(Toc.class); private static final Logger LOGGER = Logger.getLogger(LegendUIChooser.class); /** SimpleStyleEditor. */ private LegendContext editor; /** Possible Legend names. */ private String[] names; /** The list of analyses in the UI. */ private JList lst; /** The UI. */ private JPanel mainPanel; /** Illustration of the analysis in the UI. */ private JLabel imageLabel; /** * Construct a {@link LegendUIChooser} for the layer being edited in the given {@link * SimpleStyleEditor} instance. * * @param editor SimpleStyleEditor */ public LegendUIChooser(LegendContext editor) { this.editor = editor; initNamesList(editor.getLayer()); initUI(); } /** * Populates the names array with the names of legends that can be applied to the given layer. * * @param layer Layer */ private void initNamesList(ILayer layer) { // Recover the geometry type of this ILayer. DataSource ds = layer.getDataManager().getDataSource(); int geometryColumnsCount = 0; int geomType = GeometryTypeCodes.GEOMETRY; try (Connection connection = ds.getConnection()) { TableLocation tableLocation = TableLocation.parse(layer.getTableReference()); geomType = SFSUtilities.getGeometryType(connection, tableLocation, ""); geometryColumnsCount = SFSUtilities.getGeometryFields(connection, tableLocation).size(); } catch (SQLException e) { LOGGER.warn("Could not determine the specific geometry type for " + "this layer."); } // Convert to a simple geometry. int simpleGeomType = SimpleGeometryType.getSimpleType(geomType); // Fill the names array. ArrayList<String> typeNames = new ArrayList<>(); final int lineOrPolygon = SimpleGeometryType.LINE | SimpleGeometryType.POLYGON; if ((simpleGeomType & SimpleGeometryType.ALL) != 0) { typeNames.add(UniqueSymbolPoint.NAME); if ((simpleGeomType & lineOrPolygon) != 0) { typeNames.add(UniqueSymbolLine.NAME); } if ((simpleGeomType & SimpleGeometryType.POLYGON) != 0) { typeNames.add(UniqueSymbolArea.NAME); } // Do not display the thematic maps that need an attribute if there is // only one geometry if (geometryColumnsCount > -1) { typeNames.add(RecodedPoint.NAME); if ((simpleGeomType & lineOrPolygon) != 0) { typeNames.add(RecodedLine.NAME); } if ((simpleGeomType & SimpleGeometryType.POLYGON) != 0) { typeNames.add(RecodedArea.NAME); } typeNames.add(ProportionalPoint.NAME); if ((simpleGeomType & lineOrPolygon) != 0) { typeNames.add(ProportionalLine.NAME); } typeNames.add(CategorizedPoint.NAME); if ((simpleGeomType & lineOrPolygon) != 0) { typeNames.add(CategorizedLine.NAME); } if ((simpleGeomType & SimpleGeometryType.POLYGON) != 0) { typeNames.add(CategorizedArea.NAME); } } } names = typeNames.toArray(new String[typeNames.size()]); } /** Builds the UI. */ private void initUI() { // Initialize the JList DefaultListModel model = new DefaultListModel(); for (int i = 0; i < names.length; i++) { model.addElement(names[i]); } lst = new JList(model); // Add a selection listener lst.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); lst.addListSelectionListener( new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent lse) { onThumbnailChange(lse); } }); lst.setSelectedIndex(0); // calls onThumbnailChange(lse) // Add components. mainPanel = new JPanel(new BorderLayout()); mainPanel.add(new JScrollPane(lst), BorderLayout.WEST); mainPanel.add(imageLabel, BorderLayout.CENTER); } /** Change the thumbnail according the type of legend. */ public void onThumbnailChange(ListSelectionEvent lse) { if (imageLabel == null) { imageLabel = new JLabel(); } imageLabel.setIcon(getThumbnail()); } /** * Create the thumbnail image * * @return */ public ImageIcon getThumbnail() { String legendName = names[lst.getSelectedIndex()]; if (legendName.equals(UniqueSymbolPoint.NAME)) { return createImageIcon("thumbnail_unique_point.png"); } else if (legendName.equals(UniqueSymbolLine.NAME)) { return createImageIcon("thumbnail_unique_line.png"); } else if (legendName.equals(UniqueSymbolArea.NAME)) { return createImageIcon("thumbnail_unique_area.png"); } else if (legendName.equals(ProportionalPoint.NAME)) { return createImageIcon("thumbnail_proportionnal_point.png"); } else if (legendName.equals(ProportionalLine.NAME)) { return createImageIcon("thumbnail_proportionnal_line.png"); } else if (legendName.equals(RecodedPoint.NAME)) { return createImageIcon("thumbnail_recoded_point.png"); } else if (legendName.equals(RecodedLine.NAME)) { return createImageIcon("thumbnail_recoded_line.png"); } else if (legendName.equals(RecodedArea.NAME)) { return createImageIcon("thumbnail_recoded_area.png"); } else if (legendName.equals(CategorizedPoint.NAME)) { return createImageIcon("thumbnail_interval_point.png"); } else if (legendName.equals(CategorizedLine.NAME)) { return createImageIcon("thumbnail_interval_line.png"); } else if (legendName.equals(CategorizedArea.NAME)) { return createImageIcon("thumbnail_interval_area.png"); } else { return createImageIcon("thumbnail_not_found.png"); } } /** * Returns a new {@link ILegendPanel} corresponding to the legend selected in the JList, * initialized according to the local {@link LegendContext}. * * @return Panel corresponding to selected legend, initialized appropriately. */ public ILegendPanel getSelectedPanel() { String selectedLegendTypeName = names[lst.getSelectedIndex()]; ILegendPanel panel = ILegendPanelFactory.getPanelForLegendUIChooser(editor, selectedLegendTypeName); return panel; } /** Returns an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(String path) { java.net.URL imgURL = LegendUIChooser.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { LOGGER.error(I18N.tr("Couldn't find file") + ": " + path); return null; } } // *********************** UI Panel methods ****************************** @Override public URL getIconURL() { return UIFactory.getDefaultIcon(); } @Override public String getTitle() { return I18N.tr("Select Legend"); } @Override public String validateInput() { if (lst.getSelectedIndex() == -1) { return UIFactory.getI18n().tr("You must select a legend."); } return null; } @Override public Component getComponent() { return mainPanel; } }
public class MapTransform implements PointTransformation { private static final Logger LOGGER = Logger.getLogger(MapTransform.class); private static final I18n I18N = I18nFactory.getI18n(MapTransform.class); private boolean adjustExtent; private BufferedImage image = null; private Envelope adjustedExtent = new Envelope(); private AffineTransform trans = new AffineTransform(); private AffineTransform transInv = new AffineTransform(); private Envelope extent; private ArrayList<TransformListener> listeners = new ArrayList<TransformListener>(); private ShapeWriter converter; private RenderContext currentRenderContext = screenContext; private static RenderContext draftContext; private static RenderContext screenContext; private double dpi; private static final double DEFAULT_DPI = 96.0; static { ImageLayout layout = new ImageLayout(); layout.setColorModel(ColorModel.getRGBdefault()); RenderingHints screenHints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout); screenHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); screenHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); screenHints.put( RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); screenHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); screenHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); screenHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); screenHints.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); screenHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); screenContext = new RenderContext(AffineTransform.getTranslateInstance(0.0, 0.0), screenHints); RenderingHints draftHints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout); draftHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); draftHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); draftHints.put( RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); draftHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED); draftHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); draftHints.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); draftHints.put( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); draftHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); draftContext = new RenderContext(AffineTransform.getTranslateInstance(0.0, 0.0), draftHints); } private double MAXPIXEL_DISPLAY = 0; public MapTransform() { adjustExtent = true; if (!GraphicsEnvironment.isHeadless()) { this.dpi = Toolkit.getDefaultToolkit().getScreenResolution(); } else { LOGGER.trace(I18N.tr("Headless graphics environment, set current DPI to 96.0")); this.dpi = DEFAULT_DPI; } } /** * When true, the rendered map will always respects the CRS aspect ratio When false, the Map * extent will be bound to the output extent and may re-scale the map * * @return */ public boolean isAdjustExtent() { return adjustExtent; } public void setAdjustExtent(boolean adjustExtent) { this.adjustExtent = adjustExtent; } /** * Sets the painted image * * @param newImage The image where we will draw anything from now. */ public void setImage(BufferedImage newImage) { image = newImage; calculateAffineTransform(); } public void switchToDraft() { this.currentRenderContext = MapTransform.draftContext; LOGGER.debug("Switch to draft!"); } public void switchToScreen() { this.currentRenderContext = MapTransform.screenContext; LOGGER.debug("Switch to Hign-Quality!"); } /** * Gets the current {@code RenderContext} * * @return the current {@link RenderContext} */ public RenderContext getCurrentRenderContext() { return this.currentRenderContext; } /** * Gets the current {@code RenderingHints} * * @return the current {@link RenderingHints} */ public RenderingHints getRenderingHints() { return this.currentRenderContext.getRenderingHints(); } /** * Gets the painted image * * @return The image where we've drawn things. */ public BufferedImage getImage() { return image; } /** @return The currently configured dot-per-inch measure. */ public double getDpi() { return dpi; } /** @param dpi The new dot-per-inch measure as a double. */ public void setDpi(double dpi) { this.dpi = dpi; } /** * Gets the extent used to calculate the transformation. This extent is the same as the set one * but adjusted to have the same ratio than the image * * @return */ public Envelope getAdjustedExtent() { return adjustedExtent; } /** @throws RuntimeException */ private void calculateAffineTransform() { if (extent == null) { return; } else if (image == null || getWidth() == 0 || getHeight() == 0) { return; } if (adjustExtent) { double escalaX = getWidth() / extent.getWidth(); double escalaY = getHeight() / extent.getHeight(); double xCenter = extent.getMinX() + extent.getWidth() / 2.0; double yCenter = extent.getMinY() + extent.getHeight() / 2.0; adjustedExtent = new Envelope(); double scale; if (escalaX < escalaY) { scale = escalaX; double newHeight = getHeight() / scale; double newX = xCenter - (extent.getWidth() / 2.0); double newY = yCenter - (newHeight / 2.0); adjustedExtent = new Envelope(newX, newX + extent.getWidth(), newY, newY + newHeight); } else { scale = escalaY; double newWidth = getWidth() / scale; double newX = xCenter - (newWidth / 2.0); double newY = yCenter - (extent.getHeight() / 2.0); adjustedExtent = new Envelope(newX, newX + newWidth, newY, newY + extent.getHeight()); } trans.setToIdentity(); trans.concatenate(AffineTransform.getScaleInstance(scale, -scale)); trans.concatenate( AffineTransform.getTranslateInstance( -adjustedExtent.getMinX(), -adjustedExtent.getMinY() - adjustedExtent.getHeight())); } else { adjustedExtent = new Envelope(extent); trans.setToIdentity(); double scaleX = getWidth() / extent.getWidth(); double scaleY = getHeight() / extent.getHeight(); /** Map Y axis grows downward but CRS grows upward => -1 */ trans.concatenate(AffineTransform.getScaleInstance(scaleX, -scaleY)); trans.concatenate( AffineTransform.getTranslateInstance( -extent.getMinX(), -extent.getMinY() - extent.getHeight())); } try { transInv = trans.createInverse(); } catch (NoninvertibleTransformException ex) { transInv = null; throw new RuntimeException(ex); } } /** * Gets the height of the drawn image * * @return The height of the image */ public int getHeight() { if (image == null) { return 0; } else { return image.getHeight(); } } /** * Gets the width of the drawn image * * @return The width of the image */ public int getWidth() { if (image == null) { return 0; } else { return image.getWidth(); } } /** * Sets the extent of the transformation. This extent is not used directly to calculate the * transformation but is adjusted to obtain an extent with the same ratio than the image * * @param newExtent The new base extent. */ public void setExtent(Envelope newExtent) { if ((newExtent != null) && ((newExtent.getWidth() == 0) || (newExtent.getHeight() == 0))) { newExtent.expandBy(10); } Envelope oldExtent = this.extent; boolean modified = true; /* Set extent when Envelope is modified */ if (extent != null) { if (extent.equals(newExtent)) { modified = false; } } if (modified) { this.extent = newExtent; calculateAffineTransform(); for (TransformListener listener : listeners) { listener.extentChanged(oldExtent, this); } } } /** * Replaces the inner image with a new one with the specified size. * * @param width The width of the new image * @param height The height of the new image. */ public void resizeImage(int width, int height) { int oldWidth = getWidth(); int oldHeight = getHeight(); // image = new BufferedImage(width, height, // BufferedImage.TYPE_INT_ARGB); GraphicsConfiguration configuration = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice() .getDefaultConfiguration(); image = configuration.createCompatibleImage(width, height, BufferedImage.TYPE_INT_ARGB); calculateAffineTransform(); for (TransformListener listener : listeners) { listener.imageSizeChanged(oldWidth, oldHeight, this); } } /** * Gets this transformation * * @return */ public AffineTransform getAffineTransform() { return trans; } /** * Gets the extent * * @return */ public Envelope getExtent() { return extent; } /** * Transforms an envelope in map units to image units * * @param geographicEnvelope The {@link Envelope} in map units. * @return Rectangle2DDouble The envelope in image units as a {@link Rectangle2DDouble}. */ public Rectangle2DDouble toPixel(Envelope geographicEnvelope) { final Point2D lowerRight = new Point2D.Double(geographicEnvelope.getMaxX(), geographicEnvelope.getMinY()); final Point2D upperLeft = new Point2D.Double(geographicEnvelope.getMinX(), geographicEnvelope.getMaxY()); final Point2D ul = trans.transform(upperLeft, null); final Point2D lr = trans.transform(lowerRight, null); return new Rectangle2DDouble( ul.getX(), ul.getY(), lr.getX() - ul.getX(), lr.getY() - ul.getY()); } /** * Transforms an image coordinate in pixels into a map coordinate * * @param i The x ordinate of the point in the image * @param j The y ordinate of the point in the image * @return The Point2D instance on the map computed from the given coordinates. */ public Point2D toMapPoint(int i, int j) { if (transInv != null) { return transInv.transform(new Point2D.Double(i, j), null); } else { throw new RuntimeException("NonInvertibleMatrix"); } } public Shape fromMapToWorld(Polygon p) { if (transInv != null) { return transInv.createTransformedShape(p); } else { throw new RuntimeException("NonInvertibleMatrix"); } } /** * Transforms the specified map point to an image pixel * * @param point * @return */ public Point fromMapPoint(Point2D point) { Point2D ret = trans.transform(point, null); return new Point((int) ret.getX(), (int) ret.getY()); } /** * Sets the scale denominator, the Map extent is updated * * @param denominator */ public void setScaleDenominator(double denominator) { if (!adjustedExtent.isNull()) { double currentScale = getScaleDenominator(); Coordinate center = getExtent().centre(); double expandFactor = (denominator / currentScale); Envelope nextScaleEnvelope = new Envelope(center); nextScaleEnvelope.expandBy( expandFactor * getExtent().getWidth() / 2., expandFactor * getExtent().getHeight() / 2.); setExtent(nextScaleEnvelope); } } /** @return The Image width in meter */ private double getImageMeters() { double metersByPixel = 0.0254 / dpi; return getWidth() * metersByPixel; } /** * Gets the scale denominator. If the scale is 1:1000 this method returns 1000. The scale is not * absolutely precise and errors of 2% have been measured. * * @return */ public double getScaleDenominator() { if (adjustedExtent.isNull()) { return 0; } else { return adjustedExtent.getWidth() / getImageMeters(); } } /** * Adds a listener waiting for transformation changes. * * @param listener The new {@code TransformListener}. */ public void addTransformListener(TransformListener listener) { listeners.add(listener); } /** * Removes the given listener of the associated TransformListener instances. * * @param listener The listener to be removed. */ public void removeTransformListener(TransformListener listener) { listeners.remove(listener); } @Override public void transform(Coordinate src, Point2D dest) { dest.setLocation(src.x, src.y); trans.transform(dest, dest); } /** * Gets the JTS {@code ShapeWriter} used for decimation and geometry simplifications we make * before rendering * * @return The currently used {@code ShapeWriter} instance. */ public ShapeWriter getShapeWriter() { if (converter == null) { converter = new ShapeWriter(this); converter.setRemoveDuplicatePoints(true); MAXPIXEL_DISPLAY = 0.5 / (25.4 / getDpi()); } /** * Choose a fairly conservative decimation distance to avoid visual artifacts TODO : decimation * must be activate in relation with the crs to prevent rendering bug */ // Double dec = adjustedExtent == null ? 0 : MAXPIXEL_DISPLAY / getScaleDenominator(); // converter.setDecimation(dec); return converter; } /** * Gets the AWT {@link Shape} we'll use to represent {@code geom} on the map. * * @param geom The geometry we want to draw. * @param generalize If true we'll perform generalization * @return An AWT Shape instance. */ public Shape getShape(Geometry geom, boolean generalize) { if (generalize) { Rectangle2DDouble rectangle2dDouble = toPixel(geom.getEnvelopeInternal()); if ((rectangle2dDouble.getHeight() <= MAXPIXEL_DISPLAY) && (rectangle2dDouble.getWidth() <= MAXPIXEL_DISPLAY)) { if (geom.getDimension() == 1) { Coordinate[] coords = geom.getCoordinates(); return getShapeWriter() .toShape( geom.getFactory() .createLineString(new Coordinate[] {coords[0], coords[coords.length - 1]})); } else { return rectangle2dDouble; } } } return getShapeWriter().toShape(geom); } public void redraw() { for (TransformListener listener : listeners) { listener.extentChanged(this.adjustedExtent, this); } } }