001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * JUMP is Copyright (C) 2003 Vivid Solutions
006: *
007: * This program implements extensions to JUMP and is
008: * Copyright (C) 2004 Integrated Systems Analysts, Inc.
009: *
010: * This program is free software; you can redistribute it and/or
011: * modify it under the terms of the GNU General Public License
012: * as published by the Free Software Foundation; either version 2
013: * of the License, or (at your option) any later version.
014: *
015: * This program is distributed in the hope that it will be useful,
016: * but WITHOUT ANY WARRANTY; without even the implied warranty of
017: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
018: * GNU General Public License for more details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with this program; if not, write to the Free Software
022: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
023: *
024: * For more information, contact:
025: *
026: * Integrated Systems Analysts, Inc.
027: * 630C Anchors St., Suite 101
028: * Fort Walton Beach, Florida
029: * USA
030: *
031: * (850)862-7321
032: */
033:
034: package org.openjump.core.ui.plugin.mousemenu;
035:
036: import java.util.ArrayList;
037: import java.util.Collection;
038: import java.util.Iterator;
039: import javax.swing.ImageIcon;
040: import javax.swing.JPopupMenu;
041: import com.vividsolutions.jts.geom.Coordinate;
042: import com.vividsolutions.jts.geom.CoordinateFilter;
043: import com.vividsolutions.jts.geom.Envelope;
044: import com.vividsolutions.jts.geom.Geometry;
045: import com.vividsolutions.jump.I18N;
046: import com.vividsolutions.jump.workbench.WorkbenchContext;
047: import com.vividsolutions.jump.workbench.model.Layer;
048: import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn;
049: import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory;
050: import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck;
051: import com.vividsolutions.jump.workbench.plugin.PlugInContext;
052: import com.vividsolutions.jump.workbench.ui.EditTransaction;
053: import com.vividsolutions.jump.workbench.ui.LayerViewPanel;
054: import com.vividsolutions.jump.workbench.ui.MultiInputDialog;
055: import com.vividsolutions.jump.workbench.ui.plugin.FeatureInstaller;
056:
057: public class RotatePlugIn extends AbstractPlugIn {
058:
059: private static final String sRotate = I18N
060: .get("org.openjump.core.ui.plugin.mousemenu.RotatePlugIn.Rotate");
061: private static final String sRotateSelectedFeatures = I18N
062: .get("org.openjump.core.ui.plugin.mousemenu.RotatePlugIn.Rotate-Selected-Features");
063: private static final String sRotateAbout = I18N
064: .get("org.openjump.core.ui.plugin.mousemenu.RotatePlugIn.Rotate-about");
065: private static final String sTheAngleInDegreesClockwise = I18N
066: .get("org.openjump.core.ui.plugin.mousemenu.RotatePlugIn.The-angle-in-degrees-clockwise");
067:
068: private static final String METHOD_ABOUTCENTER = I18N
069: .get("org.openjump.core.ui.plugin.mousemenu.RotatePlugIn.Center");
070: private static final String METHOD_ABOUTCLICKPOINT = I18N
071: .get("org.openjump.core.ui.plugin.mousemenu.RotatePlugIn.Click-Point");
072: private final static String ANGLE = I18N
073: .get("org.openjump.core.ui.plugin.mousemenu.RotatePlugIn.Rotation-Angle");
074: private final static String ROTATEABOUT = I18N
075: .get("org.openjump.core.ui.plugin.mousemenu.RotatePlugIn.Rotate-About");
076: private final double Deg2Rad = 0.0174532925199432; //pi/180
077: private WorkbenchContext workbenchContext;
078: private double rotateAngle = 45.0;
079: private double radiansAngle = 0.0;
080: private double cosAngle = 0.0;
081: private double sinAngle = 0.0;
082: private Coordinate rotationPoint = new Coordinate(0.0, 0.0);
083: private Collection methodNames = new ArrayList();
084: private String methodNameToRun = METHOD_ABOUTCENTER;
085:
086: public void initialize(PlugInContext context) throws Exception {
087: workbenchContext = context.getWorkbenchContext();
088: FeatureInstaller featureInstaller = new FeatureInstaller(
089: workbenchContext);
090: JPopupMenu popupMenu = LayerViewPanel.popupMenu();
091: featureInstaller.addPopupMenuItem(popupMenu, this , sRotate,
092: false, null, //to do: add icon
093: this .createEnableCheck(workbenchContext));
094: methodNames.add(METHOD_ABOUTCENTER);
095: methodNames.add(METHOD_ABOUTCLICKPOINT);
096: }
097:
098: public boolean execute(final PlugInContext context)
099: throws Exception {
100: final ArrayList transactions = new ArrayList();
101: reportNothingToUndoYet(context);
102: MultiInputDialog dialog = new MultiInputDialog(context
103: .getWorkbenchFrame(), getName(), true);
104: setDialogValues(dialog, context);
105: ///GUIUtil.centreOnWindow(dialog);
106: dialog.setVisible(true);
107: if (!dialog.wasOKPressed()) {
108: return false;
109: }
110: getDialogValues(dialog);
111:
112: workbenchContext = context.getWorkbenchContext();
113: Collection layers = workbenchContext.getLayerViewPanel()
114: .getSelectionManager().getLayersWithSelectedItems();
115: if (methodNameToRun.equals(METHOD_ABOUTCENTER)) {
116: //rotationPoint = getRotationPoint(layers);
117: Envelope en = new Envelope();
118: Collection geometries = context.getLayerViewPanel()
119: .getSelectionManager().getSelectedItems();
120: for (Iterator j = geometries.iterator(); j.hasNext();) {
121: Geometry geometry = (Geometry) j.next();
122: en.expandToInclude(geometry.getEnvelopeInternal());
123: }
124: rotationPoint.x = en.getMinX()
125: + (en.getMaxX() - en.getMinX()) / 2.0;
126: rotationPoint.y = en.getMinY()
127: + (en.getMaxY() - en.getMinY()) / 2.0;
128: } else if (methodNameToRun.equals(METHOD_ABOUTCLICKPOINT)) {
129: rotationPoint = context.getLayerViewPanel().getViewport()
130: .toModelCoordinate(
131: context.getLayerViewPanel()
132: .getLastClickedPoint());
133: }
134: radiansAngle = Deg2Rad * rotateAngle;
135: cosAngle = Math.cos(radiansAngle);
136: sinAngle = Math.sin(radiansAngle);
137:
138: for (Iterator i = layers.iterator(); i.hasNext();) {
139: Layer layerWithSelectedItems = (Layer) i.next();
140: transactions.add(createTransaction(layerWithSelectedItems));
141: }
142: EditTransaction.commit(transactions);
143: return true;
144: }
145:
146: private void setDialogValues(MultiInputDialog dialog,
147: PlugInContext context) {
148: dialog.setSideBarImage(new ImageIcon(getClass().getResource(
149: "Rotate.png")));
150: dialog.setSideBarDescription(sRotateSelectedFeatures);
151: dialog.addComboBox(ROTATEABOUT, methodNameToRun, methodNames,
152: sRotateAbout);
153: dialog.addDoubleField(ANGLE, rotateAngle, 6,
154: sTheAngleInDegreesClockwise);
155: }
156:
157: private void getDialogValues(MultiInputDialog dialog) {
158: //JComboBox combobox = dialog.getComboBox(ROTATEABOUT);
159: methodNameToRun = dialog.getText(ROTATEABOUT);
160: rotateAngle = dialog.getDouble(ANGLE);
161: }
162:
163: private EditTransaction createTransaction(Layer layer) {
164: EditTransaction transaction = EditTransaction
165: .createTransactionOnSelection(
166: new EditTransaction.SelectionEditor() {
167: public Geometry edit(
168: Geometry geometryWithSelectedItems,
169: Collection selectedItems) {
170: for (Iterator j = selectedItems
171: .iterator(); j.hasNext();) {
172: Geometry item = (Geometry) j.next();
173: rotate(item);
174: }
175: return geometryWithSelectedItems;
176: }
177: }, workbenchContext.getLayerViewPanel(),
178: workbenchContext.getLayerViewPanel()
179: .getContext(), getName(), layer, false,
180: false);// isRollingBackInvalidEdits(), false);
181: return transaction;
182: }
183:
184: //rotate geometry about rotationPoint by rotationAngle degrees (+ clockwise)
185: private void rotate(Geometry geometry) {
186: geometry.apply(new CoordinateFilter() {
187: public void filter(Coordinate coordinate) {
188: double x = coordinate.x - rotationPoint.x;
189: double y = coordinate.y - rotationPoint.y;
190: coordinate.x = rotationPoint.x + (x * cosAngle)
191: + (y * sinAngle);
192: coordinate.y = rotationPoint.y + (y * cosAngle)
193: - (x * sinAngle);
194: }
195: });
196: }
197:
198: public MultiEnableCheck createEnableCheck(
199: final WorkbenchContext workbenchContext) {
200: EnableCheckFactory checkFactory = new EnableCheckFactory(
201: workbenchContext);
202: return new MultiEnableCheck()
203: .add(
204: checkFactory
205: .createWindowWithLayerViewPanelMustBeActiveCheck())
206: .add(
207: checkFactory
208: .createAtLeastNFeaturesMustHaveSelectedItemsCheck(1))
209: .add(
210: checkFactory
211: .createSelectedItemsLayersMustBeEditableCheck());
212: }
213: }
|