예제 #1
0
    private void updateTitle(Layer layer) {
      String editView;
      if (layer.isEditable()) {
        editView = I18N.get("ui.plugin.ViewAttributesPlugIn.edit");
      } else {
        editView = I18N.get("ui.plugin.ViewAttributesPlugIn.view");
      }

      setTitle(
          " " + I18N.get("ui.plugin.ViewAttributesPlugIn.attributes") + ": " + layer.getName());
    }
예제 #2
0
  private FeatureCollection convexHhull(TaskMonitor monitor, FeatureCollection fc) {
    monitor.allowCancellationRequests();
    monitor.report(I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Computing-Convex-Hull") + "...");

    int size = fc.size();
    GeometryFactory geomFact = null;

    if (size == 0) {
      return null;
    }
    int count = 0;
    Geometry[] geoms = new Geometry[size];

    for (Iterator i = fc.iterator(); i.hasNext(); ) {
      Feature f = (Feature) i.next();
      Geometry geom = f.getGeometry();
      if (geom == null) {
        continue;
      }
      if (geomFact == null) {
        geomFact = geom.getFactory();
      }

      geoms[count++] = geom;
    }
    GeometryCollection gc = geomFact.createGeometryCollection(geoms);
    Geometry hull = gc.convexHull();
    List hullList = new ArrayList();
    hullList.add(hull);

    return FeatureDatasetFactory.createFromGeometry(hullList);
  }
예제 #3
0
  private void initDialog(PlugInContext context) {
    dialog =
        new MultiInputDialog(
            context.getWorkbenchFrame(),
            I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Convex-Hull-on-Layer"),
            true);

    // dialog.setSideBarImage(IconLoader.icon("Overlay.gif"));
    dialog.setSideBarDescription(
        I18N.get(
            "ui.plugin.analysis.ConvexHullPlugIn.Creates-a-new-layer-containing-the-convex-hull-of-all-the-features-in-the-source-layer"));
    String fieldName = LAYER;
    JComboBox addLayerComboBox =
        dialog.addLayerComboBox(
            fieldName, context.getCandidateLayer(0), null, context.getLayerManager());
    GUIUtil.centreOnWindow(dialog);
  }
예제 #4
0
    public ViewAttributesFrame(final Layer layer, final PlugInContext context) {
      this.layerManager = context.getLayerManager();
      addInternalFrameListener(
          new InternalFrameAdapter() {
            public void internalFrameClosed(InternalFrameEvent e) {
              // Assume that there are no other views on the model [Jon
              // Aquino]
              attributeTab.getModel().dispose();
            }
          });
      setResizable(true);
      setClosable(true);
      setMaximizable(true);
      setIconifiable(true);
      getContentPane().setLayout(new BorderLayout());
      attributeTab =
          new OneLayerAttributeTab(
                  context.getWorkbenchContext(),
                  ((TaskFrameProxy) context.getActiveInternalFrame()).getTaskFrame(),
                  this)
              .setLayer(layer);
      addInternalFrameListener(
          new InternalFrameAdapter() {
            public void internalFrameOpened(InternalFrameEvent e) {
              attributeTab.getToolBar().updateEnabledState();
            }
          });
      getContentPane().add(attributeTab, BorderLayout.CENTER);
      setSize(500, 300);
      updateTitle(attributeTab.getLayer());
      context
          .getLayerManager()
          .addLayerListener(
              new LayerListener() {
                public void layerChanged(LayerEvent e) {
                  if (attributeTab.getLayer() != null) {
                    updateTitle(attributeTab.getLayer());
                  }
                  // Layer REMOVE [mmichaud 2012-01-05]
                  if (e.getType() == LayerEventType.REMOVED) {
                    if (e.getLayerable() == attributeTab.getLayer()) {
                      attributeTab.getModel().dispose();
                      context.getLayerManager().removeLayerListener(this);
                      context.getWorkbenchFrame().removeInternalFrame(ViewAttributesFrame.this);
                      dispose();
                    }
                  }
                }

                public void categoryChanged(CategoryEvent e) {}

                public void featuresChanged(FeatureEvent e) {}
              });
      Assert.isTrue(
          !(this instanceof CloneableInternalFrame),
          I18N.get("ui.plugin.ViewAttributesPlugIn.there-can-be-no-other-views-on-the-InfoModels"));
    }
예제 #5
0
 public String toString() {
   StringBuffer sb =
       new StringBuffer(I18N.get("org.openjump.core.ui.plugin.queries.Operator." + key));
   if (arg < 0.0) {
     return sb.toString();
   } else {
     return sb.toString() + " (" + arg + ")";
   }
 }
예제 #6
0
  public void run(TaskMonitor monitor, PlugInContext context) throws Exception {
    FeatureCollection a = dialog.getLayer(LAYER).getFeatureCollectionWrapper();
    FeatureCollection hullFC = convexHhull(monitor, a);

    if (hullFC == null) {
      return;
    }

    context.getLayerManager().addCategory(categoryName);
    context.addLayer(
        categoryName, I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Convex-Hull"), hullFC);
  }
예제 #7
0
  public boolean execute(PlugInContext context) throws Exception {
    // [sstein, 16.07.2006] put here again for language settings
    LAYER = I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Source-Layer");
    // Unlike ValidatePlugIn, here we always call #initDialog because we want
    // to update the layer comboboxes. [Bob Boseko]
    initDialog(context);
    dialog.setVisible(true);

    if (!dialog.wasOKPressed()) {
      return false;
    }

    return true;
  }
예제 #8
0
 public String getName() {
   return I18N.get("ui.plugin.ViewAttributesPlugIn.view-edit-attributes");
 }
 public String getAttributeValueColumnTitle() {
   return I18N.get("ui.renderer.style.RangeColorThemingState.minimum-attribute-values");
 }
 public String getAllOtherValuesDescription() {
   return I18N.get("ui.renderer.style.RangeColorThemingState.values-below-these-values");
 }
public class QuantileColorThemingState implements ColorThemingStylePanel.State {
  private ColorThemingStylePanel stylePanel;
  private static final String RANGE_COUNT_KEY =
      QuantileColorThemingState.class.getName() + " - QUANTILE COUNT";

  public String getAllOtherValuesDescription() {
    return I18N.get("ui.renderer.style.RangeColorThemingState.values-below-these-values");
  }

  public String getAttributeValueColumnTitle() {
    return I18N.get("ui.renderer.style.RangeColorThemingState.minimum-attribute-values");
  }

  private int getRangeCount() {
    return ((Integer) comboBox.getSelectedItem()).intValue();
  }

  private int getMaxAttributeClassCount() {
    return stylePanel.getAttributeValuesCount().entrySet().size() + 1;
  }

  // return a collection of lower bound values for a quantile classification.
  // avgClassSize is the average size of a quantile class
  // valuesCount is the map (attributeValue -> number of corresponding entities)
  private Collection getQuantileBreaks(double avgClassSize, SortedMap valuesCount) {
    Set filteredValues = new TreeSet();
    Iterator v = valuesCount.keySet().iterator();
    if (!v.hasNext()) return filteredValues;
    Object value = v.next();
    int count = ((Integer) valuesCount.get(value)).intValue();
    filteredValues.add(value);
    // update of classification variables
    int classified = count; // total classified at this point
    double avgClassifiedAtNextLoop = avgClassSize; // expected to be classified at next loop
    while (v.hasNext()) {
      value = v.next();
      count = ((Integer) valuesCount.get(value)).intValue();

      if (((double) classified) > avgClassifiedAtNextLoop) {
        //        		System.out.println("break value : " + value.toString());
        filteredValues.add(value);
        avgClassifiedAtNextLoop =
            avgClassifiedAtNextLoop + avgClassSize; // expected to be classified at next loop
      }
      classified = classified + count; // total classified at this point
    }
    return filteredValues;
  }

  /**
   * Returns a Collection with double values that are corresponding to the class breaks. Note: the
   * smallest number is equal to the minValue of all attributes.
   */
  public Collection filterAttributeValues(SortedSet attributeValues) {
    // -1 because one row in the table is reserved for "all other values". [Bob Boseko]
    // int classCount = getRangeCount() - 1;
    Collection filteredValues = new ArrayList();
    if (attributeValues.size() == 0) {
      return filteredValues;
    }
    // -1 deleted because class range is false
    int classCount = Math.min(getRangeCount(), attributeValues.size());

    // -- [sstein 15.Feb. 2009]
    //   replaced O-Bedels code by own code to be consistent
    //   in case somebody uses Classifier1D methods for classification
    //   and attaches the result as attribute values (i.e. to ensure
    //   that same values are obtained)
    /*
    int featuresCount = stylePanel.getLayer().getFeatureCollectionWrapper().size();
    double avgClassSize = ((double) featuresCount) / ((double) classCount); // type double to avoid round off errors
    SortedMap valuesCount = stylePanel.getAttributeValuesCount();

    Collection filteredValues = getQuantileBreaks(avgClassSize, valuesCount);
    */
    // -- sstein: new code
    double[] data = new double[attributeValues.size()];
    int i = 0;
    boolean isInteger = false;
    for (Iterator iterator = attributeValues.iterator(); iterator.hasNext(); ) {
      Object val = (Object) iterator.next();
      if (val instanceof Integer) {
        data[i] = (Integer) val;
        isInteger = true;
      } else if (val instanceof Double) {
        data[i] = (Double) val;
      } else {
        data[i] = Double.NaN;
      }
      i++;
    }
    double[] breaks = Classifier1D.classifyEqualNumber(data, classCount);
    double minVal = org.math.array.DoubleArray.min(data);
    // add minVal as smallest value
    if (isInteger) {
      filteredValues.add(new Integer((int) minVal));
    } else {
      filteredValues.add(new Double(minVal));
    }
    for (int j = 0; j < breaks.length; j++) {
      if (isInteger) {
        filteredValues.add(new Integer((int) breaks[j]));
      } else {
        filteredValues.add(new Double(breaks[j]));
      }
    }
    // -- sstein: end
    return filteredValues;
  }

  private JPanel panel =
      new JPanel(new GridBagLayout()) {
        public void setEnabled(boolean enabled) {
          comboBox.setEnabled(enabled);
          label.setEnabled(enabled);
          reverseButton.setEnabled(enabled);
          super.setEnabled(enabled);
        }
      };

  public QuantileColorThemingState(final ColorThemingStylePanel stylePanel) {
    this.stylePanel = stylePanel;
    addComboBoxItems();
    comboBox.setSelectedItem(
        stylePanel
            .getLayer()
            .getLayerManager()
            .getBlackboard()
            .get(RANGE_COUNT_KEY, new Integer(5)));
    // Don't add action listeners until items have been added to the
    // combo box. [Bob Boseko]
    comboBox.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            stylePanel.populateTable();
            stylePanel
                .getLayer()
                .getLayerManager()
                .getBlackboard()
                .put(RANGE_COUNT_KEY, comboBox.getSelectedItem());
          }
        });
    panel.add(
        label,
        new GridBagConstraints(
            1,
            0,
            1,
            1,
            0,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(2, 2, 2, 2),
            0,
            0));
    panel.add(
        comboBox,
        new GridBagConstraints(
            2,
            0,
            1,
            1,
            0,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(2, 2, 2, 2),
            0,
            0));
    panel.add(
        reverseButton,
        new GridBagConstraints(
            3,
            0,
            1,
            1,
            0,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(2, 2, 2, 2),
            0,
            0));
    reverseButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            reversingColorScheme = !reversingColorScheme;
            stylePanel.applyColorScheme();
          }
        });
  }

  private JButton reverseButton =
      new JButton(I18N.get("ui.renderer.style.RangeColorThemingState.reverse-colors"));

  private void addComboBoxItems() {
    int maxColorSchemeSize = -1;
    for (Iterator i = ColorScheme.rangeColorSchemeNames().iterator(); i.hasNext(); ) {
      String rangeColorSchemeName = (String) i.next();
      maxColorSchemeSize =
          Math.max(maxColorSchemeSize, ColorScheme.create(rangeColorSchemeName).getColors().size());
    }
    for (int i = 3; i <= maxColorSchemeSize; i++) {
      comboBoxModel.addElement(new Integer(i));
    }
  }

  private DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel();
  private JComboBox comboBox = new JComboBox(comboBoxModel);
  private JLabel label =
      new JLabel(I18N.get("ui.renderer.style.RangeColorThemingState.range-count"));

  public JComponent getPanel() {
    return panel;
  }

  public Map fromExternalFormat(Map attributeValueToObjectMap) {
    // Table takes values, not ranges. [Bob Boseko]
    TreeMap newMap = new TreeMap();
    for (Iterator i = attributeValueToObjectMap.keySet().iterator(); i.hasNext(); ) {
      Range range = (Range) i.next();
      newMap.put(range.getMin(), attributeValueToObjectMap.get(range));
    }
    return newMap;
  }

  public Map toExternalFormat(Map attributeValueToObjectMap) {
    if (attributeValueToObjectMap.isEmpty()) {
      return attributeValueToObjectMap;
    }
    // Turn the values into ranges. Validations have already ensured that
    // the values are unique and contain no nulls. [Bob Boseko]
    Assert.isTrue(attributeValueToObjectMap instanceof SortedMap);
    TreeMap newMap = new Range.RangeTreeMap();
    Object previousValue = null;
    for (Iterator i = attributeValueToObjectMap.keySet().iterator(); i.hasNext(); ) {
      Object value = i.next();
      try {
        if (previousValue == null) {
          // Let the default style handle values from negative infinity to
          // the first value. [Bob Boseko]
          continue;
        }
        // Make one side inclusive and the other exclusive to ensure no
        // overlaps. [Bob Boseko]
        newMap.put(
            new Range(previousValue, true, value, false),
            attributeValueToObjectMap.get(previousValue));
      } finally {
        previousValue = value;
      }
    }
    newMap.put(
        new Range(previousValue, true, new Range.PositiveInfinity(), false),
        attributeValueToObjectMap.get(previousValue));
    return newMap;
  }

  public void applyColorScheme(ColorScheme colorScheme) {
    stylePanel
        .tableModel()
        .apply(
            new ColorScheme(
                null,
                CollectionUtil.stretch(
                    colorScheme.getColors(),
                    new ArrayList(),
                    stylePanel.tableModel().getRowCount())),
            false);
  }

  public Collection getColorSchemeNames() {
    return ColorScheme.rangeColorSchemeNames();
  }

  private TableModelListener tableModelListener =
      new TableModelListener() {
        public void tableChanged(TableModelEvent e) {
          if (e instanceof ColorThemingTableModel.AttributeValueTableModelEvent) {
            stylePanel.tableModel().sort(stylePanel.tableModel().wasLastSortAscending());
            // I'd like to scroll to the row at this point, but the user probably
            // finished the edit by clicking on another cell, so even if I scroll
            // to the row, it scrolls back to where the user clicked. [Bob Boseko]
          }
        }
      };

  private int row(Object attributeValue) {
    for (int i = 0; i < stylePanel.tableModel().getRowCount(); i++) {
      Object otherAttributeValue =
          stylePanel.tableModel().getValueAt(i, ColorThemingTableModel.ATTRIBUTE_COLUMN);
      if (attributeValue == null && otherAttributeValue == null) {
        return i;
      }
      if (attributeValue != null && attributeValue.equals(otherAttributeValue)) {
        return i;
      }
    }
    Assert.shouldNeverReachHere();
    return -1;
  }

  public void activate() {
    stylePanel.tableModel().addTableModelListener(tableModelListener);
  }

  public void deactivate() {
    stylePanel.tableModel().removeTableModelListener(tableModelListener);
  }

  private boolean reversingColorScheme = false;

  public ColorScheme filterColorScheme(ColorScheme colorScheme) {
    if (!reversingColorScheme) {
      return colorScheme;
    }
    List colors = new ArrayList(colorScheme.getColors());
    Collections.reverse(colors);
    return new ColorScheme(colorScheme.getName(), colors);
  }
}
예제 #12
0
 public String getName() {
   return I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Convex-Hull-on-Layer");
 }
