/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.fge.controller;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openflexo.fge.ConnectorGraphicalRepresentation;
import org.openflexo.fge.DefaultDrawing;
import org.openflexo.fge.Drawing;
import org.openflexo.fge.DrawingGraphicalRepresentation;
import org.openflexo.fge.FGEConstants;
import org.openflexo.fge.GraphicalRepresentation;
import org.openflexo.fge.ShapeGraphicalRepresentation;
import org.openflexo.fge.ShapeGraphicalRepresentation.LocationConstraints;
import org.openflexo.fge.cp.ConnectorAdjustingControlPoint;
import org.openflexo.fge.cp.ControlArea;
import org.openflexo.fge.cp.ControlPoint;
import org.openflexo.fge.geom.FGEPoint;
import org.openflexo.fge.graphics.BackgroundStyle;
import org.openflexo.fge.graphics.ForegroundStyle;
import org.openflexo.fge.graphics.ShadowStyle;
import org.openflexo.fge.graphics.TextStyle;
import org.openflexo.fge.notifications.GraphicalObjectsHierarchyRebuildEnded;
import org.openflexo.fge.notifications.GraphicalObjectsHierarchyRebuildStarted;
import org.openflexo.fge.shapes.Shape;
import org.openflexo.fge.shapes.Shape.ShapeType;
import org.openflexo.fge.view.ConnectorView;
import org.openflexo.fge.view.DrawingView;
import org.openflexo.fge.view.FGEPaintManager;
import org.openflexo.fge.view.LabelView;
import org.openflexo.fge.view.ShapeView;
public class DrawingController<D extends Drawing<?>> extends Observable implements Observer {
private static final Logger logger = Logger.getLogger(DrawingController.class.getPackage().getName());
private D drawing;
private DrawingView<D> drawingView;
public enum EditorTool {
SelectionTool, DrawShapeTool, DrawConnectorTool, DrawTextTool
}
private EditorTool currentTool;
private DrawShapeToolController<?> drawShapeToolController;
private DrawShapeAction drawShapeAction;
private ForegroundStyle currentForegroundStyle;
private BackgroundStyle currentBackgroundStyle;
private TextStyle currentTextStyle;
private ShadowStyle currentShadowStyle;
private Shape currentShape;
private ScalePanel _scalePanel;
private EditorToolbox toolbox;
private GraphicalRepresentation<?> focusedFloatingLabel;
// private GraphicalRepresentation focusedObject;
private Vector<GraphicalRepresentation<?>> focusedObjects;
private Vector<GraphicalRepresentation<?>> selectedObjects;
private LabelView<?> _currentlyEditedLabel;
private ControlArea<?> focusedControlArea;
private double scale = 1.0;
private Vector<DrawingPalette> palettes;
private FGEPoint lastClickedPoint;
private GraphicalRepresentation<?> lastSelectedGR;
public DrawingController(D aDrawing) {
super();
setCurrentTool(EditorTool.SelectionTool);
currentForegroundStyle = ForegroundStyle.makeDefault();
currentBackgroundStyle = BackgroundStyle.makeColoredBackground(FGEConstants.DEFAULT_BACKGROUND_COLOR);
currentTextStyle = TextStyle.makeDefault();
currentShadowStyle = ShadowStyle.makeDefault();
currentShape = Shape.makeShape(ShapeType.RECTANGLE, null);
toolbox = new EditorToolbox(this);
drawing = aDrawing;
if (drawing instanceof DefaultDrawing<?>) {
((DefaultDrawing<?>) drawing).addObserver(this);
}
focusedObjects = new Vector<GraphicalRepresentation<?>>();
selectedObjects = new Vector<GraphicalRepresentation<?>>();
palettes = new Vector<DrawingPalette>();
_buildDrawingView();
if (logger.isLoggable(Level.FINE)) {
logger.fine("Building DrawingController: " + this);
}
}
public DrawingView<D> rebuildDrawingView() {
if (drawingView != null) {
drawingView.delete();
}
_buildDrawingView();
return drawingView;
}
private DrawingView<D> _buildDrawingView() {
drawingView = makeDrawingView(drawing);
if (drawing.getContainedObjects(drawing.getModel()) != null) {
for (Object o : drawing.getContainedObjects(drawing.getModel())) {
GraphicalRepresentation<?> gr = drawing.getGraphicalRepresentation(o);
if (gr instanceof ShapeGraphicalRepresentation && gr.isValidated()) {
ShapeView<?> v = _buildShapeView((ShapeGraphicalRepresentation<?>) gr);
drawingView.add(v);
} else if (gr instanceof ConnectorGraphicalRepresentation && gr.isValidated()) {
ConnectorGraphicalRepresentation<?> connectorGR = (ConnectorGraphicalRepresentation<?>) gr;
ConnectorView<?> v = connectorGR.makeConnectorView(this);
drawingView.add(v);
}
if (!gr.isValidated()) {
logger.warning("DrawingView " + drawingView.getClass().getSimpleName() + " unvalidated GR found " + gr);
}
}
}
return drawingView;
}
private <O> ShapeView<O> _buildShapeView(ShapeGraphicalRepresentation<O> shapedGR) {
ShapeView<O> returned = shapedGR.makeShapeView(this);
if (shapedGR.getContainedObjects() != null) {
for (Object o : shapedGR.getContainedObjects()) {
GraphicalRepresentation<?> gr = shapedGR.getDrawing().getGraphicalRepresentation(o);
if (gr instanceof ShapeGraphicalRepresentation) {
ShapeView<?> v = _buildShapeView((ShapeGraphicalRepresentation<?>) gr);
returned.add(v);
} else if (gr instanceof ConnectorGraphicalRepresentation) {
ConnectorGraphicalRepresentation<?> connectorGR = (ConnectorGraphicalRepresentation<?>) gr;
ConnectorView<?> v = connectorGR.makeConnectorView(this);
returned.add(v);
}
}
}
return returned;
}
// Override for a custom view
public DrawingView<D> makeDrawingView(D drawing) {
return new DrawingView<D>(drawing, this);
}
public DrawShapeToolController<?> getDrawShapeToolController() {
return drawShapeToolController;
}
public EditorTool getCurrentTool() {
return currentTool;
}
public void setCurrentTool(EditorTool aTool) {
if (aTool != currentTool) {
logger.fine("Switch to tool " + aTool);
switch (aTool) {
case SelectionTool:
/*if (currentTool == EditorTool.DrawShapeTool && drawShapeToolController != null) {
drawShapeToolController.makeNewShape();
}*/
break;
case DrawShapeTool:
// if (drawShapeAction != null) {
drawShapeToolController = new DrawPolygonToolController(this, drawShapeAction);
// }
break;
case DrawConnectorTool:
break;
case DrawTextTool:
break;
default:
break;
}
currentTool = aTool;
if (getToolbox() != null) {
getToolbox().getToolPanel().updateButtons();
}
if (getPaintManager() != null) {
getPaintManager().repaint(getDrawingView());
}
}
}
public ForegroundStyle getCurrentForegroundStyle() {
return currentForegroundStyle;
}
public void setCurrentForegroundStyle(ForegroundStyle currentForegroundStyle) {
this.currentForegroundStyle = currentForegroundStyle;
}
public BackgroundStyle getCurrentBackgroundStyle() {
return currentBackgroundStyle;
}
public void setCurrentBackgroundStyle(BackgroundStyle currentBackgroundStyle) {
this.currentBackgroundStyle = currentBackgroundStyle;
}
public TextStyle getCurrentTextStyle() {
return currentTextStyle;
}
public void setCurrentTextStyle(TextStyle currentTextStyle) {
this.currentTextStyle = currentTextStyle;
}
public ShadowStyle getCurrentShadowStyle() {
return currentShadowStyle;
}
public void setCurrentShadowStyle(ShadowStyle currentShadowStyle) {
this.currentShadowStyle = currentShadowStyle;
}
public Shape getCurrentShape() {
return currentShape;
}
public void setCurrentShape(Shape currentShape) {
this.currentShape = currentShape;
}
public double getScale() {
return scale;
}
public void setScale(double aScale) {
if (aScale < 0) {
return;
}
scale = aScale;
if (_scalePanel != null) {
_scalePanel.slider.setValue((int) (aScale * 100));
}
drawingView.rescale();
}
public DrawShapeAction getDrawShapeAction() {
return drawShapeAction;
}
public void setDrawShapeAction(DrawShapeAction drawShapeAction) {
this.drawShapeAction = drawShapeAction;
}
public EditorToolbox getToolbox() {
return toolbox;
}
public ScalePanel getScalePanel() {
if (_scalePanel == null) {
_scalePanel = new ScalePanel();
}
return _scalePanel;
}
public class ScalePanel extends JToolBar {
private static final int MAX_ZOOM_VALUE = 300;
protected JTextField scaleTF;
protected JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 500, 100);
protected ChangeListener sliderChangeListener;
protected ActionListener actionListener;
protected ScalePanel() {
super(/* new FlowLayout(FlowLayout.LEFT, 10, 0) */);
setOpaque(false);
scaleTF = new JTextField(5);
int currentScale = (int) (getScale() * 100);
scaleTF.setText(currentScale + "%");
slider = new JSlider(SwingConstants.HORIZONTAL, 0, MAX_ZOOM_VALUE, currentScale);
slider.setOpaque(false);
slider.setMajorTickSpacing(100);
slider.setMinorTickSpacing(20);
slider.setPaintTicks(false/* true */);
slider.setPaintLabels(false);
slider.setBorder(BorderFactory.createEmptyBorder());
sliderChangeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (slider.getValue() > 0) {
setScale((double) slider.getValue() / 100);
scaleTF.removeActionListener(actionListener);
scaleTF.setText("" + (int) (getScale() * 100) + "%");
scaleTF.addActionListener(actionListener);
}
}
};
actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
// logger.info("On fait avec "+scaleTF.getText()+" ce qui donne: "+(((double)Integer.decode(scaleTF.getText()))/100));
Integer newScale = null;
if (scaleTF.getText().indexOf("%") > -1) {
newScale = Integer.decode(scaleTF.getText().substring(0, scaleTF.getText().indexOf("%")));
} else {
newScale = Integer.decode(scaleTF.getText());
}
if (newScale > MAX_ZOOM_VALUE) {
newScale = MAX_ZOOM_VALUE;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
scaleTF.setText(MAX_ZOOM_VALUE + "%");
}
});
}
setScale((double) newScale / 100);
} catch (NumberFormatException exception) {
// Forget
}
scaleTF.removeActionListener(actionListener);
slider.removeChangeListener(sliderChangeListener);
scaleTF.setText("" + (int) (getScale() * 100) + "%");
slider.setValue((int) (getScale() * 100));
slider.addChangeListener(sliderChangeListener);
scaleTF.addActionListener(actionListener);
}
};
scaleTF.addActionListener(actionListener);
slider.addChangeListener(sliderChangeListener);
add(slider);
add(scaleTF);
// setBorder(BorderFactory.createEmptyBorder());
}
}
public D getDrawing() {
return drawing;
}
public DrawingGraphicalRepresentation<?> getDrawingGraphicalRepresentation() {
return drawing.getDrawingGraphicalRepresentation();
}
public DrawingView<D> getDrawingView() {
return drawingView;
}
public <O> GraphicalRepresentation<O> getGraphicalRepresentation(O drawable) {
if (drawable == null) {
return null;
}
return drawing.getGraphicalRepresentation(drawable);
}
public GraphicalRepresentation<?> getFocusedFloatingLabel() {
return focusedFloatingLabel;
}
public void setFocusedFloatingLabel(GraphicalRepresentation<?> aFocusedlabel) {
// logger.info("setFocusedFloatingLabel() with "+aFocusedlabel);
if (focusedFloatingLabel == null) {
if (aFocusedlabel == null) {
return;
} else {
focusedFloatingLabel = aFocusedlabel;
if (getPaintManager().isPaintingCacheEnabled()) {
// Just repaint connector
drawingView.getPaintManager().repaint(focusedFloatingLabel);
} else {
// @brutal mode
drawingView.getPaintManager().repaint(drawingView);
}
}
} else {
GraphicalRepresentation<?> oldFocusedFloatingLabel = focusedFloatingLabel;
focusedFloatingLabel = aFocusedlabel;
if (aFocusedlabel == null || focusedFloatingLabel != aFocusedlabel) {
if (getPaintManager().isPaintingCacheEnabled()) {
// Just repaint old and eventual new connector
drawingView.getPaintManager().repaint(oldFocusedFloatingLabel);
if (aFocusedlabel != null) {
drawingView.getPaintManager().repaint(focusedFloatingLabel);
}
} else {
// @brutal mode
drawingView.getPaintManager().repaint(drawingView);
}
}
/*
* if (aFocusedlabel == null) { focusedFloatingLabel = null;
* drawingView.getPaintManager().repaint(drawingView); } else if
* (focusedFloatingLabel != aFocusedlabel) { focusedFloatingLabel =
* aFocusedlabel;
* drawingView.getPaintManager().repaint(drawingView); }
*/
}
}
private ShapeGraphicalRepresentation<?> getFirstSelectedShape() {
for (GraphicalRepresentation<?> gr : getSelectedObjects()) {
if (gr instanceof ShapeGraphicalRepresentation) {
return (ShapeGraphicalRepresentation<?>) gr;
}
}
return null;
}
public List<GraphicalRepresentation<?>> getSelectedObjects() {
return selectedObjects;
}
public void setSelectedObjects(List<? extends GraphicalRepresentation<?>> someSelectedObjects) {
stopEditionOfEditedLabelIfAny();
if (someSelectedObjects == null) {
setSelectedObjects(new ArrayList<GraphicalRepresentation<?>>());
return;
}
if (!selectedObjects.equals(someSelectedObjects)) {
clearSelection();
for (GraphicalRepresentation<?> d : someSelectedObjects) {
addToSelectedObjects(d);
}
}
}
public void setSelectedObject(GraphicalRepresentation<?> aGraphicalRepresentation) {
stopEditionOfEditedLabelIfAny();
setSelectedObjects(Collections.singletonList(aGraphicalRepresentation));
if (getToolbox() != null) {
getToolbox().update();
}
}
public void addToSelectedObjects(GraphicalRepresentation<?> aGraphicalRepresentation) {
stopEditionOfEditedLabelIfAny();
if (aGraphicalRepresentation == null) {
logger.warning("Cannot add null object");
return;
}
if (!selectedObjects.contains(aGraphicalRepresentation)) {
selectedObjects.add(aGraphicalRepresentation);
aGraphicalRepresentation.setIsSelected(true);
}
getToolbox().update();
}
public void removeFromSelectedObjects(GraphicalRepresentation<?> aGraphicalRepresentation) {
stopEditionOfEditedLabelIfAny();
if (aGraphicalRepresentation == null) {
logger.warning("Cannot remove null object");
return;
}
if (selectedObjects.contains(aGraphicalRepresentation)) {
selectedObjects.remove(aGraphicalRepresentation);
}
aGraphicalRepresentation.setIsSelected(false);
getToolbox().update();
}
public void toggleSelection(GraphicalRepresentation<?> aGraphicalRepresentation) {
// logger.info("BEGIN toggle selection with "+aGraphicalRepresentation+" with selection="+selectedObjects);
stopEditionOfEditedLabelIfAny();
if (aGraphicalRepresentation.getIsSelected()) {
removeFromSelectedObjects(aGraphicalRepresentation);
} else {
addToSelectedObjects(aGraphicalRepresentation);
}
// logger.info("END toggle selection with "+aGraphicalRepresentation+" with selection="+selectedObjects);
}
public void clearSelection() {
// logger.info("Clear selection");
stopEditionOfEditedLabelIfAny();
for (GraphicalRepresentation<?> gr : selectedObjects) {
gr.setIsSelected(false);
}
selectedObjects.clear();
}
public Vector<GraphicalRepresentation<?>> getFocusedObjects() {
return focusedObjects;
}
public void setFocusedObjects(List<? extends GraphicalRepresentation<?>> someFocusedObjects) {
if (someFocusedObjects == null) {
setFocusedObjects(Collections.<GraphicalRepresentation<?>> emptyList());
return;
}
if (!focusedObjects.equals(someFocusedObjects)) {
clearFocusSelection();
for (GraphicalRepresentation<?> d : someFocusedObjects) {
addToFocusedObjects(d);
}
}
}
public void setFocusedObject(GraphicalRepresentation<?> aGraphicalRepresentation) {
if (aGraphicalRepresentation == null) {
clearFocusSelection();
return;
}
setFocusedObjects(Collections.singletonList(aGraphicalRepresentation));
}
public void addToFocusedObjects(GraphicalRepresentation<?> aGraphicalRepresentation) {
if (aGraphicalRepresentation == null) {
logger.warning("Cannot add null object");
return;
}
if (!focusedObjects.contains(aGraphicalRepresentation)) {
focusedObjects.add(aGraphicalRepresentation);
aGraphicalRepresentation.setIsFocused(true);
}
}
public void removeFromFocusedObjects(GraphicalRepresentation<?> aGraphicalRepresentation) {
if (aGraphicalRepresentation == null) {
logger.warning("Cannot remove null object");
return;
}
if (focusedObjects.contains(aGraphicalRepresentation)) {
focusedObjects.remove(aGraphicalRepresentation);
}
aGraphicalRepresentation.setIsFocused(false);
}
public void toggleFocusSelection(GraphicalRepresentation<?> aGraphicalRepresentation) {
if (aGraphicalRepresentation.getIsFocused()) {
removeFromFocusedObjects(aGraphicalRepresentation);
} else {
addToFocusedObjects(aGraphicalRepresentation);
}
}
public void clearFocusSelection() {
// stopEditionOfEditedLabelIfAny();
for (GraphicalRepresentation<?> gr : focusedObjects) {
gr.setIsFocused(false);
}
focusedObjects.clear();
}
public void selectDrawing() {
stopEditionOfEditedLabelIfAny();
// Override when required
}
public void setEditedLabel(LabelView<?> aLabel) {
stopEditionOfEditedLabelIfAny();
_currentlyEditedLabel = aLabel;
}
public void resetEditedLabel(LabelView<?> editedLabel) {
if (_currentlyEditedLabel == editedLabel) {
_currentlyEditedLabel = null;
}
}
public boolean hasEditedLabel() {
return _currentlyEditedLabel != null;
}
public LabelView<?> getEditedLabel() {
return _currentlyEditedLabel;
}
public void stopEditionOfEditedLabelIfAny() {
if (_currentlyEditedLabel != null) {
_currentlyEditedLabel.stopEdition();
}
}
private MouseDragControl currentMouseDrag = null;
public MouseDragControl getCurrentMouseDrag() {
return currentMouseDrag;
}
public void setCurrentMouseDrag(MouseDragControl aMouseDrag) {
currentMouseDrag = aMouseDrag;
}
/**
* Implements strategy to preferencially choose a control point or an other during focus retrieving strategy
*
* @param cp1
* @param cp2
* @return
*/
public ControlArea<?> preferredFocusedControlArea(ControlArea<?> ca1, ControlArea<?> ca2) {
if (ca1.getGraphicalRepresentation().getLayer() == ca2.getGraphicalRepresentation().getLayer()) {
// ControlPoint have priority on other ControlArea
if (ca1 instanceof ConnectorAdjustingControlPoint) {
return ca1;
} else if (ca2 instanceof ConnectorAdjustingControlPoint) {
return ca2;
}
if (ca1 instanceof ControlPoint) {
return ca1;
} else if (ca2 instanceof ControlPoint) {
return ca2;
}
}
return ca1.getGraphicalRepresentation().getLayer() > ca2.getGraphicalRepresentation().getLayer() ? ca1 : ca2;
}
public ControlArea<?> getFocusedControlArea() {
return focusedControlArea;
}
public void _setFocusedControlArea(ControlArea<?> aControlArea) {
if (focusedControlArea != aControlArea) {
this.focusedControlArea = aControlArea;
// getDrawingView().getPaintManager().repaint(getDrawingView());
}
}
public Vector<DrawingPalette> getPalettes() {
return palettes;
}
public void registerPalette(DrawingPalette aPalette) {
logger.fine("Register palette for " + this);
palettes.add(aPalette);
aPalette.registerController(this);
// if (getDrawingView() != null)
// getDrawingView().registerPalette(aPalette);
}
public void unregisterPalette(DrawingPalette aPalette) {
logger.fine("Un-Register palette for " + this);
palettes.remove(aPalette);
}
public void activatePalette(DrawingPalette aPalette) {
if (getDrawingView() != null) {
getDrawingView().registerPalette(aPalette);
}
}
public FGEPaintManager getPaintManager() {
if (getDrawingView() != null) {
return getDrawingView().getPaintManager();
}
return null;
}
public void enablePaintingCache() {
getPaintManager().enablePaintingCache();
}
public void disablePaintingCache() {
getPaintManager().disablePaintingCache();
}
public String getToolTipText() {
if (getFocusedObjects().size() > 0) {
GraphicalRepresentation<?> gr = getFocusedObjects().firstElement();
if (gr.getToolTipText() != null) {
// logger.info("getToolTipText() ? return "+gr.getToolTipText());
return gr.getToolTipText();
}
}
// logger.info("getToolTipText() ? return null");
return null;
}
public void delete() {
if (drawing instanceof DefaultDrawing<?>) {
((DefaultDrawing<?>) drawing).deleteObserver(this);
}
if (palettes != null) {
for (DrawingPalette palette : palettes) {
palette.delete();
}
}
if (drawingView != null) {
drawingView.delete();
}
if (toolbox != null) {
toolbox.delete();
}
focusedObjects.clear();
selectedObjects.clear();
focusedControlArea = null;
toolbox = null;
palettes = null;
storedSelection = null;
drawingView = null;
}
public FGEPoint getLastClickedPoint() {
return lastClickedPoint;
}
public void setLastClickedPoint(FGEPoint lastClickedPoint) {
this.lastClickedPoint = lastClickedPoint;
}
public GraphicalRepresentation<?> getLastSelectedGR() {
return lastSelectedGR;
}
public void setLastSelectedGR(GraphicalRepresentation<?> lastSelectedGR) {
this.lastSelectedGR = lastSelectedGR;
}
private Vector<Object> storedSelection;
private void restoreStoredSelection() {
if (storedSelection == null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Cannot restore null selection");
}
return;
}
try {
for (Object o : storedSelection) {
GraphicalRepresentation<?> gr = getGraphicalRepresentation(o);
if (gr != null) {
addToSelectedObjects(gr);
}
}
} finally {
storedSelection = null;
}
}
private void storeCurrentSelection() {
if (storedSelection != null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Cannot store selection when there is already a stored selection");
}
return;
}
storedSelection = new Vector<Object>();
for (GraphicalRepresentation<?> gr : getSelectedObjects()) {
storedSelection.add(gr.getDrawable());
}
}
@Override
public void update(Observable o, Object arg) {
if (o == getDrawing()) {
if (arg instanceof GraphicalObjectsHierarchyRebuildStarted) {
storeCurrentSelection();
} else if (arg instanceof GraphicalObjectsHierarchyRebuildEnded) {
restoreStoredSelection();
}
}
}
// Override when required
public void notifyWillMove(MoveInfo currentMove) {
}
// Override when required
public void notifyHasMoved(MoveInfo currentMove) {
}
/**
* Process 'UP' key pressed
*
* @return boolean indicating if event was successfully processed
*/
public boolean upKeyPressed() {
// System.out.println("Up");
return getDrawing().isEditable() && keyDrivenMove(0, -1);
}
/**
* Process 'DOWN' key pressed
*
* @return boolean indicating if event was successfully processed
*/
public boolean downKeyPressed() {
// System.out.println("Down");
return getDrawing().isEditable() && keyDrivenMove(0, 1);
}
/**
* Process 'LEFT' key pressed
*
* @return boolean indicating if event was successfully processed
*/
public boolean leftKeyPressed() {
// System.out.println("Left");
return getDrawing().isEditable() && keyDrivenMove(-1, 0);
}
/**
* Process 'RIGHT' key pressed
*
* @return boolean indicating if event was successfully processed
*/
public boolean rightKeyPressed() {
// System.out.println("Right");
return getDrawing().isEditable() && keyDrivenMove(1, 0);
}
private MoveInfo keyDrivenMovingSession;
private KeyDrivenMovingSessionTimer keyDrivenMovingSessionTimer = null;
private synchronized boolean keyDrivenMove(int deltaX, int deltaY) {
if (keyDrivenMovingSessionTimer == null && getFirstSelectedShape() != null) {
// System.out.println("BEGIN to move with keyboard");
if (startKeyDrivenMovingSession()) {
doMoveInSession(deltaX, deltaY);
return true;
}
return false;
} else if (keyDrivenMovingSessionTimer != null) {
doMoveInSession(deltaX, deltaY);
return true;
}
return false;
}
public void doMoveInSession(int deltaX, int deltaY) {
keyDrivenMovingSessionTimer.typed();
Point newLocation = keyDrivenMovingSession.getCurrentLocationInDrawingView();
newLocation.x += deltaX;
newLocation.y += deltaY;
keyDrivenMovingSession.moveTo(newLocation);
}
private synchronized boolean startKeyDrivenMovingSession() {
if (getFirstSelectedShape().getLocationConstraints() != LocationConstraints.UNMOVABLE) {
keyDrivenMovingSessionTimer = new KeyDrivenMovingSessionTimer();
keyDrivenMovingSessionTimer.start();
ShapeGraphicalRepresentation<?> movedObject = getFirstSelectedShape();
keyDrivenMovingSession = new MoveInfo(movedObject, this);
notifyWillMove(keyDrivenMovingSession);
return true;
} else {
return false;
}
}
private synchronized void stopKeyDrivenMovingSession() {
keyDrivenMovingSessionTimer = null;
notifyHasMoved(keyDrivenMovingSession);
keyDrivenMovingSession = null;
}
private class KeyDrivenMovingSessionTimer extends Thread {
volatile boolean typed = false;
public KeyDrivenMovingSessionTimer() {
typed = true;
}
@Override
public void run() {
while (typed) {
typed = false;
try {
sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
stopKeyDrivenMovingSession();
}
});
}
public synchronized void typed() {
typed = true;
// System.out.println("Tiens on retape sur le clavier");
}
}
}