2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009-2010 - DIGITEO - Pierre Lando
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
12 package org.scilab.modules.renderer.JoGLView.interaction;
14 import org.scilab.forge.scirenderer.DrawingTools;
15 import org.scilab.forge.scirenderer.SciRendererException;
16 import org.scilab.forge.scirenderer.buffers.BuffersManager;
17 import org.scilab.forge.scirenderer.buffers.ElementsBuffer;
18 import org.scilab.forge.scirenderer.buffers.IndicesBuffer;
19 import org.scilab.forge.scirenderer.shapes.appearance.Appearance;
20 import org.scilab.forge.scirenderer.shapes.appearance.Color;
21 import org.scilab.forge.scirenderer.shapes.geometry.DefaultGeometry;
22 import org.scilab.forge.scirenderer.shapes.geometry.Geometry;
23 import org.scilab.forge.scirenderer.tranformations.Vector3d;
24 import org.scilab.modules.graphic_objects.axes.Axes;
25 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
26 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
27 import org.scilab.modules.renderer.JoGLView.DrawerVisitor;
28 import org.scilab.modules.renderer.JoGLView.interaction.util.HelpersGeometry;
29 import org.scilab.modules.renderer.JoGLView.interaction.util.PointAComputer;
30 import org.scilab.modules.renderer.JoGLView.interaction.util.PointBComputer;
31 import org.scilab.modules.renderer.JoGLView.interaction.util.PointCComputer;
32 import org.scilab.modules.renderer.JoGLView.interaction.util.PointComputer;
33 import org.scilab.modules.renderer.JoGLView.interaction.util.PointDComputer;
34 import org.scilab.modules.renderer.JoGLView.postRendering.PostRendered;
36 import javax.swing.event.EventListenerList;
37 import java.awt.Component;
38 import java.awt.Point;
39 import java.awt.event.KeyEvent;
40 import java.awt.event.KeyListener;
41 import java.awt.event.MouseEvent;
42 import java.awt.event.MouseListener;
43 import java.awt.event.MouseMotionListener;
44 import java.text.DecimalFormat;
47 * @author Pierre Lando
49 public class RubberBox extends FigureInteraction implements PostRendered, MouseListener, MouseMotionListener, KeyListener {
51 /** Decimal format used to show info messages */
52 private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.###E0");
54 /** Axes name used to show info messages */
55 private static final String[] AXES_NAMES = new String[]{"X", "Y", "Z"};
57 /** The cube indices */
58 private static final int[] CUBE_INDICES = {
59 0, 1, 3, 2, 4, 5, 7, 6,
60 0, 3, 1, 2, 4, 7, 5, 6,
61 0, 4, 1, 5, 3, 7, 2, 6
64 /** Rubber box status */
65 public static enum Status {
72 /** Rubber box color */
73 private static final Color RUBBER_BOX_COLOR = new Color(.2f, .3f, .4f);
75 /** Rubber box thickness */
76 private static final float RUBBER_BOX_THICKNESS = 2;
78 /** Rubber box pattern */
79 private static final short RUBBER_BOX_PATTERN = (short) 0xFAFA;
81 /** The mouse button used to perform a rubber box */
82 private static final int MOUSE_MODIFIER = MouseEvent.BUTTON1_MASK;
84 /** This key stop the rubber box */
85 private static final int STOP_KEY = KeyEvent.VK_ESCAPE;
87 /** Helpers appearance */
88 private static Appearance helpersAppearance;
90 /** Rubber box cube appearance */
91 private static Appearance cubeAppearance;
93 /** The event listener list */
94 private final EventListenerList listenerList = new EventListenerList();
96 /** Helpers geometry */
97 private HelpersGeometry helpersGeometry;
99 /** Rubber box cube geometry */
100 private DefaultGeometry cubeGeometry;
102 /** Current status */
103 private Status status;
107 private PointAComputer pointAComputer;
108 private PointBComputer pointBComputer;
109 private PointCComputer pointCComputer;
110 private PointDComputer pointDComputer;
111 private Vector3d firstPoint;
112 private Vector3d secondPoint;
115 * Default constructor.
117 * @param drawerVisitor parent drawer visitor.
119 public RubberBox(DrawerVisitor drawerVisitor) {
120 super(drawerVisitor);
121 status = Status.WAIT_POINT_A;
125 * Add a rubber box listener.
126 * The listener will be notified when a rubber box end.
127 * @param rubberBoxListener the new listener.
129 public final void addListener(RubberBoxListener rubberBoxListener) {
130 listenerList.add(RubberBoxListener.class, rubberBoxListener);
134 * Remove a rubber box listener.
135 * The listener will no long be notified on events.
136 * @param rubberBoxListener the removed listener.
138 public final void removeListener(RubberBoxListener rubberBoxListener) {
139 listenerList.remove(RubberBoxListener.class, rubberBoxListener);
143 * Notify all listener that the rubber box have ended
145 private void fireRubberBoxEnd() {
146 for (RubberBoxListener rubberBoxListener : listenerList.getListeners(RubberBoxListener.class)) {
147 rubberBoxListener.rubberBoxEnd();
152 public final void draw(DrawingTools drawingTools) throws SciRendererException {
153 if (isEnable() && (axes != null)) {
154 drawingTools.getTransformationManager().useSceneCoordinate();
155 drawingTools.getTransformationManager().getModelViewStack().push(
156 getDrawerVisitor().getAxesDrawer().getSceneProjection(axes.getIdentifier())
159 if (status != Status.WAIT_POINT_A) {
160 drawingTools.draw(getCubeGeometry(drawingTools), getCubeAppearance());
163 if (secondPoint != null) {
164 drawingTools.draw(getHelpersGeometry(drawingTools), getHelpersAppearance());
167 drawingTools.getTransformationManager().getModelViewStack().pop();
172 public final void changeEnable(boolean isEnable) {
173 Component component = getDrawerVisitor().getComponent();
175 status = Status.WAIT_POINT_A;
176 pointAComputer = null;
177 component.addMouseListener(this);
178 component.addMouseMotionListener(this);
179 component.addKeyListener(this);
180 component.setFocusTraversalKeysEnabled(false);
181 component.setFocusable(true);
182 component.requestFocus();
184 component.removeMouseListener(this);
185 component.removeMouseMotionListener(this);
186 component.removeKeyListener(this);
189 getDrawerVisitor().getCanvas().redraw();
193 public final void keyTyped(KeyEvent e) {
194 if (e.getKeyChar() == STOP_KEY) {
201 public final void mouseClicked(MouseEvent e) {
202 if (e.getModifiers() == MOUSE_MODIFIER) {
205 if (setPointA(e.getPoint())) {
206 status = Status.WAIT_POINT_B;
213 setPointB(e.getPoint());
214 if (pointBComputer.is2D()) {
219 status = Status.WAIT_POINT_C;
223 setPointC(e.getPoint());
224 status = Status.WAIT_POINT_D;
227 setPointD(e.getPoint());
239 public final void mouseMoved(MouseEvent e) {
242 setPointA(e.getPoint());
243 getDrawerVisitor().getCanvas().redraw();
246 setPointB(e.getPoint());
247 getDrawerVisitor().getCanvas().redraw();
250 setPointC(e.getPoint());
251 getDrawerVisitor().getCanvas().redraw();
254 setPointD(e.getPoint());
255 getDrawerVisitor().getCanvas().redraw();
263 * Update displayed info message.
265 private void updateInfoMessage() {
269 setInfoMessage("Click to set first bounds", pointAComputer, false);
272 setInfoMessage("Click to set second bounds", pointBComputer, false);
275 setInfoMessage("Click to set first", pointCComputer, true);
278 setInfoMessage("Click to set second ", pointDComputer, true);
283 GraphicController.getController().setProperty(
284 getDrawerVisitor().getFigure().getIdentifier(),
285 GraphicObjectProperties.__GO_INFO_MESSAGE__,
292 * Set the info message.
293 * @param baseMessage the base of the message.
294 * @param pointComputer current used point computer.
295 * @param oneAxis true if only one coordinate is currently set.
297 private void setInfoMessage(String baseMessage, PointComputer pointComputer, boolean oneAxis) {
298 if ((pointComputer != null) && (pointComputer.isValid())) {
299 String message = baseMessage + " ";
300 double[] data = pointComputer.getSecondPosition().getData();
308 for (int i = 0; i < PointComputer.AXIS_NUMBER; i++) {
309 if ((i != pointComputer.getFirstAxisIndex()) ^ oneAxis) {
310 message += AXES_NAMES[i] + " = " + DECIMAL_FORMAT.format(data[i]) + comma;
314 GraphicController.getController().setProperty(
315 getDrawerVisitor().getFigure().getIdentifier(),
316 GraphicObjectProperties.__GO_INFO_MESSAGE__,
320 String message = "Move your mouse on an axes box.";
321 GraphicController.getController().setProperty(
322 getDrawerVisitor().getFigure().getIdentifier(),
323 GraphicObjectProperties.__GO_INFO_MESSAGE__,
330 * Actually set the zoom box depending on current value of firstPoint and secondPoint.
332 private void setZoomBox() {
334 Math.min(firstPoint.getX(), secondPoint.getX()), Math.max(firstPoint.getX(), secondPoint.getX()),
335 Math.min(firstPoint.getY(), secondPoint.getY()), Math.max(firstPoint.getY(), secondPoint.getY()),
336 Math.min(firstPoint.getZ(), secondPoint.getZ()), Math.max(firstPoint.getZ(), secondPoint.getZ()),
339 if (bounds[0].compareTo(bounds[1]) != 0 && bounds[2].compareTo(bounds[3]) != 0 && bounds[4].compareTo(bounds[5]) != 0) {
340 Boolean zoomed = tightZoomBounds(axes, bounds);
341 GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_ZOOM_BOX__, bounds);
342 GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_ZOOM_ENABLED__, zoomed);
343 getDrawerVisitor().getCanvas().redraw();
348 * Set the first point.
349 * @param point first point AWT coordinate.
350 * @return true if the first point is valid.
352 private boolean setPointA(Point point) {
353 axes = getUnderlyingAxes(point);
355 PointAComputer pointComputer = new PointAComputer(axes, point);
356 if (pointComputer.isValid()) {
357 this.pointAComputer = pointComputer;
358 firstPoint = pointComputer.getPosition();
359 secondPoint = firstPoint;
367 * Set second point in 3D zoom.
368 * @param point second point.
369 * @return true if the point is valid.
371 private boolean setPointB(Point point) {
372 PointBComputer pointComputer = new PointBComputer(axes, pointAComputer, point);
373 if (pointComputer.isValid()) {
374 this.pointBComputer = pointComputer;
375 firstPoint = pointComputer.getFirstPosition();
376 secondPoint = pointComputer.getSecondPosition();
377 getDrawerVisitor().getCanvas().redraw();
385 * Set zoom box position in 3D zoom.
386 * @param point mouse position.
387 * @return true if the point is valid.
389 private boolean setPointC(Point point) {
390 PointCComputer pointComputer = new PointCComputer(axes, pointBComputer, point);
391 if (pointComputer.isValid()) {
392 this.pointCComputer = pointComputer;
393 firstPoint = pointComputer.getFirstPosition();
394 secondPoint = pointComputer.getSecondPosition();
395 getDrawerVisitor().getCanvas().redraw();
403 * Set zoom box position in 3D zoom.
404 * @param point mouse position.
405 * @return true if the point is valid.
407 private boolean setPointD(Point point) {
408 PointDComputer pointComputer = new PointDComputer(axes, pointCComputer, point);
409 if (pointComputer.isValid()) {
410 this.pointDComputer = pointComputer;
411 firstPoint = pointComputer.getFirstPosition();
412 secondPoint = pointComputer.getSecondPosition();
413 getDrawerVisitor().getCanvas().redraw();
421 * Initialise or update the helpers geometry.
422 * @param drawingTools the drawing tools used to draw the helpers.
423 * @return updated helpers geometry.
425 private Geometry getHelpersGeometry(DrawingTools drawingTools) {
426 if (helpersGeometry == null) {
427 helpersGeometry = new HelpersGeometry(drawingTools);
429 helpersGeometry.updateVertex(axes, pointAComputer, secondPoint, status);
430 return helpersGeometry;
434 * Helpers appearance getter.
435 * First initialise the helpers appearance.
436 * @return the helpers appearance.
438 public final Appearance getHelpersAppearance() {
439 if (helpersAppearance == null) {
440 helpersAppearance = new Appearance();
441 helpersAppearance.setLineColor(new Color(1, 0, 0));
442 helpersAppearance.setLineWidth(2);
444 return helpersAppearance;
448 * Rubber box cube geometry getter.
449 * @param drawingTools the drawing tools.
450 * @return the rubber box cubeGeometry.
452 private Geometry getCubeGeometry(DrawingTools drawingTools) {
453 if (cubeGeometry == null) {
454 cubeGeometry = new DefaultGeometry();
456 BuffersManager bufferManager = drawingTools.getCanvas().getBuffersManager();
457 ElementsBuffer vertexBuffer = bufferManager.createElementsBuffer();
458 IndicesBuffer indicesBuffer = bufferManager.createIndicesBuffer();
459 indicesBuffer.setData(CUBE_INDICES);
461 cubeGeometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
462 cubeGeometry.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
463 cubeGeometry.setVertices(vertexBuffer);
464 cubeGeometry.setWireIndices(indicesBuffer);
467 cubeGeometry.getVertices().setData(new float[] {
468 (float) firstPoint.getX(), (float) firstPoint.getY(), (float) firstPoint.getZ(), 1,
469 (float) firstPoint.getX(), (float) firstPoint.getY(), (float) secondPoint.getZ(), 1,
470 (float) firstPoint.getX(), (float) secondPoint.getY(), (float) secondPoint.getZ(), 1,
471 (float) firstPoint.getX(), (float) secondPoint.getY(), (float) firstPoint.getZ(), 1,
472 (float) secondPoint.getX(), (float) firstPoint.getY(), (float) firstPoint.getZ(), 1,
473 (float) secondPoint.getX(), (float) firstPoint.getY(), (float) secondPoint.getZ(), 1,
474 (float) secondPoint.getX(), (float) secondPoint.getY(), (float) secondPoint.getZ(), 1,
475 (float) secondPoint.getX(), (float) secondPoint.getY(), (float) firstPoint.getZ(), 1
482 * Rubber-box cube appearance getter.
483 * @return the rubber-box cube appearance.
485 private Appearance getCubeAppearance() {
486 if (cubeAppearance == null) {
487 cubeAppearance = new Appearance();
488 cubeAppearance.setLineColor(RUBBER_BOX_COLOR);
489 cubeAppearance.setLineWidth(RUBBER_BOX_THICKNESS);
490 cubeAppearance.setLinePattern(RUBBER_BOX_PATTERN);
492 return cubeAppearance;
496 public void mousePressed(MouseEvent e) {
500 public void mouseReleased(MouseEvent e) {
504 public void mouseEntered(MouseEvent e) {
508 public void mouseExited(MouseEvent e) {
512 public void mouseDragged(MouseEvent e) {
516 public void keyPressed(KeyEvent e) {
520 public void keyReleased(KeyEvent e) {