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