예제 #13
0
public class ConvexHullPlugIn extends AbstractPlugIn implements ThreadedPlugIn {

  private String LAYER = I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Source-Layer");
  private MultiInputDialog dialog;

  public ConvexHullPlugIn() {}

  private String categoryName = StandardCategoryNames.RESULT;

  public void setCategoryName(String value) {
    categoryName = value;
  }

  public void initialize(PlugInContext context) throws Exception {
    FeatureInstaller featureInstaller = new FeatureInstaller(context.getWorkbenchContext());
    featureInstaller.addMainMenuItem(
        this,
        new String[] {MenuNames.TOOLS, MenuNames.TOOLS_ANALYSIS},
        new JMenuItem(this.getName() + "..."),
        createEnableCheck(context.getWorkbenchContext()));
  }

  public static MultiEnableCheck createEnableCheck(WorkbenchContext workbenchContext) {
    EnableCheckFactory checkFactory = new EnableCheckFactory(workbenchContext);

    return new MultiEnableCheck()
        .add(checkFactory.createWindowWithLayerNamePanelMustBeActiveCheck())
        .add(checkFactory.createAtLeastNLayersMustExistCheck(1));
  }

  public boolean execute(PlugInContext context) throws Exception {
    // [sstein, 16.07.2006] put here again for language settings
    LAYER = I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Source-Layer");
    // Unlike ValidatePlugIn, here we always call #initDialog because we want
    // to update the layer comboboxes. [Bob Boseko]
    initDialog(context);
    dialog.setVisible(true);

    if (!dialog.wasOKPressed()) {
      return false;
    }

    return true;
  }

