Delete openGL component in Frame if removed.
[scilab.git] / scilab / modules / renderer / src / java / org / scilab / modules / renderer / JoGLView / DrawerVisitor.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - DIGITEO - Pierre Lando
4  *
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.1-en.txt
10  */
11
12 package org.scilab.modules.renderer.JoGLView;
13
14 import java.awt.Component;
15 import java.awt.Dimension;
16 import java.nio.ByteBuffer;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.LinkedList;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import javax.swing.SwingUtilities;
27
28 import org.scilab.forge.scirenderer.Canvas;
29 import org.scilab.forge.scirenderer.Drawer;
30 import org.scilab.forge.scirenderer.DrawingTools;
31 import org.scilab.forge.scirenderer.SciRendererException;
32 import org.scilab.forge.scirenderer.buffers.ElementsBuffer;
33 import org.scilab.forge.scirenderer.shapes.appearance.Appearance;
34 import org.scilab.forge.scirenderer.shapes.geometry.DefaultGeometry;
35 import org.scilab.forge.scirenderer.shapes.geometry.Geometry;
36 import org.scilab.forge.scirenderer.texture.AbstractTextureDataProvider;
37 import org.scilab.forge.scirenderer.texture.AnchorPosition;
38 import org.scilab.forge.scirenderer.texture.Texture;
39 import org.scilab.forge.scirenderer.tranformations.Transformation;
40 import org.scilab.forge.scirenderer.tranformations.TransformationFactory;
41 import org.scilab.forge.scirenderer.tranformations.TransformationStack;
42 import org.scilab.forge.scirenderer.tranformations.Vector3d;
43 import org.scilab.forge.scirenderer.utils.shapes.geometry.CubeFactory;
44 import org.scilab.modules.graphic_objects.ObjectRemovedException;
45 import org.scilab.modules.graphic_objects.arc.Arc;
46 import org.scilab.modules.graphic_objects.axes.Axes;
47 import org.scilab.modules.graphic_objects.axes.AxesContainer;
48 import org.scilab.modules.graphic_objects.axes.Camera.ViewType;
49 import org.scilab.modules.graphic_objects.axis.Axis;
50 import org.scilab.modules.graphic_objects.compound.Compound;
51 import org.scilab.modules.graphic_objects.datatip.Datatip;
52 import org.scilab.modules.graphic_objects.fec.Fec;
53 import org.scilab.modules.graphic_objects.figure.ColorMap;
54 import org.scilab.modules.graphic_objects.figure.Figure;
55 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
56 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject;
57 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
58 import org.scilab.modules.graphic_objects.graphicObject.Visitor;
59 import org.scilab.modules.graphic_objects.graphicView.GraphicView;
60 import org.scilab.modules.graphic_objects.imageplot.Grayplot;
61 import org.scilab.modules.graphic_objects.imageplot.Matplot;
62 import org.scilab.modules.graphic_objects.label.Label;
63 import org.scilab.modules.graphic_objects.legend.Legend;
64 import org.scilab.modules.graphic_objects.polyline.Polyline;
65 import org.scilab.modules.graphic_objects.rectangle.Rectangle;
66 import org.scilab.modules.graphic_objects.surface.Fac3d;
67 import org.scilab.modules.graphic_objects.surface.Plot3d;
68 import org.scilab.modules.graphic_objects.textObject.Text;
69 import org.scilab.modules.graphic_objects.uicontrol.frame.Frame;
70 import org.scilab.modules.graphic_objects.vectfield.Arrow;
71 import org.scilab.modules.graphic_objects.vectfield.Champ;
72 import org.scilab.modules.graphic_objects.vectfield.Segs;
73 import org.scilab.modules.renderer.JoGLView.arrowDrawing.ArrowDrawer;
74 import org.scilab.modules.renderer.JoGLView.axes.AxesDrawer;
75 import org.scilab.modules.renderer.JoGLView.contouredObject.ContouredObjectDrawer;
76 import org.scilab.modules.renderer.JoGLView.datatip.DatatipTextDrawer;
77 import org.scilab.modules.renderer.JoGLView.interaction.InteractionManager;
78 import org.scilab.modules.renderer.JoGLView.label.LabelManager;
79 import org.scilab.modules.renderer.JoGLView.legend.LegendDrawer;
80 import org.scilab.modules.renderer.JoGLView.mark.MarkSpriteManager;
81 import org.scilab.modules.renderer.JoGLView.postRendering.PostRendered;
82 import org.scilab.modules.renderer.JoGLView.text.TextManager;
83 import org.scilab.modules.renderer.JoGLView.util.ColorFactory;
84 import org.scilab.modules.renderer.JoGLView.util.LightingUtils;
85 import org.scilab.modules.renderer.JoGLView.util.OutOfMemoryException;
86
87 /**
88  * @author Pierre Lando
89  */
90 public class DrawerVisitor implements Visitor, Drawer, GraphicView {
91
92     /** Set of properties changed during a draw if auto-ticks is on for X axis. */
93     private static final Set<Integer> X_AXIS_TICKS_PROPERTIES = new HashSet<Integer>(Arrays.asList(
94                 GraphicObjectProperties.__GO_X_AXIS_TICKS_LOCATIONS__,
95                 GraphicObjectProperties.__GO_X_AXIS_TICKS_LABELS__
96             ));
97
98     /** Set of properties changed during a draw if auto-ticks is on for Y axis. */
99     private static final Set<Integer> Y_AXIS_TICKS_PROPERTIES = new HashSet<Integer>(Arrays.asList(
100                 GraphicObjectProperties.__GO_Y_AXIS_TICKS_LOCATIONS__,
101                 GraphicObjectProperties.__GO_Y_AXIS_TICKS_LABELS__
102             ));
103
104     /** Set of properties changed during a draw if auto-ticks is on for Z axis. */
105     private static final Set<Integer> Z_AXIS_TICKS_PROPERTIES = new HashSet<Integer>(Arrays.asList(
106                 GraphicObjectProperties.__GO_Z_AXIS_TICKS_LOCATIONS__,
107                 GraphicObjectProperties.__GO_Z_AXIS_TICKS_LABELS__
108             ));
109
110     /** Set of figure properties for witch a change doesn't lead to a redraw */
111     private static final Set<Integer> SILENT_FIGURE_PROPERTIES = new HashSet<Integer>(Arrays.asList(
112                 GraphicObjectProperties.__GO_ROTATION_TYPE__,
113                 GraphicObjectProperties.__GO_INFO_MESSAGE__,
114                 GraphicObjectProperties.__GO_FIGURE_NAME__,
115                 GraphicObjectProperties.__GO_AUTORESIZE__,
116                 GraphicObjectProperties.__GO_POSITION__,
117                 GraphicObjectProperties.__GO_SIZE__,
118                 GraphicObjectProperties.__GO_ID__
119             ));
120
121     private static final boolean DEBUG_MODE = false;
122
123     private final Component component;
124     private final AxesContainer figure;
125     private final InteractionManager interactionManager;
126
127     private final ColorMapTextureDataProvider colorMapTextureDataProvider;
128
129     private final ScilabTextureManager textureManager;
130     private final MarkSpriteManager markManager;
131     private final LabelManager labelManager;
132     private final DataManager dataManager;
133     private final TextManager textManager;
134
135     private final ContouredObjectDrawer contouredObjectDrawer;
136     private final LegendDrawer legendDrawer;
137     protected final AxesDrawer axesDrawer;
138     private final AxisDrawer axisDrawer;
139     private final ArrowDrawer arrowDrawer;
140     private final FecDrawer fecDrawer;
141     private final DatatipTextDrawer datatipTextDrawer;
142
143     private DrawingTools drawingTools;
144     private Texture colorMapTexture;
145     private ColorMap colorMap;
146
147     private Axes currentAxes;
148     private Canvas canvas;
149
150     /**
151      * The map between the existing Figures' identifiers and their corresponding Visitor.
152      * Used to get access to the DrawerVisitor corresponding to a given Figure when the
153      * renderer module is accessed from another thread than the AWT's.
154      */
155     private final static Map<Integer, DrawerVisitor> visitorMap = new HashMap<Integer, DrawerVisitor>();
156     private final List<PostRendered> postRenderedList = new LinkedList<PostRendered>();
157     private final static Map<Integer, List<Integer>> openGLChildren = new HashMap<Integer, List<Integer>>();
158
159     public DrawerVisitor(Component component, Canvas canvas, AxesContainer figure) {
160         GraphicController.getController().register(this);
161
162         this.component = component;
163         this.canvas = canvas;
164         this.figure = figure;
165
166         this.interactionManager = new InteractionManager(this);
167         this.dataManager = new DataManager(canvas);
168         this.textureManager = new ScilabTextureManager(this);
169         this.markManager = new MarkSpriteManager(canvas.getTextureManager());
170         this.textManager = new TextManager(canvas.getTextureManager());
171         this.labelManager = new LabelManager(canvas.getTextureManager());
172         this.axesDrawer = new AxesDrawer(this);
173         this.axisDrawer = new AxisDrawer(this);
174         this.arrowDrawer = new ArrowDrawer(this);
175         this.contouredObjectDrawer = new ContouredObjectDrawer(this, this.dataManager, this.markManager);
176         this.legendDrawer = new LegendDrawer(this);
177         this.fecDrawer = new FecDrawer(this);
178         this.colorMapTextureDataProvider = new ColorMapTextureDataProvider();
179         this.datatipTextDrawer = new DatatipTextDrawer(canvas.getTextureManager());
180
181         visitorMap.put(figure.getIdentifier(), this);
182     }
183
184     public static void changeVisitor(AxesContainer figure, DrawerVisitor visitor) {
185         if (visitor == null) {
186             visitorMap.remove(figure.getIdentifier());
187         } else {
188             visitorMap.put(figure.getIdentifier(), visitor);
189         }
190     }
191
192     public void setDrawingTools(DrawingTools drawingTools) {
193         this.drawingTools = drawingTools;
194     }
195
196     public DrawingTools getDrawingTools() {
197         return drawingTools;
198     }
199
200     public Canvas getCanvas() {
201         return canvas;
202     }
203
204     public void setCanvas(Canvas canvas) {
205         this.canvas = canvas;
206     }
207
208     /**
209      * @return the DataManager
210      */
211     public DataManager getDataManager() {
212         return dataManager;
213     }
214
215     /**
216      * @return the TextManager
217      */
218     public TextManager getTextManager() {
219         return textManager;
220     }
221
222     /**
223      * @return the LegendDrawer
224      */
225     public LegendDrawer getLegendDrawer() {
226         return legendDrawer;
227     }
228
229     /**
230      * Mark manager getter.
231      * @return the mark manager.
232      */
233     public MarkSpriteManager getMarkManager() {
234         return markManager;
235     }
236
237     /**
238      * @return the AxesDrawer
239      */
240     public AxesDrawer getAxesDrawer() {
241         return axesDrawer;
242     }
243
244     /**
245      * @return the ArrowDrawer
246      */
247     public ArrowDrawer getArrowDrawer() {
248         return arrowDrawer;
249     }
250
251     public ColorMap getColorMap() {
252         return colorMap;
253     }
254
255     public DatatipTextDrawer getDatatipTextDrawer() {
256         return datatipTextDrawer;
257     }
258
259     /**
260      * Returns the visitor corresponding to the Figure identifier.
261      * @param figureId the figure identifier.
262      * @return the visitor.
263      */
264     public static DrawerVisitor getVisitor(Integer figureId) {
265         return visitorMap.get(figureId);
266     }
267
268     public void addPostRendering(PostRendered postRendered) {
269         if (postRendered != null) {
270             postRenderedList.add(postRendered);
271         }
272     }
273
274     public void removePostRendering(PostRendered postRendered) {
275         postRenderedList.remove(postRendered);
276     }
277
278     @Override
279     public void draw(DrawingTools drawingTools) {
280         this.drawingTools = drawingTools;
281         if (figure instanceof Figure) {
282             visit((Figure) figure);
283         } else {
284             visit((Frame) figure);
285         }
286
287         for (PostRendered postRendered : postRenderedList) {
288             try {
289                 postRendered.draw(drawingTools);
290             } catch (SciRendererException e) {
291                 System.err.println("A 'PostRendered' is not drawable because: '" + e.getMessage() + "'");
292             }
293         }
294         drawingTools.getTransformationManager().useSceneCoordinate();
295     }
296
297     /**
298      * Ask the given object to accept visitor.
299      * @param childrenId array of object identifier.
300      */
301     public void askAcceptVisitor(Integer[] childrenId) {
302         if (childrenId != null) {
303
304             for (int i = childrenId.length - 1; i >= 0; --i) {
305                 GraphicObject child = GraphicController.getController().getObjectFromId(childrenId[i]);
306                 if (child != null) {
307                     try {
308                         child.accept(this);
309                     } catch (ObjectRemovedException e) {
310                         if (DEBUG_MODE) {
311                             System.err.println("[DEBUG] Try to draw an already removed object");
312                             System.err.println("[DEBUG] " + e);
313                             System.err.println("[DEBUG] Skipped...");
314                         }
315                     }
316                 }
317             }
318         }
319     }
320
321     /**
322      * @return true if it is a 2D view
323      */
324     public boolean is2DView() {
325         return currentAxes.getViewAsEnum() == ViewType.VIEW_2D;
326     }
327
328     @Override
329     public void visit(Axes axes) {
330         synchronized (axes) {
331             if (axes.isValid() && axes.getVisible()) {
332                 try {
333                     currentAxes = axes;
334                     axesDrawer.computeRulers(axes);
335                     axesDrawer.draw(axes);
336                 } catch (SciRendererException e) {
337                     invalidate(axes, e);
338                 }
339             }
340         }
341     }
342
343     @Override
344     public void visit(Arc arc) {
345         if (arc.isValid() && arc.getVisible()) {
346             axesDrawer.enableClipping(currentAxes, arc.getClipProperty());
347             try {
348                 contouredObjectDrawer.draw(arc, currentAxes.getViewAsEnum() == ViewType.VIEW_2D);
349             } catch (OutOfMemoryException e) {
350                 invalidate(arc, e);
351             } catch (SciRendererException e) {
352                 invalidate(arc, e);
353             } catch (ObjectRemovedException e) {
354                 invalidate(arc, e);
355             }
356             axesDrawer.disableClipping(arc.getClipProperty());
357         }
358     }
359
360     @Override
361     public void visit(Axis axis) {
362         if (axis.getVisible()) {
363             axesDrawer.enableClipping(currentAxes, axis.getClipProperty());
364             axisDrawer.draw(currentAxes, axis);
365             axesDrawer.disableClipping(axis.getClipProperty());
366         }
367     }
368
369     @Override
370     public void visit(Compound compound) {
371         if (compound.getVisible()) {
372             askAcceptVisitor(compound.getChildren());
373         }
374     }
375
376     @Override
377     public void visit(Fec fec) throws ObjectRemovedException {
378         if (fec.isValid() && fec.getVisible()) {
379             axesDrawer.enableClipping(currentAxes, fec.getClipProperty());
380             try {
381                 fecDrawer.draw(fec);
382             } catch (OutOfMemoryException e) {
383                 invalidate(fec, e);
384             }
385             axesDrawer.disableClipping(fec.getClipProperty());
386         }
387     }
388
389     @Override
390     public void visit(Figure figure) {
391         synchronized (figure) {
392             /** Set the current {@see ColorMap}. */
393             try {
394                 Dimension dims = getCanvas().getDimension();
395                 colorMap = figure.getColorMap();
396                 drawingTools.clear(ColorFactory.createColor(colorMap, figure.getBackground()));
397                 drawingTools.clearDepthBuffer();
398                 if (figure.isValid() && figure.getVisible() && figure.getImmediateDrawing() && dims.width > 1 && dims.height > 1) {
399                     askAcceptVisitor(figure.getChildren());
400                 }
401             } catch (Exception e) {
402                 System.err.println(e);
403             }
404         }
405     }
406
407     public void visit(Frame frame) {
408         synchronized (frame) {
409             /** Set the current {@see ColorMap}. */
410             try {
411                 colorMap = frame.getColorMap();
412                 drawingTools.clear(ColorFactory.createColor(colorMap, frame.getBackground()));
413                 drawingTools.clearDepthBuffer();
414                 if (frame.isValid() && frame.getVisible()) {
415                     DrawerVisitor visitor = visitorMap.get(frame.getIdentifier());
416                     if (visitor != null) {
417                         Dimension dims = visitor.getCanvas().getDimension();
418                         visitor.setDrawingTools(drawingTools);
419                         if (dims.width > 1 && dims.height > 1) {
420                             visitor.askAcceptVisitor(frame.getChildren());
421                         }
422                     }
423                 }
424             } catch (Exception e) {
425                 System.err.println(e);
426             }
427         }
428     }
429
430     @Override
431     public void visit(final Grayplot grayplot) {
432         if (grayplot.isValid() && grayplot.getVisible()) {
433             axesDrawer.enableClipping(currentAxes, grayplot.getClipProperty());
434             try {
435                 DefaultGeometry triangles = new DefaultGeometry();
436                 triangles.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
437                 triangles.setVertices(dataManager.getVertexBuffer(grayplot.getIdentifier()));
438                 triangles.setColors(dataManager.getColorBuffer(grayplot.getIdentifier()));
439                 triangles.setIndices(dataManager.getIndexBuffer(grayplot.getIdentifier()));
440                 triangles.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
441                 Appearance trianglesAppearance = new Appearance();
442                 drawingTools.draw(triangles, trianglesAppearance);
443                 /*} catch (ObjectRemovedException e) {
444                   invalidate(grayplot, e);
445                   } catch (SciRendererException e) {
446                   invalidate(grayplot, e);
447                   } catch (OutOfMemoryException e) {
448                   invalidate(grayplot, e);
449                   }*/
450             } catch (Exception e) {
451                 System.err.println(e);
452                 e.printStackTrace();
453             }
454             axesDrawer.disableClipping(grayplot.getClipProperty());
455         }
456     }
457
458     @Override
459     public void visit(final Matplot matplot) {
460         if (matplot.isValid() && matplot.getVisible()) {
461             axesDrawer.enableClipping(currentAxes, matplot.getClipProperty());
462             try {
463                 if ((currentAxes != null) && (currentAxes.getXAxisLogFlag() || currentAxes.getYAxisLogFlag())) {
464                     DefaultGeometry geometry = new DefaultGeometry();
465                     geometry.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
466                     geometry.setVertices(dataManager.getVertexBuffer(matplot.getIdentifier()));
467                     geometry.setColors(dataManager.getColorBuffer(matplot.getIdentifier()));
468                     geometry.setIndices(dataManager.getIndexBuffer(matplot.getIdentifier()));
469                     geometry.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
470                     Appearance appearance = new Appearance();
471                     drawingTools.draw(geometry, appearance);
472                 } else {
473                     TransformationStack modelViewStack = drawingTools.getTransformationManager().getModelViewStack();
474                     double[][] factors = currentAxes.getScaleTranslateFactors();
475                     Double[] scale = matplot.getScale();
476                     Double[] translate = matplot.getTranslate();
477
478                     scale[0] *= factors[0][0];
479                     scale[1] *= factors[0][1];
480
481                     translate[0] = translate[0] * factors[0][0] + factors[1][0];
482                     translate[1] = translate[1] * factors[0][1] + factors[1][1];
483
484                     Transformation t = TransformationFactory.getTranslateTransformation(translate[0], translate[1], 0);
485                     Transformation t2 = TransformationFactory.getScaleTransformation(scale[0], scale[1], 1);
486                     modelViewStack.pushRightMultiply(t);
487                     modelViewStack.pushRightMultiply(t2);
488                     drawingTools.draw(textureManager.getTexture(matplot.getIdentifier()));
489                     modelViewStack.pop();
490                     modelViewStack.pop();
491                 }
492             } catch (ObjectRemovedException e) {
493                 invalidate(matplot, e);
494             } catch (SciRendererException e) {
495                 invalidate(matplot, e);
496             } catch (OutOfMemoryException e) {
497                 invalidate(matplot, e);
498             }
499             axesDrawer.disableClipping(matplot.getClipProperty());
500         }
501     }
502
503     @Override
504     public void visit(Label label) {
505         if (label.isValid() && label.getVisible() && !label.isEmpty()) {
506             try {
507                 labelManager.draw(drawingTools, colorMap, label, axesDrawer);
508             } catch (SciRendererException e) {
509                 invalidate(label, e);
510             }
511         }
512     }
513
514     @Override
515     public void visit(Legend legend) {
516         if (legend.isValid() && legend.getVisible()) {
517             try {
518                 legendDrawer.draw(legend);
519             } catch (SciRendererException e) {
520                 invalidate(legend, e);
521             }
522         }
523     }
524
525     @Override
526     public void visit(final Polyline polyline) {
527         synchronized (polyline) {
528             if (polyline.isValid() && polyline.getVisible()) {
529                 axesDrawer.enableClipping(currentAxes, polyline.getClipProperty());
530                 try {
531                     DefaultGeometry geometry = new DefaultGeometry();
532
533                     geometry.setVertices(dataManager.getVertexBuffer(polyline.getIdentifier()));
534                     geometry.setIndices(dataManager.getIndexBuffer(polyline.getIdentifier()));
535                     geometry.setWireIndices(dataManager.getWireIndexBuffer(polyline.getIdentifier()));
536
537                     final int style = polyline.getPolylineStyle();
538                     if (style == 1 || style == 2 || style == 4 || style == 5) {
539                         geometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS_STRIP);
540                     } else {
541                         geometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
542                     }
543
544                     geometry.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
545                     geometry.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
546
547                     geometry.setPolygonOffsetMode(currentAxes.getCamera().getView() == ViewType.VIEW_3D);
548
549                     /* Interpolated color rendering is used only for basic polylines for now. */
550                     Appearance appearance = new Appearance();
551
552                     if (polyline.getInterpColorMode() && style == 1) {
553                         geometry.setTextureCoordinates(dataManager.getTextureCoordinatesBuffer(polyline.getIdentifier()));
554                         appearance.setTexture(getColorMapTexture());
555                     } else {
556                         geometry.setColors(null);
557                     }
558
559                     appearance.setLineColor(ColorFactory.createColor(colorMap, polyline.getLineColor()));
560                     appearance.setLineWidth(polyline.getLineThickness().floatValue());
561                     appearance.setLinePattern(polyline.getLineStyleAsEnum().asPattern());
562
563                     if (!polyline.getInterpColorMode() || style != 1) {
564                         int fillColor;
565
566                         /*
567                          * The line color is used as fill color for the filled patch polyline style
568                          * whereas the background color is used for all the other styles.
569                          */
570                         if (style == 5) {
571                             fillColor = polyline.getLineColor();
572                         } else {
573                             fillColor = polyline.getBackground();
574                         }
575
576                         appearance.setFillColor(ColorFactory.createColor(colorMap, fillColor));
577                     }
578
579                     drawingTools.draw(geometry, appearance);
580
581                     if (style == 4) {
582                         arrowDrawer.drawArrows(polyline.getParentAxes(), polyline.getIdentifier(), polyline.getArrowSizeFactor(),
583                                                polyline.getLineThickness(), false, false, polyline.getLineColor(), true);
584                     }
585
586                     if (polyline.getMarkMode()) {
587                         Texture sprite = markManager.getMarkSprite(polyline, colorMap, appearance);
588                         ElementsBuffer positions = dataManager.getVertexBuffer(polyline.getIdentifier());
589                         int offset = polyline.getMarkOffset();
590                         int stride = polyline.getMarkStride();
591                         drawingTools.draw(sprite, AnchorPosition.CENTER, positions, offset, stride, 0);
592                     }
593                 } catch (ObjectRemovedException e) {
594                     invalidate(polyline, e);
595                 } catch (OutOfMemoryException e) {
596                     invalidate(polyline, e);
597                 } catch (SciRendererException e) {
598                     invalidate(polyline, e);
599                 }
600                 axesDrawer.disableClipping(polyline.getClipProperty());
601                 askAcceptVisitor(polyline.getDatatips());
602             }
603         }
604     }
605
606     @Override
607     public void visit(Rectangle rectangle) {
608         if (rectangle.isValid() && rectangle.getVisible()) {
609             axesDrawer.enableClipping(currentAxes, rectangle.getClipProperty());
610             try {
611                 contouredObjectDrawer.draw(rectangle, currentAxes.getCamera().getView() == ViewType.VIEW_2D);
612             } catch (ObjectRemovedException e) {
613                 invalidate(rectangle, e);
614             } catch (OutOfMemoryException e) {
615                 invalidate(rectangle, e);
616             } catch (SciRendererException e) {
617                 invalidate(rectangle, e);
618             }
619             axesDrawer.disableClipping(rectangle.getClipProperty());
620         }
621     }
622
623     /*
624      * To do:
625      * -use common code for both the Fac3d and Plot3d visit methods
626      *  as they are mostly similar.
627      */
628     @Override
629     public void visit(final Fac3d fac3d) {
630         if (fac3d.isValid() && fac3d.getVisible()) {
631             axesDrawer.enableClipping(currentAxes, fac3d.getClipProperty());
632             try {
633                 if (fac3d.getSurfaceMode()) {
634                     DefaultGeometry geometry = new DefaultGeometry();
635                     geometry.setVertices(dataManager.getVertexBuffer(fac3d.getIdentifier()));
636                     geometry.setNormals(dataManager.getNormalBuffer(fac3d.getIdentifier()));
637                     geometry.setIndices(dataManager.getIndexBuffer(fac3d.getIdentifier()));
638
639                     geometry.setPolygonOffsetMode(true);
640
641                     /* Front-facing triangles */
642                     Appearance appearance = new Appearance();
643                     appearance.setMaterial(LightingUtils.getMaterial(fac3d.getMaterial()));
644                     LightingUtils.setupLights(drawingTools.getLightManager(), currentAxes);
645
646                     if (fac3d.getColorMode() != 0) {
647                         geometry.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
648                         /* Back-facing triangles */
649                         if (fac3d.getHiddenColor() > 0) {
650                             geometry.setFaceCullingMode(axesDrawer.getBackFaceCullingMode());
651                             Appearance backTrianglesAppearance = new Appearance();
652                             backTrianglesAppearance.setFillColor(ColorFactory.createColor(colorMap, fac3d.getHiddenColor()));
653                             drawingTools.draw(geometry, backTrianglesAppearance);
654
655                             // Now we will draw front face.
656                             geometry.setFaceCullingMode(axesDrawer.getFrontFaceCullingMode());
657                         } else {
658                             geometry.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
659                         }
660
661                         if (fac3d.getColorFlag() == 0) {
662                             appearance.setFillColor(ColorFactory.createColor(colorMap, Math.abs(fac3d.getColorMode())));
663                         } else if (fac3d.getColorFlag() > 0) {
664                             geometry.setTextureCoordinates(dataManager.getTextureCoordinatesBuffer(fac3d.getIdentifier()));
665                             appearance.setTexture(getColorMapTexture());
666                         } else {
667                             geometry.setColors(null);
668                         }
669                     } else {
670                         geometry.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
671                     }
672
673                     if ((fac3d.getColorMode() >= 0) && (fac3d.getLineThickness() > 0.0)) {
674                         geometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
675                         geometry.setWireIndices(dataManager.getWireIndexBuffer(fac3d.getIdentifier()));
676
677                         appearance.setLineColor(ColorFactory.createColor(colorMap, fac3d.getLineColor()));
678                         appearance.setLineWidth(fac3d.getLineThickness().floatValue());
679                     }
680
681                     drawingTools.draw(geometry, appearance);
682                     LightingUtils.setLightingEnable(drawingTools.getLightManager(), false);
683                 }
684
685                 if (fac3d.getMarkMode()) {
686                     Appearance appearance = null;
687                     if (fac3d.getLineThickness() > 0.0) {
688                         appearance = new Appearance();
689                         appearance.setLineWidth(fac3d.getLineThickness().floatValue());
690                     }
691
692                     Texture texture = markManager.getMarkSprite(fac3d, colorMap, appearance);
693                     ElementsBuffer positions = dataManager.getVertexBuffer(fac3d.getIdentifier());
694                     drawingTools.draw(texture, AnchorPosition.CENTER, positions);
695                 }
696             } catch (ObjectRemovedException e) {
697                 invalidate(fac3d, e);
698             } catch (OutOfMemoryException e) {
699                 invalidate(fac3d, e);
700             } catch (SciRendererException e) {
701                 invalidate(fac3d, e);
702             }
703             axesDrawer.disableClipping(fac3d.getClipProperty());
704         }
705     }
706
707     @Override
708     public void visit(final Plot3d plot3d) {
709         if (plot3d.isValid() && plot3d.getVisible()) {
710             axesDrawer.enableClipping(currentAxes, plot3d.getClipProperty());
711             try {
712                 if (plot3d.getSurfaceMode()) {
713                     DefaultGeometry geometry = new DefaultGeometry();
714                     if (plot3d.getColorMode() != 0) {
715                         geometry.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
716                     } else {
717                         geometry.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
718                     }
719
720                     geometry.setPolygonOffsetMode(true);
721
722                     geometry.setVertices(dataManager.getVertexBuffer(plot3d.getIdentifier()));
723                     geometry.setNormals(dataManager.getNormalBuffer(plot3d.getIdentifier()));
724                     geometry.setIndices(dataManager.getIndexBuffer(plot3d.getIdentifier()));
725                     /* Back-facing triangles */
726                     if (plot3d.getHiddenColor() > 0) {
727                         geometry.setFaceCullingMode(axesDrawer.getBackFaceCullingMode());
728                         Appearance backTrianglesAppearance = new Appearance();
729                         backTrianglesAppearance.setFillColor(ColorFactory.createColor(colorMap, plot3d.getHiddenColor()));
730                         drawingTools.draw(geometry, backTrianglesAppearance);
731                     }
732
733                     /* Front-facing triangles */
734                     Appearance appearance = new Appearance();
735                     appearance.setMaterial(LightingUtils.getMaterial(plot3d.getMaterial()));
736                     LightingUtils.setupLights(drawingTools.getLightManager(), currentAxes);
737
738                     if (plot3d.getColorFlag() == 1) {
739                         geometry.setColors(dataManager.getColorBuffer(plot3d.getIdentifier()));
740                     } else {
741                         geometry.setColors(null);
742                     }
743
744                     if (plot3d.getHiddenColor() > 0) {
745                         geometry.setFaceCullingMode(axesDrawer.getFrontFaceCullingMode());
746                     } else {
747                         geometry.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
748                     }
749
750                     if (plot3d.getColorFlag() == 0) {
751                         appearance.setFillColor(ColorFactory.createColor(colorMap, Math.abs(plot3d.getColorMode())));
752                     }
753
754                     if ((plot3d.getColorMode() >= 0) && (plot3d.getLineThickness() > 0.0)) {
755                         geometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
756                         geometry.setWireIndices(dataManager.getWireIndexBuffer(plot3d.getIdentifier()));
757
758                         appearance.setLinePattern(plot3d.getLineStyleAsEnum().asPattern());
759                         appearance.setLineColor(ColorFactory.createColor(colorMap, plot3d.getLineColor()));
760                         appearance.setLineWidth(plot3d.getLineThickness().floatValue());
761                     }
762                     drawingTools.draw(geometry, appearance);
763                     LightingUtils.setLightingEnable(drawingTools.getLightManager(), false);
764                 }
765
766                 if (plot3d.getMarkMode()) {
767                     Appearance appearance = null;
768                     if (plot3d.getLineThickness() > 0.0) {
769                         appearance = new Appearance();
770                         appearance.setLineWidth(plot3d.getLineThickness().floatValue());
771                     }
772
773                     Texture texture = markManager.getMarkSprite(plot3d, colorMap, appearance);
774                     ElementsBuffer positions = dataManager.getVertexBuffer(plot3d.getIdentifier());
775                     drawingTools.draw(texture, AnchorPosition.CENTER, positions);
776                 }
777             } catch (ObjectRemovedException e) {
778                 invalidate(plot3d, e);
779             } catch (OutOfMemoryException e) {
780                 invalidate(plot3d, e);
781             } catch (SciRendererException e) {
782                 invalidate(plot3d, e);
783             }
784             axesDrawer.disableClipping(plot3d.getClipProperty());
785         }
786
787     }
788
789     @Override
790     public void visit(Text text) {
791         if (text.isValid() && text.getVisible()) {
792             axesDrawer.enableClipping(currentAxes, text.getClipProperty());
793             try {
794                 textManager.draw(drawingTools, colorMap, text);
795             } catch (SciRendererException e) {
796                 invalidate(text, e);
797             }
798             axesDrawer.disableClipping(text.getClipProperty());
799         }
800     }
801
802     @Override
803     public void visit(Datatip datatip) {
804         if (datatip.isValid() && datatip.getVisible()) {
805             axesDrawer.enableClipping(currentAxes, datatip.getClipProperty());
806             try {
807                 if (datatip.getMarkMode()) {
808                     /* TODO: appearance can be not-null */
809                     Texture texture = markManager.getMarkSprite(datatip, colorMap, null);
810                     Vector3d markPos = DatatipTextDrawer.calculateAnchorPoint(datatip);
811                     drawingTools.draw(texture, AnchorPosition.CENTER, markPos);
812                 }
813                 if (datatip.getTipLabelMode()) {
814                     datatipTextDrawer.draw(drawingTools, colorMap, datatip);
815                 }
816             } catch (SciRendererException e) {
817                 invalidate((Text)datatip, e);
818             }
819             axesDrawer.disableClipping(datatip.getClipProperty());
820         }
821     }
822
823     @Override
824     public void visit(Arrow arrow) {
825         // TODO
826         System.out.println("How can I draw an arrow ?");
827     }
828
829     @Override
830     public void visit(final Champ champ) {
831         if (champ.isValid() && champ.getVisible()) {
832             axesDrawer.enableClipping(currentAxes, champ.getClipProperty());
833             try {
834                 DefaultGeometry segments = new DefaultGeometry();
835                 segments.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
836                 segments.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
837                 segments.setVertices(dataManager.getVertexBuffer(champ.getIdentifier()));
838                 segments.setWireIndices(dataManager.getWireIndexBuffer(champ.getIdentifier()));
839                 segments.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
840                 if (champ.getColored()) {
841                     segments.setColors(dataManager.getColorBuffer(champ.getIdentifier()));
842                 } else {
843                     segments.setColors(null);
844                 }
845
846                 if (champ.getLineMode()) {
847                     Appearance segmentAppearance = new Appearance();
848
849                     /* If not colored, all segments have the same color. */
850                     if (champ.getColored()) {
851                         segmentAppearance.setLineColor(null);
852                     } else {
853                         segmentAppearance.setLineColor(ColorFactory.createColor(colorMap, champ.getLineColor()));
854                     }
855
856                     segmentAppearance.setLineWidth(champ.getLineThickness().floatValue());
857                     segmentAppearance.setLinePattern(champ.getLineStyleAsEnum().asPattern());
858                     drawingTools.draw(segments, segmentAppearance);
859                 }
860
861                 /* Draw the arrows */
862                 if (champ.getArrowSize() != 0.0) {
863                     arrowDrawer.drawArrows(champ.getParentAxes(), champ.getIdentifier(), champ.getArrowSize(), champ.getLineThickness(), false,
864                                            champ.getColored(), champ.getLineColor(), false);
865                 }
866             } catch (OutOfMemoryException e) {
867                 invalidate(champ, e);
868             } catch (ObjectRemovedException e) {
869                 invalidate(champ, e);
870             } catch (SciRendererException e) {
871                 invalidate(champ, e);
872             }
873             axesDrawer.disableClipping(champ.getClipProperty());
874         }
875     }
876
877     @Override
878     public void visit(final Segs segs) {
879         if (segs.isValid() && segs.getVisible() && segs.getArrows().size() != 0) {
880             axesDrawer.enableClipping(currentAxes, segs.getClipProperty());
881             try {
882                 DefaultGeometry segments = new DefaultGeometry();
883                 segments.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
884                 segments.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
885                 segments.setVertices(dataManager.getVertexBuffer(segs.getIdentifier()));
886                 segments.setColors(dataManager.getColorBuffer(segs.getIdentifier()));
887                 segments.setWireIndices(dataManager.getWireIndexBuffer(segs.getIdentifier()));
888                 segments.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
889
890                 if (segs.getLineMode()) {
891                     Appearance segmentAppearance = new Appearance();
892                     segmentAppearance.setLineColor(null);
893                     segmentAppearance.setLineWidth(segs.getLineThickness().floatValue());
894                     segmentAppearance.setLinePattern(segs.getLineStyleAsEnum().asPattern());
895                     drawingTools.draw(segments, segmentAppearance);
896                 }
897
898                 /*
899                  * Segs does not derive from ContouredObject but Arrow does, hence we have to get the former's first Arrow
900                  * in order to obtain the latter's Mark (all arrows are supposed to have the same contour properties for now).
901                  */
902                 if (segs.getMarkMode()) {
903                     Texture texture = markManager.getMarkSprite(segs.getIdentifier(), segs.getArrows().get(0).getMark(), colorMap, null);
904                     ElementsBuffer positions = dataManager.getVertexBuffer(segs.getIdentifier());
905                     // Take only into account start-end of segs and not the arrow head.
906                     positions.getData().limit(segs.getNumberArrows() * 2 * 4);
907                     drawingTools.draw(texture, AnchorPosition.CENTER, positions);
908                     positions.getData().limit(positions.getData().capacity());
909                 }
910
911                 /* Draw the arrows */
912                 if (segs.getArrowSize() != 0.0) {
913                     arrowDrawer.drawArrows(segs.getParentAxes(), segs.getIdentifier(), segs.getArrowSize(), segs.getLineThickness(), true,
914                                            true, segs.getLineColor(), false);
915                 }
916             } catch (OutOfMemoryException e) {
917                 invalidate(segs, e);
918             } catch (ObjectRemovedException e) {
919                 invalidate(segs, e);
920             } catch (SciRendererException e) {
921                 invalidate(segs, e);
922             }
923             axesDrawer.disableClipping(segs.getClipProperty());
924         }
925     }
926
927     @Override
928     public void updateObject(Integer id, int property) {
929         /*
930          * Check if property is CHILDREN and if there is a new child I should care about
931          */
932         Integer type = (Integer) GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_TYPE__);
933         int objectStyle = (type == GraphicObjectProperties.__GO_UICONTROL__ ? (Integer) GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_STYLE__) : -1);
934         if (id.intValue() != figure.getIdentifier().intValue()
935                 && ((type == GraphicObjectProperties.__GO_UICONTROL__ && objectStyle != GraphicObjectProperties.__GO_UI_FRAME__)
936                     || type == GraphicObjectProperties.__GO_UIMENU__)) {
937             return;
938         }
939
940         if (property == GraphicObjectProperties.__GO_CHILDREN__) {
941             if (id.intValue() != figure.getIdentifier().intValue()) {
942                 /* Ignore children that are not mine */
943                 return;
944             }
945             Integer[] children = GraphicController.getController().getObjectFromId(id).getChildren();
946             List<Integer> currentOpenGLChildren = openGLChildren.get(id);
947             if (currentOpenGLChildren == null) {
948                 /* No openGLChildren in cache, create empty one */
949                 openGLChildren.put(id, new ArrayList<Integer>());
950                 currentOpenGLChildren = openGLChildren.get(id);
951             }
952             List<Integer> updatedOpenGLChildren = new ArrayList<Integer>();
953             for (int i = 0 ; i < children.length ; ++i) {
954                 Integer currentType = (Integer) GraphicController.getController().getProperty(children[i], GraphicObjectProperties.__GO_TYPE__);
955                 if (currentType != GraphicObjectProperties.__GO_UICONTROL__ && currentType != GraphicObjectProperties.__GO_UIMENU__) {
956                     updatedOpenGLChildren.add(children[i]);
957                 }
958             }
959             if (currentOpenGLChildren.size() == updatedOpenGLChildren.size()) {
960                 /* No change made on openGL children => nothing to do */
961                 return;
962             } else {
963                 openGLChildren.put(id, updatedOpenGLChildren);
964             }
965         }
966         try {
967             if (needUpdate(id, property)) {
968                 if (GraphicObjectProperties.__GO_COLORMAP__ == property) {
969                     labelManager.disposeAll();
970                     dataManager.disposeAllColorBuffers();
971                     dataManager.disposeAllTextureCoordinatesBuffers();
972                     markManager.disposeAll();
973                     textManager.disposeAll();
974                     axesDrawer.disposeAll();
975                     fecDrawer.updateAll();
976                     colorMapTextureDataProvider.update();
977                     datatipTextDrawer.disposeAll();
978                     textureManager.disposeAll();
979                 } else {
980                     labelManager.update(id, property);
981                     dataManager.update(id, property);
982                     markManager.update(id, property);
983                     textManager.update(id, property);
984                     axesDrawer.update(id, property);
985                     legendDrawer.update(id, property);
986                     fecDrawer.update(id, property);
987                     datatipTextDrawer.update(id, property);
988                 }
989
990                 if (GraphicObjectProperties.__GO_ANTIALIASING__ == property) {
991                     canvas.setAntiAliasingLevel(figure.getAntialiasing());
992                 }
993
994                 Figure parentFigure = (Figure) GraphicController.getController().getObjectFromId(figure.getParentFigure());
995                 if (figure.getVisible() && parentFigure != null && parentFigure.getVisible()) {
996                     if (figure instanceof Frame || isImmediateDrawing(id)) {
997                         if (figure instanceof Frame || GraphicObjectProperties.__GO_IMMEDIATE_DRAWING__ == property) {
998                             canvas.redrawAndWait();
999                         } else {
1000                             canvas.redraw();
1001                         }
1002                     }
1003                 }
1004             }
1005
1006             if (GraphicObjectProperties.__GO_IMMEDIATE_DRAWING__ == property && !isImmediateDrawing(id)) {
1007                 canvas.waitImage();
1008             }
1009
1010         } catch (OutOfMemoryException e) {
1011             invalidate(GraphicController.getController().getObjectFromId(id), e);
1012         } catch (ObjectRemovedException e) {
1013             // Object has been removed before draw : do nothing.
1014         }
1015     }
1016
1017     /**
1018      * Check if the given changed property make the figure out of date.
1019      * @param id the object updated
1020      * @param property the changed property.
1021      * @return true id the given changed property make the figure out of date.
1022      */
1023     protected boolean needUpdate(Integer id, int property) {
1024         GraphicObject object = GraphicController.getController().getObjectFromId(id);
1025         int objectType = (Integer) GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_TYPE__);
1026         int objectStyle = (objectType == GraphicObjectProperties.__GO_UICONTROL__ ? (Integer) GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_STYLE__) : -1);
1027         if ((object != null) && isFigureChild(id) || (objectType == GraphicObjectProperties.__GO_UICONTROL__ && objectStyle == GraphicObjectProperties.__GO_UI_FRAME__)
1028                 && objectType != GraphicObjectProperties.__GO_UIMENU__ && objectType != GraphicObjectProperties.__GO_UI_FRAME_BORDER__) {
1029
1030             if (GraphicObjectProperties.__GO_VALID__ == property) {
1031                 return false;
1032             }
1033
1034             if (object instanceof Axes) {
1035                 Axes axes = (Axes) object;
1036
1037                 if ((axes.getXAxisAutoTicks() && X_AXIS_TICKS_PROPERTIES.contains(property)) ||
1038                         (axes.getYAxisAutoTicks() && Y_AXIS_TICKS_PROPERTIES.contains(property)) ||
1039                         (axes.getZAxisAutoTicks() && Z_AXIS_TICKS_PROPERTIES.contains(property))) {
1040                     return false;
1041                 }
1042
1043                 if ((!axes.getXAxisAutoTicks() && X_AXIS_TICKS_PROPERTIES.contains(property)) ||
1044                         (!axes.getYAxisAutoTicks() && Y_AXIS_TICKS_PROPERTIES.contains(property)) ||
1045                         (!axes.getZAxisAutoTicks() && Z_AXIS_TICKS_PROPERTIES.contains(property))) {
1046                     axesDrawer.computeMargins(axes);
1047                     return false;
1048                 }
1049
1050                 if (property != GraphicObjectProperties.__GO_CHILDREN__) {
1051                     //axesDrawer.computeRulers(axes);
1052                 }
1053             }
1054
1055             if (object instanceof Label || object instanceof Legend) {
1056                 GraphicObject parent = GraphicController.getController().getObjectFromId(object.getParent());
1057                 if (parent instanceof Axes) {
1058                     Axes axes = (Axes) parent;
1059                     if (axes.getXAxisLabel().equals(id) ||
1060                             axes.getYAxisLabel().equals(id) ||
1061                             axes.getZAxisLabel().equals(id) ||
1062                             axes.getTitle().equals(id)) {
1063                         labelManager.update(id, property);
1064                         axesDrawer.computeMargins(axes);
1065                     } else if (object instanceof Legend && (property == GraphicObjectProperties.__GO_LEGEND_LOCATION__ || property == GraphicObjectProperties.__GO_LINE_WIDTH__)) {
1066                         legendDrawer.update(id, property);
1067                         axesDrawer.computeMargins(axes);
1068                     }
1069                 }
1070             } else if (object instanceof Figure) {
1071                 if (property == GraphicObjectProperties.__GO_SIZE__
1072                         || property == GraphicObjectProperties.__GO_AXES_SIZE__
1073                         || property == GraphicObjectProperties.__GO_CHILDREN__
1074                         || property == GraphicObjectProperties.__GO_POSITION__) {
1075                     Figure fig = (Figure) object;
1076                     for (Integer gid : fig.getChildren()) {
1077                         GraphicObject go = GraphicController.getController().getObjectFromId(gid);
1078                         if (go instanceof Axes) {
1079                             axesDrawer.computeRulers((Axes) go);
1080                         }
1081                     }
1082                 }
1083
1084                 if (SILENT_FIGURE_PROPERTIES.contains(property)) {
1085                     return false;
1086                 }
1087             } else if (object instanceof Frame
1088                        && id.intValue() == figure.getIdentifier().intValue()
1089                        && property == GraphicObjectProperties.__GO_POSITION__) {
1090                 Frame fig = (Frame) object;
1091                 for (Integer gid : fig.getChildren()) {
1092                     GraphicObject go = GraphicController.getController().getObjectFromId(gid);
1093                     if (go instanceof Axes) {
1094                         axesDrawer.computeRulers((Axes) go);
1095                     }
1096                 }
1097
1098             } else if (object instanceof Axes && property == GraphicObjectProperties.__GO_X_AXIS_LOCATION__ ||
1099                        property == GraphicObjectProperties.__GO_Y_AXIS_LOCATION__ || property == GraphicObjectProperties.__GO_AUTO_MARGINS__) {
1100                 axesDrawer.computeMargins((Axes) object);
1101             }
1102
1103             if (!object.isValid()) {
1104                 GraphicController.getController().setProperty(id, GraphicObjectProperties.__GO_VALID__, true);
1105             }
1106
1107             return true;
1108         }
1109         // Special case if top level figure colormap has been updated, force redraw
1110         if (property == GraphicObjectProperties.__GO_COLORMAP__  && id.intValue() == figure.getParentFigure().intValue()) {
1111             return true;
1112         }
1113         return false;
1114     }
1115
1116     private boolean isImmediateDrawing(Integer id) {
1117         Integer parentId = (Integer) GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_PARENT_FIGURE__);
1118         if (parentId == null || !parentId.equals(figure.getIdentifier())) {
1119             return false;
1120         } else {
1121             Boolean b =  (Boolean) GraphicController.getController().getProperty(parentId, GraphicObjectProperties.__GO_IMMEDIATE_DRAWING__);
1122             return (b == null) ? false : b;
1123         }
1124     }
1125
1126     @Override
1127     public void createObject(Integer id) {
1128     }
1129
1130     @Override
1131     public void deleteObject(Integer id) {
1132         Integer type = (Integer) GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_TYPE__);
1133         if (type == GraphicObjectProperties.__GO_UICONTROL__ || type == GraphicObjectProperties.__GO_UIMENU__) {
1134             return; // Not of my managed openGL children
1135         }
1136
1137         openGLChildren.remove(id);
1138
1139         if (isImmediateDrawing(id)) {
1140             canvas.redraw();
1141         }
1142
1143         dataManager.dispose(id);
1144         markManager.dispose(id);
1145         textManager.dispose(id);
1146         labelManager.dispose(id);
1147         axesDrawer.dispose(id);
1148         legendDrawer.dispose(id);
1149         fecDrawer.dispose(id);
1150         textureManager.dispose(id);
1151         /*
1152          * Check we are deleting Figure managed by DrawerVisitor(this)
1153          * Otherwise do nothing on deletion.
1154          */
1155         if (!figure.getIdentifier().equals(id)) {
1156             return;
1157         }
1158
1159         visitorMap.remove(id);
1160         GraphicController.getController().unregister(this);
1161         if (SwingUtilities.isEventDispatchThread()) {
1162             canvas.destroy();
1163         } else {
1164             try {
1165                 SwingUtilities.invokeAndWait(new Runnable() {
1166                     public void run() {
1167                         canvas.destroy();
1168                     }
1169                 });
1170             } catch (Exception e) { }
1171         }
1172     }
1173
1174     /**
1175      * Check if the given id correspond to a child of the current {@see Figure}.
1176      * @param id the given id.
1177      * @return true if the given id correspond to a child of the current {@see Figure}.
1178      */
1179     private boolean isFigureChild(Integer id) {
1180         if (id.intValue() == figure.getIdentifier().intValue()) {
1181             return true;
1182         }
1183
1184         Object parentObject = GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_PARENT__);
1185         Integer parentUID = parentObject == null ? 0 : (Integer) parentObject;
1186         while (parentUID != 0) {
1187
1188             if (figure.getIdentifier().intValue() == parentUID.intValue()) {
1189                 return true;
1190             }
1191
1192             Integer parentStyle = (Integer) GraphicController.getController().getProperty(parentUID, GraphicObjectProperties.__GO_STYLE__);
1193             if (parentStyle != null && parentStyle.intValue() == GraphicObjectProperties.__GO_UI_FRAME__) {
1194                 // Drop drawing if parent is a Frame and I'm not the dedicated visitor.
1195                 return false;
1196             }
1197
1198             parentObject = GraphicController.getController().getProperty(parentUID, GraphicObjectProperties.__GO_PARENT__);
1199             parentUID = parentObject == null ? 0 : (Integer) parentObject;
1200
1201         }
1202         return false;
1203     }
1204
1205     /**
1206      * Invalidate the given graphic object and inform the user.
1207      * @param graphicObject the graphic object to invalidate
1208      * @param exception the cause of invalidation.
1209      */
1210     public void invalidate(GraphicObject graphicObject, Exception exception) {
1211         if (DEBUG_MODE) {
1212             System.err.println("The " + graphicObject.getType() + " \"" + graphicObject.getIdentifier()
1213                                + "\" has been invalidated: " + exception.getMessage());
1214             exception.printStackTrace();
1215         }
1216         GraphicController.getController().setProperty(graphicObject.getIdentifier(), GraphicObjectProperties.__GO_VALID__, false);
1217     }
1218
1219     public LabelManager getLabelManager() {
1220         return labelManager;
1221     }
1222
1223     public Texture getColorMapTexture() {
1224         if (colorMapTexture == null) {
1225             colorMapTexture = canvas.getTextureManager().createTexture();
1226             colorMapTexture.setMagnificationFilter(Texture.Filter.NEAREST);
1227             colorMapTexture.setMinifyingFilter(Texture.Filter.NEAREST);
1228             colorMapTexture.setSWrappingMode(Texture.Wrap.CLAMP);
1229             colorMapTexture.setTWrappingMode(Texture.Wrap.CLAMP);
1230             colorMapTexture.setDataProvider(colorMapTextureDataProvider);
1231         }
1232         return colorMapTexture;
1233     }
1234
1235     /**
1236      * Figure getter.
1237      * @return the figure this visitor draw.
1238      */
1239     public AxesContainer getFigure() {
1240         return figure;
1241     }
1242
1243     private Geometry cube;
1244     public Geometry getCube() {
1245         if (cube == null) {
1246             cube = CubeFactory.createCube(canvas);
1247         }
1248         return cube;
1249     }
1250
1251     /**
1252      * Component getter.
1253      * @return return the attached component.
1254      */
1255     public Component getComponent() {
1256         return component;
1257     }
1258
1259     /**
1260      * Interaction manager getter
1261      * @return the interaction manager.
1262      */
1263     public InteractionManager getInteractionManager() {
1264         return interactionManager;
1265     }
1266
1267     private class ColorMapTextureDataProvider extends AbstractTextureDataProvider {
1268         byte[] whiteColor = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
1269         byte[] blackColor = {0x00, 0x00, 0x00, (byte) 0xFF};
1270
1271         public ColorMapTextureDataProvider() {
1272             super();
1273             this.imageType = ImageType.RGBA_BYTE;
1274         }
1275
1276         @Override
1277         public Dimension getTextureSize() {
1278             return new Dimension(colorMap.getSize() + 2, 1);
1279         }
1280
1281         @Override
1282         public ByteBuffer getData() {
1283             Double[] data = colorMap.getData();
1284             ByteBuffer buffer = ByteBuffer.allocate(4 * ((data.length / 3) + 2));
1285
1286             /* White and black are written in the first and second positions */
1287             buffer.put(whiteColor);
1288             buffer.put(blackColor);
1289
1290             for (int i = 0 ; i < data.length / 3 ; i++) {
1291                 buffer.put(toByte(data[i]));
1292                 buffer.put(toByte(data[i + colorMap.getSize()].floatValue()));
1293                 buffer.put(toByte(data[i + 2 * colorMap.getSize()].floatValue()));
1294                 buffer.put(toByte(1));
1295             }
1296             buffer.rewind();
1297             return buffer;
1298         }
1299
1300         @Override
1301         public ByteBuffer getSubData(int x, int y, int width, int height) {
1302             /*
1303              * For the moment, we presuppose that x and y are 0 and that
1304              * width is equal to the colormap's total size (with height == 1).
1305              * To be correctly implemented.
1306              */
1307             return getData();
1308         }
1309
1310         @Override
1311         public boolean isValid() {
1312             return true;
1313         }
1314
1315         public void update() {
1316             fireUpdate();
1317         }
1318     }
1319 }