📄 abstractcontroller2d.java
字号:
/* $Revision: 8753 $ $Author: shk3 $ $Date: 2007-08-28 23:40:30 +0200 (Tue, 28 Aug 2007) $ * * Copyright (C) 2005-2007 Christoph Steinbeck <steinbeck@users.sf.net> * * Contact: cdk-devel@lists.sourceforge.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * All I ask is that proper credit is given for my work, which includes * - but is not limited to - adding the above copyright notice to the beginning * of your source code files, and to any copyright notice that you may distribute * with programs based on this work. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */package org.openscience.cdk.controller;import java.awt.BorderLayout;import java.awt.Color;import java.awt.Component;import java.awt.Container;import java.awt.Dimension;import java.awt.Frame;import java.awt.Point;import java.awt.Polygon;import java.awt.Shape;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.MouseMotionListener;import java.awt.geom.AffineTransform;import java.awt.geom.PathIterator;import java.util.ArrayList;import java.util.EventObject;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Vector;import javax.swing.BorderFactory;import javax.swing.Box;import javax.swing.BoxLayout;import javax.swing.JButton;import javax.swing.JComboBox;import javax.swing.JDialog;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.undo.UndoableEdit;import javax.vecmath.Point2d;import javax.vecmath.Vector2d;import org.openscience.cdk.CDKConstants;import org.openscience.cdk.applications.undoredo.AddAtomsAndBondsEdit;import org.openscience.cdk.applications.undoredo.AddFuncGroupEdit;import org.openscience.cdk.applications.undoredo.AdjustBondOrdersEdit;import org.openscience.cdk.applications.undoredo.ChangeAtomSymbolEdit;import org.openscience.cdk.applications.undoredo.ChangeChargeEdit;import org.openscience.cdk.applications.undoredo.IUndoRedoHandler;import org.openscience.cdk.applications.undoredo.MergeMoleculesEdit;import org.openscience.cdk.applications.undoredo.MoveAtomEdit;import org.openscience.cdk.applications.undoredo.RemoveAtomsAndBondsEdit;import org.openscience.cdk.config.IsotopeFactory;import org.openscience.cdk.event.ICDKChangeListener;import org.openscience.cdk.geometry.BondTools;import org.openscience.cdk.geometry.GeometryTools;import org.openscience.cdk.graph.ConnectivityChecker;import org.openscience.cdk.interfaces.IAtom;import org.openscience.cdk.interfaces.IAtomContainer;import org.openscience.cdk.interfaces.IBond;import org.openscience.cdk.interfaces.IChemModel;import org.openscience.cdk.interfaces.IChemObject;import org.openscience.cdk.interfaces.IElectronContainer;import org.openscience.cdk.interfaces.IIsotope;import org.openscience.cdk.interfaces.IMapping;import org.openscience.cdk.interfaces.IMolecule;import org.openscience.cdk.interfaces.IMoleculeSet;import org.openscience.cdk.interfaces.IReaction;import org.openscience.cdk.interfaces.IRing;import org.openscience.cdk.layout.AtomPlacer;import org.openscience.cdk.layout.RingPlacer;import org.openscience.cdk.renderer.Renderer2DModel;import org.openscience.cdk.tools.HydrogenAdder;import org.openscience.cdk.tools.LoggingTool;import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;import org.openscience.cdk.tools.manipulator.ChemModelManipulator;/** * Class that acts on MouseEvents and KeyEvents. * * @author steinbeck * @author egonw * @cdk.created 2005-05-02 * @cdk.keyword mouse events * @cdk.require java1.4+ * @cdk.module control * @cdk.bug 1562511 */abstract class AbstractController2D implements MouseMotionListener, MouseListener, KeyListener{ private final static int DRAG_UNSET = 0; private final static int DRAG_MOVING_SELECTED = 1; private final static int DRAG_DRAWING_PROPOSED_BOND = 2; private final static int DRAG_DRAWING_PROPOSED_RING = 3; private final static int DRAG_MAKING_SQUARE_SELECTION = 4; private final static int DRAG_MAKING_LASSO_SELECTION = 5; private final static int DRAG_DRAWING_PROPOSED_ATOMATOMMAP = 6; private final static int DRAG_ROTATE = 7; protected Vector lastAction=null; protected JButton moveButton=null; protected IChemModel chemModel; Renderer2DModel r2dm; Controller2DModel c2dm; boolean wasDragged = false; boolean isUndoableChange = false; private Vector listeners = new Vector(); private LoggingTool logger; private int prevDragCoordX = 0; private int prevDragCoordY = 0; private boolean draggingSelected = true; private int dragMode = DRAG_UNSET; private Vector commonElements; private HashMap currentCommonElement = new HashMap(); IAtom lastAtomInRange = null; private double shiftX = 0; private double shiftY = 0; double moveoldX; double moveoldY; private IUndoRedoHandler undoRedoHandler; private HashMap funcgroupsmap=new HashMap(); // Helper classes HydrogenAdder hydrogenAdder = new HydrogenAdder("org.openscience.cdk.tools.ValencyChecker"); AbstractController2D() { logger = new LoggingTool(this); } AbstractController2D(Controller2DModel c2dm) { this(); this.c2dm = c2dm; commonElements = new Vector(); String[] elements = c2dm.getCommonElements(); for (int i = 0; i < elements.length; i++) { commonElements.add(elements[i]); } } AbstractController2D(Renderer2DModel r2dm, Controller2DModel c2dm) { this(c2dm); this.r2dm = r2dm; } /** * Gets the controller2DModel attribute of the Controller2D object * *@return The controller2DModel value */ public Controller2DModel getController2DModel() { return c2dm; } /** * Gets the undoableChange attribute of the Controller2D object * *@return The undoableChange value */ public boolean isUndoableChange() { return isUndoableChange; } /** * Sets the undoableChange attribute of the Controller2D object * *@param isUndoable The new undoableChange value */ public void setUndoableChange(boolean isUndoable) { this.isUndoableChange = isUndoable; } /** * Sets the controller2DModel attribute of the Controller2D object * *@param model The new controller2DModel value */ public void setController2DModel(Controller2DModel model) { this.c2dm = model; } /** * Manages all actions that will be invoked when the mouse is moved. * *@param event MouseEvent object */ public void mouseMoved(MouseEvent event) { int[] screenCoords = {event.getX(), event.getY()}; int[] mouseCoords = getWorldCoordinates(screenCoords); int mouseX = mouseCoords[0]; int mouseY = mouseCoords[1]; highlightNearestChemObject(mouseX, mouseY); //this is the rotate feature if(c2dm.isMovingAllowed() && r2dm.getSelectedPart()!=null && r2dm.getHighlightedAtom()==null && r2dm.getHighlightedBond()==null && c2dm.getDrawMode() == Controller2DModel.LASSO){ double xmin=Double.MAX_VALUE; double xmax=Double.MIN_VALUE; double ymin=Double.MAX_VALUE; double ymax=Double.MIN_VALUE; for(int i=0;i<r2dm.getSelectedPart().getAtomCount();i++){ if(((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).x>xmax) xmax=((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).x; if(((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).y>ymax) ymax=((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).y; if(((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).x<xmin) xmin=((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).x; if(((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).y<ymin) ymin=((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).y; } if(mouseCoords[0]>xmin && mouseCoords[0]<xmax && mouseCoords[1]>ymin && mouseCoords[1]<ymax){ //ok, we want to rotate r2dm.setRotateCenter(xmin+(xmax-xmin)/2,ymin+(ymax-ymin)/2); r2dm.setRotateRadius(Math.min((xmax-xmin)/4,(ymax-ymin)/4)); } }else{ //no rotation r2dm.setRotateRadius(0); } } /** * Manages all actions that will be invoked when the mouse is dragged. * *@param event MouseEvent object */ public void mouseDragged(MouseEvent event) { isUndoableChange = false; logger.debug("MouseDragged Event Props: mode=", c2dm.getDrawModeString()); if (logger.isDebugEnabled()) { logger.debug(" trigger=" + event.isPopupTrigger() + /* * ", Button number: " + event.getButton() + */ ", Click count: " + event.getClickCount()); } int[] screenCoords = {event.getX(), event.getY()}; int[] mouseCoords = getWorldCoordinates(screenCoords); int mouseX = mouseCoords[0]; int mouseY = mouseCoords[1]; if (!wasDragged) { prevDragCoordX = mouseX; prevDragCoordY = mouseY; wasDragged = true; } if (dragMode == DRAG_DRAWING_PROPOSED_BOND) { int startX = r2dm.getPointerVectorStart().x; int startY = r2dm.getPointerVectorStart().y; highlightNearestChemObject(mouseX, mouseY); drawProposedBond(startX, startY, mouseX, mouseY); } else if (dragMode == DRAG_MAKING_SQUARE_SELECTION) { int startX = r2dm.getPointerVectorStart().x; int startY = r2dm.getPointerVectorStart().y; selectRectangularArea(startX, startY, mouseX, mouseY); } else if (dragMode == DRAG_DRAWING_PROPOSED_RING) { int endX = 0; int endY = 0; double angle = 0; double pointerVectorLength = c2dm.getRingPointerLength(); Point2d center = GeometryTools.get2DCenter(getHighlighted(),r2dm.getRenderingCoordinates()); r2dm.setPointerVectorStart(new Point((int) center.x, (int) center.y)); angle = GeometryTools.getAngle(center.x - mouseX, center.y - mouseY); endX = (int) center.x - (int) (Math.cos(angle) * pointerVectorLength); endY = (int) center.y - (int) (Math.sin(angle) * pointerVectorLength); r2dm.setPointerVectorEnd(new Point(endX, endY)); } else if (dragMode == DRAG_MAKING_LASSO_SELECTION) { /* * Draw polygon in screencoordinates, convert them * to world coordinates when mouse released */ r2dm.addLassoPoint(new Point(event.getX(), event.getY())); } else if (dragMode == DRAG_MOVING_SELECTED) { // all these are in model coordinates logger.debug("Dragging selected atoms"); int deltaX = mouseX - prevDragCoordX; int deltaY = mouseY - prevDragCoordY; moveSelectedAtomsWith(deltaX, deltaY); IAtomContainer selected=r2dm.getSelectedPart(); r2dm.getMerge().clear(); for(int i=0;i<selected.getAtomCount();i++){ IAtom inrange=getAtomInRange((int)((Point2d)r2dm.getRenderingCoordinate(selected.getAtom(i))).x, (int)((Point2d)r2dm.getRenderingCoordinate(selected.getAtom(i))).y, selected.getAtom(i)); if(inrange!=null && inrange!=selected.getAtom(i)){ r2dm.getMerge().put(selected.getAtom(i),inrange); } } /* * PRESERVE THIS. This notifies the * the listener responsible for * undo and redo storage that it * should not store this change */ isUndoableChange = false; fireChange(); } else if(dragMode==DRAG_ROTATE){ double angle=BondTools.giveAngleBothMethods(new Point2d(r2dm.getRotateCenter()[0],r2dm.getRotateCenter()[1]),new Point2d(prevDragCoordX,prevDragCoordY),new Point2d(mouseX, mouseY),true); Polygon polygon=new Polygon(); for(int i=0;i<r2dm.getSelectedPart().getAtomCount();i++) { polygon.addPoint((int)(((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).x*1000),(int)(((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(i))).y*1000)); } polygon.addPoint((int)(((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(0))).x*1000),(int)(((Point2d)r2dm.getRenderingCoordinate(r2dm.getSelectedPart().getAtom(0))).y*1000)); AffineTransform at=AffineTransform.getRotateInstance(angle,r2dm.getRotateCenter()[0]*1000,r2dm.getRotateCenter()[1]*1000); Shape transformedpolygon=at.createTransformedShape(polygon); PathIterator pa=transformedpolygon.getPathIterator(null); for(int i=0;i<r2dm.getSelectedPart().getAtomCount();i++) { double[] d=new double[6]; pa.currentSegment(d); r2dm.setRenderingCoordinate(r2dm.getSelectedPart().getAtom(i),new Point2d(d[0]/1000,d[1]/1000)); pa.next(); } fireChange();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -