package com.chemhack.jsMolEditor.client.listener; import com.google.gwt.user.client.ui.*; import com.chemhack.jsMolEditor.client.renderer.CordTransformer; import com.chemhack.jsMolEditor.client.controller.*; import com.chemhack.jsMolEditor.client.jre.emulation.java.awt.geom.Point2D; import com.chemhack.jsMolEditor.client.model.Atom; import com.chemhack.jsMolEditor.client.model.Bond; import com.chemhack.jsMolEditor.client.math.Vector2D; import java.util.Set; public class EditorMouseListener implements MouseListener, MouseWheelListener { private EditorController controller; enum MouseStatus { onAtom, onBond, onWhiteSpace } boolean isMouseDown = false; boolean isClick = false; Point2D lastCord = new Point2D(); Atom dragStartedAtom; MouseStatus mouseStatus = MouseStatus.onWhiteSpace; DrawBondModel drawBondModel = new DrawBondModel(); MoveAtomModel moveAtomModel = new MoveAtomModel(); DrawRingModel drawRingModel = new DrawRingModel(); public EditorMouseListener(EditorController controller) { this.controller = controller; } public void onMouseDown(Widget sender, int x, int y) { isMouseDown = true; isClick = true; if (mouseStatus == MouseStatus.onAtom || ((controller.currentAction == EditorController.EditActions.drawSingleBond || controller.currentAction == EditorController.EditActions.drawDoubleBond || controller.currentAction == EditorController.EditActions.drawTrippleBond) && mouseStatus == MouseStatus.onWhiteSpace)) { Atom mouseAtom = controller.getClosestAtom(new Point2D(x, y)); if (mouseAtom == null) { //Draw on blank canvas Point2D realCord = controller.graphCordToRealCord(new Point2D(x, y)); mouseAtom = controller.getMolecule().addAtom("C", realCord.x, realCord.y, 0); Set<Atom> highLightedAtoms = controller.getRenderer().getRendererModel().getHighlightedAtoms(); highLightedAtoms.clear(); highLightedAtoms.add(mouseAtom); mouseStatus = MouseStatus.onAtom; controller.refreshView(); } switch (controller.currentAction) { case drawSingleBond: drawBondModel.bondType = 1; drawBondModel.activated = true; drawBondModel.startAtom = mouseAtom; drawBondModel.newAtom = null; break; case drawDoubleBond: drawBondModel.bondType = 2; drawBondModel.activated = true; drawBondModel.startAtom = mouseAtom; drawBondModel.newAtom = null; break; case drawTrippleBond: drawBondModel.bondType = 3; drawBondModel.activated = true; drawBondModel.startAtom = mouseAtom; drawBondModel.newAtom = null; break; case drawRing: drawRingModel.ringSize = controller.currentRingSize; drawRingModel.activated = true; drawRingModel.startAtom = mouseAtom; drawRingModel.isBenzene = false; break; case drawBenzene: drawRingModel.ringSize = controller.currentRingSize; drawRingModel.activated = true; drawRingModel.startAtom = mouseAtom; drawRingModel.isBenzene = true; break; case eraser: break; case moveAtom: moveAtomModel.activated = true; moveAtomModel.moveAtom = mouseAtom; break; } } lastCord.setLocation(x, y); } public void onMouseUp(Widget sender, int x, int y) { isMouseDown = false; if (mouseStatus == MouseStatus.onBond) { Bond bond = controller.getClosestBond(new Point2D(x, y)); int bondType = bond.getType(); switch (controller.currentAction) { case drawSingleBond: if (bondType >= 2) bondType = 0; bond.setType(bondType + 1); break; case drawDoubleBond: bondType = bondType == 2 ? 1 : 2; bond.setType(bondType); break; case drawTrippleBond: bondType = bondType == 3 ? 1 : 3; bond.setType(bondType); break; case eraser: Atom source = bond.getSource(); Atom target = bond.getTarget(); controller.getMolecule().removeBond(bond); if (source.countNeighbors() == 0) controller.getMolecule().removeAtom(source); if (target.countNeighbors() == 0) controller.getMolecule().removeAtom(target); break; default: break; } controller.refreshView(); } else if (mouseStatus == MouseStatus.onAtom) { Atom currentAtom = controller.getClosestAtom(new Point2D(x, y)); switch (controller.currentAction) { case drawSingleBond: if (isClick) { Point2D newPoint = MoleculePlacer.calcNewAtomPlace(currentAtom, controller.getRenderer().getRendererModel().getDefaultBondLength()); Atom newAtom = controller.getMolecule().addAtom(controller.currentElement, newPoint.x, newPoint.y, 0); controller.getMolecule().connect(currentAtom, newAtom, 1); } break; case drawDoubleBond: if (isClick) { Point2D newPoint = MoleculePlacer.calcNewAtomPlace(currentAtom, controller.getRenderer().getRendererModel().getDefaultBondLength()); Atom newAtom = controller.getMolecule().addAtom(controller.currentElement, newPoint.x, newPoint.y, 0); controller.getMolecule().connect(currentAtom, newAtom, 2); } break; case drawTrippleBond: if (isClick) { Point2D newPoint = MoleculePlacer.calcNewAtomPlace(currentAtom, controller.getRenderer().getRendererModel().getDefaultBondLength()); Atom newAtom = controller.getMolecule().addAtom(controller.currentElement, newPoint.x, newPoint.y, 0); controller.getMolecule().connect(currentAtom, newAtom, 3); } break; case drawBenzene: case drawRing: if (isClick) { if(currentAtom.countNeighbors()==1){ MoleculePlacer.placeRingOnCurrentAtom(currentAtom, controller.getRenderer().getRendererModel().getDefaultBondLength(), drawRingModel.ringSize, drawRingModel.isBenzene,currentAtom.getNeighbors()[0]); }else{ Atom newAtom = MoleculePlacer.placeNewRing(currentAtom, controller.getRenderer().getRendererModel().getDefaultBondLength(), drawRingModel.ringSize, drawRingModel.isBenzene); controller.getMolecule().connect(currentAtom, newAtom, 1); } } break; case eraser: controller.getMolecule().removeAtom(currentAtom); break; case drawAtom: //Swtich atom currentAtom.setSymbol(controller.currentElement); break; default: break; } controller.refreshView(); } else if (mouseStatus == MouseStatus.onWhiteSpace) { switch (controller.currentAction) { case drawAtom: //Swtich atom if (isClick) { Point2D realCord = controller.graphCordToRealCord(new Point2D(x, y)); Atom newAtom = controller.getMolecule().addAtom(controller.currentElement, realCord.x, realCord.y, 0); } break; case drawBenzene: if (isClick) { Point2D realCord = controller.graphCordToRealCord(new Point2D(x, y)); Atom newAtom = controller.getMolecule().addAtom("C", realCord.x, realCord.y, 0); MoleculePlacer.placeRingOnCurrentAtom(newAtom, controller.getRenderer().getRendererModel().getDefaultBondLength(), controller.currentRingSize, true); } break; case drawRing: if (isClick) { Point2D realCord = controller.graphCordToRealCord(new Point2D(x, y)); Atom newAtom = controller.getMolecule().addAtom("C", realCord.x, realCord.y, 0); MoleculePlacer.placeRingOnCurrentAtom(newAtom, controller.getRenderer().getRendererModel().getDefaultBondLength(), controller.currentRingSize, false); } break; default: break; } controller.refreshView(); } if (drawBondModel.activated) { drawNewBondTo(x, y, false); drawBondModel.activated = false; } // if (moveAtomModel.activated) { // moveAtomModel.activated = false; // } } public void onMouseEnter(Widget sender) { mouseStatus = MouseStatus.onWhiteSpace; isMouseDown = false; } public void onMouseLeave(Widget sender) { mouseStatus = MouseStatus.onWhiteSpace; } public void onMouseMove(Widget sender, int x, int y) { if (isMouseDown) isClick = false; //process dragging the view if (isMouseDown && mouseStatus == MouseStatus.onWhiteSpace) { CordTransformer cordTransformer = controller.getRenderer().getTransformer(); cordTransformer.translate((x - lastCord.getX()) / cordTransformer.getScaleX(), (y - lastCord.getY()) / cordTransformer.getScaleY()); lastCord.setLocation(x, y); controller.refreshView(); return; } //process bond drawing if (isMouseDown && drawBondModel.activated) { drawNewBondTo(x, y, true); return; } if (isMouseDown && moveAtomModel.activated) { Point2D realCord = controller.graphCordToRealCord(new Point2D(x, y)); moveAtomModel.moveAtom.move(realCord.getX(), realCord.getY(), 0); controller.refreshView(); return; } //process normal move processNormalMove(x, y); } private void processNormalMove(int x, int y) { Atom atom = controller.getClosestAtom(new Point2D(x, y)); Set<Atom> atoms = controller.getRenderer().getRendererModel().getHighlightedAtoms(); Bond bond = controller.getClosestBond(new Point2D(x, y)); Set<Bond> bonds = controller.getRenderer().getRendererModel().getHighlightedBonds(); boolean needRefresh = atoms.size() > 0 || bonds.size() > 0; //indicates if necessary to refreh view mouseStatus = MouseStatus.onWhiteSpace; atoms.clear(); bonds.clear(); if (atom != null) { atoms.add(atom); mouseStatus = MouseStatus.onAtom; controller.refreshView(); return; } if (bond != null) { bonds.add(bond); mouseStatus = MouseStatus.onBond; controller.refreshView(); return; } if (needRefresh) { controller.refreshView(); } } private void drawNewBondTo(int x, int y, boolean isPreview) { Atom mouseAtom = controller.getClosestAtom(new Point2D(x, y)); if (mouseAtom != drawBondModel.startAtom) { if (mouseAtom != null) { if (mouseAtom != drawBondModel.newAtom) { if (drawBondModel.newAtom != null) { controller.getMolecule().removeAtom(drawBondModel.newAtom); drawBondModel.newAtom = null; } controller.getRenderer().getRendererModel().getHighlightedAtoms().add(mouseAtom); Bond bond1 = controller.getMolecule().getBond(drawBondModel.startAtom, mouseAtom); Bond bond2 = controller.getMolecule().getBond(mouseAtom, drawBondModel.startAtom); Bond oldBond = bond1 == null ? (bond2 == null ? null : bond2) : bond1; if (oldBond != null) { oldBond.setType(oldBond.getType() + 1); controller.refreshView(); if (isPreview) oldBond.setType(oldBond.getType() - 1); } else { Bond bond = controller.getMolecule().connect(drawBondModel.startAtom, mouseAtom, drawBondModel.bondType); controller.refreshView(); controller.getRenderer().getRendererModel().getHighlightedAtoms().remove(mouseAtom); if (isPreview) controller.getMolecule().removeBond(bond); } } else { Point2D worldCord = controller.graphCordToRealCord(new Point2D(x, y)); Vector2D bondVector = new Vector2D(worldCord.x - drawBondModel.startAtom.getX(), worldCord.y - drawBondModel.startAtom.getY()); bondVector.setLength(controller.getRenderer().getRendererModel().getDefaultBondLength()); drawBondModel.newAtom.move(drawBondModel.startAtom.getX() + bondVector.x, drawBondModel.startAtom.getY() + bondVector.y, 0); controller.refreshView(); } } else { if (drawBondModel.newAtom == null) { drawBondModel.newAtom = controller.getMolecule().addAtom(controller.currentElement); controller.getMolecule().connect(drawBondModel.startAtom, drawBondModel.newAtom, drawBondModel.bondType); } Point2D worldCord = controller.graphCordToRealCord(new Point2D(x, y)); Vector2D bondVector = new Vector2D(worldCord.x - drawBondModel.startAtom.getX(), worldCord.y - drawBondModel.startAtom.getY()); bondVector.setLength(controller.getRenderer().getRendererModel().getDefaultBondLength()); drawBondModel.newAtom.move(drawBondModel.startAtom.getX() + bondVector.x, drawBondModel.startAtom.getY() + bondVector.y, 0); controller.refreshView(); } } } public void onMouseWheel(Widget sender, MouseWheelVelocity velocity) { // CordTransformer cordTransformer = controller.getRenderer().getTransformer(); // cordTransformer.scale(cordTransformer.getScaleX()*(1 + velocity.getDeltaY() / 1000d), cordTransformer.getScaleY()*(1 + velocity.getDeltaY() / 1000d)); // controller.refreshView(); controller.getRenderer().getRendererModel().setZoomFactor(controller.getRenderer().getRendererModel().getZoomFactor() * (1 + velocity.getDeltaY() / 1000d)); controller.refreshView(); // System.out.println(cordTransformer.getScaleX()*(1 + velocity.getDeltaY() / 1000d)); } }