  public String getName() {
    return I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Convex-Hull-on-Layer");
  }

  private void initDialog(PlugInContext context) {
    dialog =
        new MultiInputDialog(
            context.getWorkbenchFrame(),
            I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Convex-Hull-on-Layer"),
            true);

    // dialog.setSideBarImage(IconLoader.icon("Overlay.gif"));
    dialog.setSideBarDescription(
        I18N.get(
            "ui.plugin.analysis.ConvexHullPlugIn.Creates-a-new-layer-containing-the-convex-hull-of-all-the-features-in-the-source-layer"));
    String fieldName = LAYER;
    JComboBox addLayerComboBox =
        dialog.addLayerComboBox(
            fieldName, context.getCandidateLayer(0), null, context.getLayerManager());
    GUIUtil.centreOnWindow(dialog);
  }

  public void run(TaskMonitor monitor, PlugInContext context) throws Exception {
    FeatureCollection a = dialog.getLayer(LAYER).getFeatureCollectionWrapper();
    FeatureCollection hullFC = convexHhull(monitor, a);

    if (hullFC == null) {
      return;
    }

    context.getLayerManager().addCategory(categoryName);
    context.addLayer(
        categoryName, I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Convex-Hull"), hullFC);
  }

  private FeatureCollection convexHhull(TaskMonitor monitor, FeatureCollection fc) {
    monitor.allowCancellationRequests();
    monitor.report(I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Computing-Convex-Hull") + "...");

    int size = fc.size();
    GeometryFactory geomFact = null;

    if (size == 0) {
      return null;
    }
    int count = 0;
    Geometry[] geoms = new Geometry[size];

    for (Iterator i = fc.iterator(); i.hasNext(); ) {
      Feature f = (Feature) i.next();
      Geometry geom = f.getGeometry();
      if (geom == null) {
        continue;
      }
      if (geomFact == null) {
        geomFact = geom.getFactory();
      }

      geoms[count++] = geom;
    }
    GeometryCollection gc = geomFact.createGeometryCollection(geoms);
    Geometry hull = gc.convexHull();
    List hullList = new ArrayList();
    hullList.add(hull);

    return FeatureDatasetFactory.createFromGeometry(hullList);
  }
}
예제 #14
0
/**
 * The types of validation errors detected by Validator.
 *
 * @see Validator
 */
public class ValidationErrorType {
  /** Geometry class not allowed */
  public static final ValidationErrorType GEOMETRY_CLASS_DISALLOWED =
      new ValidationErrorType(I18N.get("qa.ValidationErrorType.geometry-class-not-allowed"));

  /** Basic topology is invalid */
  public static final ValidationErrorType BASIC_TOPOLOGY_INVALID =
      new ValidationErrorType(I18N.get("qa.ValidationErrorType.basic-topology-is-invalid"));

  /** Polygon shell is oriented counter-clockwise */
  public static final ValidationErrorType EXTERIOR_RING_CCW =
      new ValidationErrorType(
          I18N.get("qa.ValidationErrorType.polygon-shell-is-oriented-counter-clockwise"));

  /** Polygon hole is oriented clockwise */
  public static final ValidationErrorType INTERIOR_RING_CW =
      new ValidationErrorType(
          I18N.get("qa.ValidationErrorType.polygon-hole-is-oriented-clockwise"));

  /** Linestring not simple */
  public static final ValidationErrorType NONSIMPLE_LINESTRING =
      new ValidationErrorType(I18N.get("qa.ValidationErrorType.linestring-not-simple"));

  /** Contains segment with length below minimum */
  public static final ValidationErrorType SMALL_SEGMENT =
      new ValidationErrorType(
          I18N.get("qa.ValidationErrorType.contains-segment-with-length-below-minimum"));

  /** Is/contains polygon with area below minimum */
  public static final ValidationErrorType SMALL_AREA =
      new ValidationErrorType(
          I18N.get("qa.ValidationErrorType.is-contain-polygon-with-area-below-minimum"));

  /** Contains segments with angle below minimum */
  public static final ValidationErrorType SMALL_ANGLE =
      new ValidationErrorType(
          I18N.get("qa.ValidationErrorType.contains-segments-with-angle-below-minimum"));

  /** Polygon has holes */
  public static final ValidationErrorType POLYGON_HAS_HOLES =
      new ValidationErrorType(I18N.get("qa.ValidationErrorType.polygon-has-holes"));

  /** Consecutive points are the same */
  public static final ValidationErrorType REPEATED_CONSECUTIVE_POINTS =
      new ValidationErrorType(I18N.get("qa.ValidationErrorType.consecutive-points-are-the-same"));

  private String message;

  private ValidationErrorType(String message) {
    this.message = message;
  }

  /**
   * Returns a description of the error.
   *
   * @return a description of the error
   */
  public String getMessage() {
    return message;
  }

  public String toString() {
    return getMessage();
  }
}
예제 #15
0
 public String getName() {
   // The default implementation will return "Select Line Strings". [Bob Boseko]
   return I18N.get("ui.cursortool.SelectLineStringsTool.select-linestrings");
 }
예제 #16
0
public class ConstraintsOptionsPanel extends JPanel {

  private Border titleBorder;
  WorkbenchContext workbenchContext;
  static final String length =
      I18N.get("org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Length");
  static final String incAngle =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Incremental-Angle");
  static final String incAngleShiftCtrl =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Incremental-Angle-Shift-to-activate-Ctrl-to-close");
  static final String angle =
      I18N.get("org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Angle");
  static final String angleShift =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Angle-Shift-to-activate");
  static final String constrainAngleByStepsOf =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Constrain-angle-by-steps-of");
  static final String degree =
      I18N.get("org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.degree");
  static final String negativeNumbersNotAllowedForLength =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.negative-numbers-not-allowed-for-length");
  static final String isToSmall =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.is-too-small-must-be-3-or-greater");
  static final String invalidNumbers =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.invalid-numbers");
  static final String constrainLengthToNearest =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Constrain-length-to-nearest");
  static final String modelUnits =
      I18N.get("org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.model-units");
  static final String ConstrainAngleTo45DegreeIncrements =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Constrain-angle-to-45-degree-increments");
  static final String byDividing360DegreesInto =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.by-dividing-360-degrees-into");
  static final String parts =
      I18N.get("org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.parts");
  static final String constrainToRelativeAngle =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Constrain-to-relative-angle");
  static final String constrainToAbsoluteAngle =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Constrain-to-absolute-angle");
  static final String degrees =
      I18N.get("org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.degrees");
  static final String constrainToAngle =
      I18N.get(
          "org.openjump.core.ui.plugin.edittoolbox.tab.ConstraintsOptionsPanel.Constrain-to-angle");
  // main constraints panel
  private JPanel constraintsPanel = new JPanel();
  private BorderLayout constraintsBorderLayout = new BorderLayout();
  private GridBagLayout constraintsGridBagLayout = new GridBagLayout();
  // length constraint
  private JPanel lengthPanel = new JPanel();
  private JPanel lengthSubPanel = new JPanel();
  private GridBagLayout lengthPanelGridBagLayout = new GridBagLayout();
  private GridBagLayout lengthSubPanelGridBagLayout = new GridBagLayout();
  private TitledBorder lengthPanelTitle = new TitledBorder(titleBorder, length);
  private JCheckBox lengthCheckBox = new JCheckBox();
  private JTextField lengthTextField = new JTextField(4);
  private JLabel lengthUnitsLabel = new JLabel();
  // incremental angle constraint
  private JPanel incrementalAnglePanel = new JPanel();
  private JPanel incrementalAngleSubPanel = new JPanel();
  private GridBagLayout incrementalAnglePanelGridBagLayout = new GridBagLayout();
  private GridBagLayout incrementalAngleSubPanelGridBagLayout = new GridBagLayout();
  private TitledBorder IncrementalAnglePanelTitleShort = new TitledBorder(titleBorder, incAngle);
  private TitledBorder IncrementalAnglePanelTitleLong =
      new TitledBorder(titleBorder, incAngleShiftCtrl);
  private JCheckBox constrainIncrementalAngleCheckBox = new JCheckBox();
  private JTextField numPartsTextField = new JTextField(4);
  private GridBagLayout gridBagLayout4 = new GridBagLayout();
  private JPanel numPartsPanel = new JPanel();
  private JLabel numPartsPreLabel = new JLabel();
  private JLabel numPartsPostLabel = new JLabel();
  // angle constraint
  private JPanel anglePanel = new JPanel();
  private TitledBorder anglePanelTitleShort = new TitledBorder(titleBorder, angle);
  private TitledBorder anglePanelTitleLong = new TitledBorder(titleBorder, angleShift);
  private GridBagLayout AnglePanelGridBagLayout = new GridBagLayout();
  private GridBagLayout angleDataPanelGridBagLayout = new GridBagLayout();
  private JPanel angleDataPanel = new JPanel();
  private JTextField angleConstraintTextField = new JTextField(4);
  private JCheckBox constrainAngleCheckBox = new JCheckBox();
  private JRadioButton relativeAngleRadioButton = new JRadioButton();
  private JRadioButton absoluteAngleRadioButton = new JRadioButton();
  private JLabel angleUnitsLabel = new JLabel();
  private ButtonGroup angleButtonGroup = new ButtonGroup();
  private JLabel absAngleImageLabel = new JLabel();
  private JLabel relAngleImageLabel = new JLabel();
  boolean start = false;

  public ConstraintsOptionsPanel(WorkbenchContext workbenchContext) {
    this.workbenchContext = workbenchContext;
    try {
      this.jbInit();
      this.init();
    } catch (Exception e) {
      Assert.shouldNeverReachHere(e.toString());
    }
    relativeAngleRadioButton.addItemListener(
        new ItemListener() {
          @Override
          public void itemStateChanged(ItemEvent e) {
            if (start) {
              SettingOptionsDialog.page.fireButtonEvent(
                  ButtonEvent.ENABLE_BUTTON, ButtonNames.APPLY);
            }
          }
        });
    lengthCheckBox.addItemListener(
        new ItemListener() {
          @Override
          public void itemStateChanged(ItemEvent e) {
            updateEnabled();
          }
        });
    constrainIncrementalAngleCheckBox.addItemListener(
        new ItemListener() {
          public void itemStateChanged(ItemEvent e) {
            updateEnabled();
          }
        });
    constrainAngleCheckBox.addItemListener(
        new ItemListener() {
          public void itemStateChanged(ItemEvent e) {
            updateEnabled();
          }
        });
    numPartsTextField.addFocusListener(
        new myFocusListener() {
          public void focusLost(FocusEvent e) {
            double newAngle = 360.0 / Double.parseDouble(numPartsTextField.getText());
            // constrainIncrementalAngleCheckBox.setText("Constrain angle to " + newAngle + " degree
            // increments");
            // [sstein: 16.10.2005]
            constrainIncrementalAngleCheckBox.setText(
                constrainAngleByStepsOf + " " + newAngle + " " + degree);
          }
        });
  }

  private void updateEnabled() {
    lengthTextField.setEnabled(lengthCheckBox.isSelected());
    numPartsTextField.setEnabled(constrainIncrementalAngleCheckBox.isSelected());
    angleConstraintTextField.setEnabled(constrainAngleCheckBox.isSelected());
    relativeAngleRadioButton.setEnabled(constrainAngleCheckBox.isSelected());
    absoluteAngleRadioButton.setEnabled(constrainAngleCheckBox.isSelected());

    if (constrainIncrementalAngleCheckBox.isSelected()) {
      incrementalAnglePanel.setBorder(IncrementalAnglePanelTitleLong);
    } else {
      incrementalAnglePanel.setBorder(IncrementalAnglePanelTitleShort);
    }

    if (constrainAngleCheckBox.isSelected()) {
      anglePanel.setBorder(anglePanelTitleLong);
    } else {
      anglePanel.setBorder(anglePanelTitleShort);
    }
    if (start) {
      SettingOptionsDialog.page.fireButtonEvent(ButtonEvent.ENABLE_BUTTON, ButtonNames.APPLY);
    }
  }

  public String validateInput() {
    String errorMessage1 =
        "\"" + lengthTextField.getText() + "\"" + negativeNumbersNotAllowedForLength;
    String errorMessage2 = "\"" + numPartsTextField.getText() + "\"" + isToSmall;
    String errorMessage3 = invalidNumbers;

    try {
      if (Double.parseDouble(lengthTextField.getText()) < 0) {
        return errorMessage1;
      }
      if (Integer.parseInt(numPartsTextField.getText()) < 3) {
        return errorMessage2;
      }
    } catch (NumberFormatException e) {
      return errorMessage3;
    }
    return null;
  }

  public void okPressed() {
    PersistentBlackboardPlugIn.get(workbenchContext)
        .put(ConstraintManager.CONSTRAIN_LENGTH_ENABLED_KEY, lengthCheckBox.isSelected());
    PersistentBlackboardPlugIn.get(workbenchContext)
        .put(
            ConstraintManager.LENGTH_CONSTRAINT_KEY, Double.parseDouble(lengthTextField.getText()));
    PersistentBlackboardPlugIn.get(workbenchContext)
        .put(
            ConstraintManager.CONSTRAIN_INCREMENTAL_ANGLE_ENABLED_KEY,
            constrainIncrementalAngleCheckBox.isSelected());
    PersistentBlackboardPlugIn.get(workbenchContext)
        .put(
            ConstraintManager.INCREMENTAL_ANGLE_SIZE_KEY,
            Integer.parseInt(numPartsTextField.getText()));
    PersistentBlackboardPlugIn.get(workbenchContext)
        .put(ConstraintManager.CONSTRAIN_ANGLE_ENABLED_KEY, constrainAngleCheckBox.isSelected());
    PersistentBlackboardPlugIn.get(workbenchContext)
        .put(
            ConstraintManager.ANGLE_SIZE_KEY,
            Double.parseDouble(angleConstraintTextField.getText()));
    PersistentBlackboardPlugIn.get(workbenchContext)
        .put(ConstraintManager.RELATIVE_ANGLE_KEY, relativeAngleRadioButton.isSelected());
    PersistentBlackboardPlugIn.get(workbenchContext)
        .put(ConstraintManager.ABSOLUTE_ANGLE_KEY, absoluteAngleRadioButton.isSelected());
  }

  public final void init() {
    lengthCheckBox.setSelected(
        PersistentBlackboardPlugIn.get(workbenchContext)
            .get(ConstraintManager.CONSTRAIN_LENGTH_ENABLED_KEY, false));
    lengthTextField.setText(
        ""
            + PersistentBlackboardPlugIn.get(workbenchContext)
                .get(ConstraintManager.LENGTH_CONSTRAINT_KEY, 0.5d));
    constrainIncrementalAngleCheckBox.setSelected(
        PersistentBlackboardPlugIn.get(workbenchContext)
            .get(ConstraintManager.CONSTRAIN_INCREMENTAL_ANGLE_ENABLED_KEY, false));
    numPartsTextField.setText(
        ""
            + PersistentBlackboardPlugIn.get(workbenchContext)
                .get(ConstraintManager.INCREMENTAL_ANGLE_SIZE_KEY, 8));
    constrainAngleCheckBox.setSelected(
        PersistentBlackboardPlugIn.get(workbenchContext)
            .get(ConstraintManager.CONSTRAIN_ANGLE_ENABLED_KEY, false));
    angleConstraintTextField.setText(
        ""
            + PersistentBlackboardPlugIn.get(workbenchContext)
                .get(ConstraintManager.ANGLE_SIZE_KEY, 30d));
    relativeAngleRadioButton.setSelected(
        PersistentBlackboardPlugIn.get(workbenchContext)
            .get(ConstraintManager.RELATIVE_ANGLE_KEY, true));
    absoluteAngleRadioButton.setSelected(
        PersistentBlackboardPlugIn.get(workbenchContext)
            .get(ConstraintManager.ABSOLUTE_ANGLE_KEY, false));
    double newAngle = 360.0 / Double.parseDouble(numPartsTextField.getText());
    // constrainIncrementalAngleCheckBox.setText("Constrain angle to " + newAngle + " degree
    // increments"); [sstein]
    constrainIncrementalAngleCheckBox.setText(
        constrainAngleByStepsOf + " " + newAngle + " " + degree);
    updateEnabled();
    start = true;
  }

  private void jbInit() throws Exception {
    constrainAngleCheckBox.setFocusable(false);
    lengthCheckBox.setFocusable(false);
    constrainIncrementalAngleCheckBox.setFocusable(false);
    relativeAngleRadioButton.setFocusable(false);
    absoluteAngleRadioButton.setFocusable(false);
    titleBorder = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140));

    // **********************
    // main constraints panel
    // **********************

    this.setLayout(constraintsBorderLayout);
    this.add(constraintsPanel, BorderLayout.CENTER);
    constraintsPanel.setLayout(constraintsGridBagLayout);

    //        constraintsPanel.add(constraintsSubPanel,
    //                             new GridBagConstraints(0, 3, 1, 1, 0.0, 1.0,
    //                             GridBagConstraints.CENTER, GridBagConstraints.VERTICAL,
    //                             new Insets(0, 0, 0, 0), 0, 0));

    // ****************
    // length constraint
    // *****************
    lengthPanel.setBorder(lengthPanelTitle);
    lengthPanel.setLayout(lengthPanelGridBagLayout);
    lengthSubPanel.setLayout(lengthSubPanelGridBagLayout);
    lengthTextField.setText("0.5");
    lengthTextField.setHorizontalAlignment(SwingConstants.TRAILING);
    lengthCheckBox.setToolTipText("");
    lengthCheckBox.setText(constrainLengthToNearest + " ");
    lengthUnitsLabel.setText(modelUnits);

    constraintsPanel.add(
        lengthPanel,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            1.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(10, 10, 10, 10),
            0,
            0));

    lengthPanel.add(
        lengthSubPanel,
        new GridBagConstraints(
            0,
            1,
            1,
            1,
            1.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(0, 0, 0, 0),
            0,
            0));

    lengthSubPanel.add(
        lengthCheckBox,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(0, 0, 0, 0),
            0,
            0));

    lengthSubPanel.add(
        lengthTextField,
        new GridBagConstraints(
            1,
            0,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(0, 0, 0, 5),
            0,
            0));

    lengthSubPanel.add(
        lengthUnitsLabel,
        new GridBagConstraints(
            2,
            0,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(0, 0, 0, 0),
            0,
            0));

    // ****************************
    // incremental angle constraint
    // ****************************

    incrementalAnglePanel.setLayout(incrementalAnglePanelGridBagLayout);
    incrementalAngleSubPanel.setLayout(incrementalAngleSubPanelGridBagLayout);
    numPartsTextField.setText("8");
    constrainIncrementalAngleCheckBox.setText(ConstrainAngleTo45DegreeIncrements);

    constraintsPanel.add(
        incrementalAnglePanel,
        new GridBagConstraints(
            0,
            1,
            1,
            1,
            1.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(10, 10, 10, 10),
            0,
            1));

    incrementalAnglePanel.add(
        incrementalAngleSubPanel,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            1.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 0),
            0,
            0));

    incrementalAngleSubPanel.add(
        constrainIncrementalAngleCheckBox,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 0),
            0,
            0));

    incrementalAngleSubPanel.add(
        numPartsPanel,
        new GridBagConstraints(
            0,
            1,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 0),
            0,
            0));

    numPartsTextField.setHorizontalAlignment(SwingConstants.TRAILING);
    numPartsPanel.setLayout(gridBagLayout4);
    numPartsPreLabel.setText(byDividing360DegreesInto);
    numPartsPostLabel.setText(parts);

    numPartsPanel.add(
        numPartsPreLabel,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            1.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 5),
            0,
            0));

    numPartsPanel.add(
        numPartsTextField,
        new GridBagConstraints(
            1,
            0,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.CENTER,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 5),
            0,
            0));

    numPartsPanel.add(
        numPartsPostLabel,
        new GridBagConstraints(
            2,
            0,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.CENTER,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 0),
            0,
            0));

    // ****************
    // angle constraint
    // ****************

    anglePanel.setBorder(anglePanelTitleShort);
    anglePanel.setLayout(AnglePanelGridBagLayout);
    angleDataPanel.setLayout(angleDataPanelGridBagLayout);

    constraintsPanel.add(
        anglePanel,
        new GridBagConstraints(
            0,
            2,
            1,
            1,
            1.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(10, 10, 10, 10),
            0,
            0));

    anglePanel.add(
        angleDataPanel,
        new GridBagConstraints(
            0,
            1,
            1,
            1,
            1.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 0),
            0,
            0));

    angleDataPanel.add(
        constrainAngleCheckBox,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 0),
            0,
            0));

    angleDataPanel.add(
        angleConstraintTextField,
        new GridBagConstraints(
            1,
            0,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.CENTER,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 5),
            0,
            0));

    angleDataPanel.add(
        relativeAngleRadioButton,
        new GridBagConstraints(
            0,
            1,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 0),
            0,
            0));

    angleDataPanel.add(
        relAngleImageLabel,
        new GridBagConstraints(
            1,
            1,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.NORTHWEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(0, 0, 0, 0),
            0,
            0));
    relAngleImageLabel.setIcon((new ImageIcon(getClass().getResource("relAngle.png"))));

    angleDataPanel.add(
        absoluteAngleRadioButton,
        new GridBagConstraints(
            0,
            2,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 0),
            0,
            0));

    angleDataPanel.add(
        absAngleImageLabel,
        new GridBagConstraints(
            1,
            2,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.NORTHWEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(0, 0, 0, 0),
            0,
            0));
    absAngleImageLabel.setIcon((new ImageIcon(getClass().getResource("absAngle.png"))));

    angleDataPanel.add(
        angleUnitsLabel,
        new GridBagConstraints(
            2,
            0,
            1,
            1,
            0.0,
            0.0,
            GridBagConstraints.CENTER,
            GridBagConstraints.NONE,
            new Insets(0, 0, 0, 0),
            0,
            0));

    relativeAngleRadioButton.setText(constrainToRelativeAngle);
    absoluteAngleRadioButton.setText(constrainToAbsoluteAngle);
    angleUnitsLabel.setText(degrees);
    angleButtonGroup.add(relativeAngleRadioButton);
    angleButtonGroup.add(absoluteAngleRadioButton);
    angleConstraintTextField.setText("30");
    angleConstraintTextField.setHorizontalAlignment(SwingConstants.TRAILING);
    constrainAngleCheckBox.setText(constrainToAngle);
  }

  public class myFocusListener extends FocusAdapter {

    public void focusGained(FocusEvent e) {}

    public void focusLost(FocusEvent e) {}
  }
}