2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2011-2012 - DIGITEO - Manuel JULIACHS
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
12 package org.scilab.modules.renderer.JoGLView.legend;
14 import org.scilab.forge.scirenderer.Canvas;
15 import org.scilab.forge.scirenderer.DrawingTools;
16 import org.scilab.forge.scirenderer.SciRendererException;
17 import org.scilab.forge.scirenderer.buffers.ElementsBuffer;
18 import org.scilab.forge.scirenderer.buffers.IndicesBuffer;
19 import org.scilab.forge.scirenderer.shapes.appearance.Appearance;
20 import org.scilab.forge.scirenderer.shapes.geometry.DefaultGeometry;
21 import org.scilab.forge.scirenderer.shapes.geometry.Geometry;
22 import org.scilab.forge.scirenderer.texture.AnchorPosition;
23 import org.scilab.forge.scirenderer.texture.Texture;
24 import org.scilab.forge.scirenderer.texture.TextureManager;
25 import org.scilab.forge.scirenderer.tranformations.Transformation;
26 import org.scilab.forge.scirenderer.tranformations.TransformationFactory;
27 import org.scilab.forge.scirenderer.tranformations.TransformationStack;
28 import org.scilab.forge.scirenderer.tranformations.Vector3d;
29 import org.scilab.modules.graphic_objects.axes.Axes;
30 import org.scilab.modules.graphic_objects.figure.ColorMap;
31 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
32 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
33 import org.scilab.modules.graphic_objects.legend.Legend;
34 import org.scilab.modules.graphic_objects.legend.Legend.LegendLocation;
35 import org.scilab.modules.graphic_objects.polyline.Polyline;
36 import org.scilab.modules.renderer.JoGLView.DrawerVisitor;
37 import org.scilab.modules.renderer.JoGLView.mark.MarkSpriteManager;
38 import org.scilab.modules.renderer.JoGLView.util.ColorFactory;
40 import java.awt.Dimension;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.HashSet;
46 import java.util.concurrent.ConcurrentHashMap;
51 * Utility class used by DrawerVisitor to draw the Legend object.
55 * - modify bounds depending on the location (for OUT_* values)
56 * - take into account the actual tick/label size (instead of an arbitrary value)
57 * - implement box clipping mode
58 * - use the GraphicController to update links / move the update code somewhere else
59 * in order to perform it when objects are deleted, add the Links property to the set of
60 * properties affecting the sprite's update.
62 * @author Manuel JULIACHS
64 public class LegendDrawer {
67 * Set of properties that affect the legend sprite
69 private static final Set<Integer> SPRITE_PROPERTIES = new HashSet<Integer>(Arrays.asList(
70 GraphicObjectProperties.__GO_FONT_SIZE__,
71 GraphicObjectProperties.__GO_FONT_COLOR__,
72 GraphicObjectProperties.__GO_FONT_STYLE__,
73 GraphicObjectProperties.__GO_FONT_FRACTIONAL__,
74 GraphicObjectProperties.__GO_TEXT_ARRAY_DIMENSIONS__,
75 GraphicObjectProperties.__GO_TEXT_STRINGS__
78 /** The height of a bar relative to the height difference between two lines */
79 private static final float BAR_HEIGHT = 0.5f;
81 /** The DrawerVisitor used */
82 private final DrawerVisitor visitor;
84 /** The SpriteManager used */
85 private final TextureManager textureManager;
87 /** The MarkSpriteManager used */
88 private final MarkSpriteManager markManager;
90 /** The Legend sprite drawer */
91 private LegendSpriteDrawer legendSpriteDrawer;
93 /** The relative line width */
94 private static final double LINE_WIDTH = 0.1;
96 /** The relative y-offset */
97 private static final double Y_OFFSET = 0.01;
99 /** The relative tick and label size (arbitrarily chosen) */
100 private static final double TICK_LABEL_SIZE = 0.055;
102 /** The z-value corresponding to the frontmost position */
103 private static final float Z_FRONT = 0.99f;
105 /** The legend background's vertices */
106 private ElementsBuffer rectangleVertices;
108 /** The vertices used to draw lines */
109 private ElementsBuffer lineVertices;
111 /** The vertices used to draw bars */
112 private ElementsBuffer barVertices;
114 /** The indices used to draw lines */
115 private IndicesBuffer lineIndices;
117 /** The indices used to draw a rectangle */
118 private IndicesBuffer rectangleIndices;
120 /** The indices used to draw the outline of a rectangle */
121 private IndicesBuffer rectangleOutlineIndices;
123 /** The map storing legend text sprites */
124 private Map<Integer, Texture> textureMap;
128 * @param visitor the DrawerVisitor {@see DrawerVisitor}.
130 public LegendDrawer(DrawerVisitor visitor) {
131 this.visitor = visitor;
132 this.textureManager = visitor.getCanvas().getTextureManager();
133 this.markManager = visitor.getMarkManager();
135 rectangleVertices = visitor.getCanvas().getBuffersManager().createElementsBuffer();
136 lineVertices = visitor.getCanvas().getBuffersManager().createElementsBuffer();
137 barVertices = visitor.getCanvas().getBuffersManager().createElementsBuffer();
138 lineIndices = visitor.getCanvas().getBuffersManager().createIndicesBuffer();
139 rectangleIndices = visitor.getCanvas().getBuffersManager().createIndicesBuffer();
140 rectangleOutlineIndices = visitor.getCanvas().getBuffersManager().createIndicesBuffer();
142 textureMap = new ConcurrentHashMap<Integer, Texture>();
144 int[] lineIndexData = new int[] {0, 1, 1, 2};
145 lineIndices.setData(lineIndexData);
149 * Draws the given Legend.
150 * @param legend the Legend to draw.
151 * @throws SciRendererException if the draw fail.
153 public void draw(Legend legend) throws SciRendererException {
154 /* The coordinates of the legend box's lower-left corner */
155 double [] legendCorner = new double[] {0.25, 0.75, Z_FRONT};
157 DrawingTools drawingTools = visitor.getDrawingTools();
158 ColorMap colorMap = visitor.getColorMap();
159 Canvas canvas = visitor.getCanvas();
161 Integer [] links = legend.getLinks();
164 * Determine whether any links have become invalid,
165 * force the sprite's update and update the Legend's
166 * links property as needed.
168 int nbValidLinks = getNumberValidLinks(legend);
170 if (nbValidLinks < links.length) {
171 dispose(legend.getIdentifier());
172 updateLinks(legend, nbValidLinks);
175 links = legend.getLinks();
178 * Set the projection and modelview transformations so that coordinates
179 * are specified in the {0,+1,0,+1,0,+1} space.
181 TransformationStack modelViewStack = drawingTools.getTransformationManager().getModelViewStack();
182 TransformationStack projectionStack = drawingTools.getTransformationManager().getProjectionStack();
184 Transformation identity = TransformationFactory.getIdentity();
185 modelViewStack.push(identity);
187 Transformation orthoProj = TransformationFactory.getOrthographic(0.0, 1.0, 0.0, 1.0, -1.0, 0.0);
188 projectionStack.push(orthoProj);
191 /* First, compute the legend box's position and dimensions from the Axes' parameters and the text sprite's dimensions */
193 Integer parentAxesID = legend.getParentAxes();
194 Axes parentAxes = (Axes) GraphicController.getController().getObjectFromId(parentAxesID);
196 Double [] axesBounds = parentAxes.getAxesBounds();
197 Double [] margins = parentAxes.getMargins();
199 int xAxisLocation = parentAxes.getXAxisLocation();
200 int yAxisLocation = parentAxes.getYAxisLocation();
203 int canvasWidth = canvas.getWidth();
204 int canvasHeight = canvas.getHeight();
206 if (canvasWidth == 0) {
210 if (canvasHeight == 0) {
214 Texture legendSprite = null;
216 if (nbValidLinks > 0) {
217 legendSprite = getTexture(colorMap, legend);
220 double normSpriteWidth = 0;
221 double normSpriteHeight = 0;
223 if (nbValidLinks > 0) {
224 Dimension textureSize = legendSprite.getDataProvider().getTextureSize();
225 normSpriteWidth = textureSize.getWidth() / (double) canvasWidth;
226 normSpriteHeight = textureSize.getHeight() / (double) canvasHeight;
231 /* The legend box's width and height */
232 double [] legendDims = new double[2];
234 double [] axesPos = new double[2];
235 double [] axesDims = new double[2];
237 lineWidth = LINE_WIDTH * (axesBounds[2]) * (1.0 - margins[0] - margins[1]);
239 double xOffset = lineWidth / 8.0;
240 double yOffset = (Y_OFFSET * (axesBounds[3]) * (1.0 - margins[2] - margins[3]));
242 legendDims[0] = normSpriteWidth + lineWidth + 3.0 * xOffset;
243 legendDims[1] = normSpriteHeight + 2.0 * yOffset;
245 /* Save the legend box size */
246 Double[] DimsToSet = { legendDims[0], legendDims[1]};
247 legend.setSize(DimsToSet);
249 axesPos[0] = axesBounds[0];
250 axesPos[1] = 1.0 - (axesBounds[1] + axesBounds[3]);
252 axesDims[0] = axesBounds[2];
253 axesDims[1] = axesBounds[3];
255 /* The {x, y} coordinates of the axes box's lower-left and upper-right corners (as defined by bounds and margins) */
256 double [] llBoxCorner = new double[2];
257 double [] urBoxCorner = new double[2];
259 LegendLocation legendLocation = legend.getLegendLocationAsEnum();
261 llBoxCorner[0] = axesPos[0] + margins[0] * axesDims[0];
262 llBoxCorner[1] = axesPos[1] + margins[3] * axesDims[1];
264 urBoxCorner[0] = axesPos[0] + (1.0 - margins[1]) * axesDims[0];
265 urBoxCorner[1] = axesPos[1] + (1.0 - margins[2]) * axesDims[1];
267 if (legendLocation == LegendLocation.IN_UPPER_RIGHT) {
268 legendCorner[0] = (float) (urBoxCorner[0] - xOffset - legendDims[0]);
269 legendCorner[1] = (float) (urBoxCorner[1] - yOffset - legendDims[1]);
270 } else if (legendLocation == LegendLocation.IN_UPPER_LEFT) {
271 legendCorner[0] = (float) (llBoxCorner[0] + xOffset);
272 legendCorner[1] = (float) (urBoxCorner[1] - yOffset - legendDims[1]);
273 } else if (legendLocation == LegendLocation.IN_LOWER_RIGHT) {
274 legendCorner[0] = (float) (urBoxCorner[0] - xOffset - legendDims[0]);
275 legendCorner[1] = (float) (llBoxCorner[1] + yOffset);
276 } else if (legendLocation == LegendLocation.IN_LOWER_LEFT) {
277 legendCorner[0] = (float) (llBoxCorner[0] + xOffset);
278 legendCorner[1] = (float) (llBoxCorner[1] + yOffset);
279 } else if (legendLocation == LegendLocation.OUT_UPPER_RIGHT) {
280 legendCorner[0] = (float) (urBoxCorner[0] + xOffset);
281 legendCorner[1] = (float) (urBoxCorner[1] - legendDims[1]);
282 } else if (legendLocation == LegendLocation.OUT_UPPER_LEFT) {
283 legendCorner[0] = (float) (llBoxCorner[0] - xOffset - legendDims[0]);
284 legendCorner[1] = (float) (urBoxCorner[1] - legendDims[1]);
285 } else if (legendLocation == LegendLocation.OUT_LOWER_RIGHT) {
286 legendCorner[0] = (float) (urBoxCorner[0] + xOffset);
287 legendCorner[1] = (float) (llBoxCorner[1]);
288 } else if (legendLocation == LegendLocation.OUT_LOWER_LEFT) {
289 legendCorner[0] = (float) (llBoxCorner[0] - xOffset - legendDims[0]);
290 legendCorner[1] = (float) (llBoxCorner[1]);
291 } else if (legendLocation == LegendLocation.UPPER_CAPTION) {
292 legendCorner[0] = (float) (llBoxCorner[0]);
293 legendCorner[1] = (float) (urBoxCorner[1] + yOffset);
295 /* x-axis at the top */
296 if (xAxisLocation == 1) {
297 /* To do: use the actual label+tick bounding box height */
298 legendCorner[1] += TICK_LABEL_SIZE;
300 } else if (legendLocation == LegendLocation.LOWER_CAPTION) {
301 legendCorner[0] = (float) (llBoxCorner[0]);
302 legendCorner[1] = (float) (llBoxCorner[1] - yOffset - legendDims[1]);
304 /* x-axis at the bottom */
305 if (xAxisLocation == 0) {
306 /* To do: use the actual label+tick bounding box height */
307 legendCorner[1] -= TICK_LABEL_SIZE;
309 } else if (legendLocation == LegendLocation.BY_COORDINATES) {
310 Double [] legPos = legend.getPosition();
312 legendCorner[0] = (float) (axesPos[0] + legPos[0] * axesBounds[2]);
313 legendCorner[1] = (float) (axesPos[1] + (1.0 - legPos[1]) * axesBounds[3] - legendDims[1]);
316 /* y-axis positioned to the left */
317 if ((legendLocation == LegendLocation.OUT_UPPER_LEFT || legendLocation == LegendLocation.OUT_LOWER_LEFT) && yAxisLocation == 4) {
318 /* To do: use the actual label+tick bounding box width */
319 legendCorner[0] -= TICK_LABEL_SIZE;
320 /* y-axis positioned to the right */
321 } else if ((legendLocation == LegendLocation.OUT_UPPER_RIGHT || legendLocation == LegendLocation.OUT_LOWER_RIGHT) && yAxisLocation == 5) {
322 /* To do: use the actual label+tick bounding box width */
323 legendCorner[0] += TICK_LABEL_SIZE;
327 /* Afterwards, draw the elements making up the Legend using the previously computed values */
329 /* Legend background vertex data: lower-left, lower-right, upper-left and upper-right corners */
330 float [] rectangleVertexData = new float[] {
331 (float)legendCorner[0], (float)legendCorner[1], Z_FRONT, 1.0f,
332 (float)(legendCorner[0] + legendDims[0]), (float)legendCorner[1], Z_FRONT, 1.0f,
333 (float)legendCorner[0], (float)(legendCorner[1] + legendDims[1]), Z_FRONT, 1.0f,
334 (float)(legendCorner[0] + legendDims[0]), (float)(legendCorner[1] + legendDims[1]), Z_FRONT, 1.0f
337 /* The indices of a rectangle's triangles and a rectangle outline's segment loop */
338 int[] rectangleIndexData = new int[] {0, 1, 3, 0, 3, 2};
339 int[] rectangleOutlineIndexData = new int[] {0, 1, 1, 3, 3, 2, 2, 0};
341 rectangleIndices.setData(rectangleIndexData);
342 rectangleOutlineIndices.setData(rectangleOutlineIndexData);
344 rectangleVertices.setData(rectangleVertexData, 4);
346 /* Legend rectangle background and outline */
347 DefaultGeometry legendRectangle = new DefaultGeometry();
348 legendRectangle.setVertices(rectangleVertices);
349 legendRectangle.setIndices(rectangleIndices);
351 Appearance appearance = new Appearance();
353 if (legend.getFillMode()) {
354 legendRectangle.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
355 appearance.setFillColor(ColorFactory.createColor(colorMap, legend.getBackground()));
357 legendRectangle.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
361 if (legend.getLineMode()) {
362 legendRectangle.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
363 legendRectangle.setWireIndices(rectangleOutlineIndices);
365 appearance.setLineColor(ColorFactory.createColor(colorMap, legend.getLineColor()));
366 appearance.setLineWidth(legend.getLineThickness().floatValue());
367 appearance.setLinePattern(legend.getLineStyleAsEnum().asPattern());
369 legendRectangle.setLineDrawingMode(Geometry.LineDrawingMode.NONE);
372 drawingTools.draw(legendRectangle, appearance);
374 /* Lines: 3 vertices each, left, middle, and right */
375 float [] lineVertexData = new float[] {0.25f, 0.75f, Z_FRONT, 1.0f,
376 0.5f, 0.75f, Z_FRONT, 1.0f,
377 0.75f, 0.75f, Z_FRONT, 1.0f
380 double normSpriteMargin = 0.0;
382 if (nbValidLinks > 0) {
383 normSpriteMargin = (double) legendSpriteDrawer.getVMargin() / (double) canvasHeight;
386 lineVertexData[0] = (float) (legendCorner[0] + xOffset);
387 lineVertexData[1] = (float) (legendCorner[1] + normSpriteMargin + yOffset);
389 lineVertexData[8] = lineVertexData[0] + (float) lineWidth;
390 lineVertexData[9] = lineVertexData[1];
392 lineVertexData[4] = 0.5f * (lineVertexData[0] + lineVertexData[8]);
393 lineVertexData[5] = lineVertexData[1];
395 float deltaHeight = 0.0f;
397 if (links.length > 0) {
398 deltaHeight = (float) (normSpriteHeight - 2.0 * normSpriteMargin) / ((float)(links.length));
401 lineVertexData[1] = lineVertexData[1] + 0.5f * deltaHeight;
402 lineVertexData[5] = lineVertexData[5] + 0.5f * deltaHeight;
403 lineVertexData[9] = lineVertexData[9] + 0.5f * deltaHeight;
405 /* Bar vertex data: lower-left, lower-right, upper-left and upper-right corners */
406 float [] barVertexData = new float[] {0.25f, 0.75f, Z_FRONT, 1.0f,
407 0.75f, 0.75f, Z_FRONT, 1.0f,
408 0.25f, 1.00f, Z_FRONT, 1.0f,
409 0.75f, 1.00f, Z_FRONT, 1.0f
412 float barHeight = BAR_HEIGHT * deltaHeight;
414 barVertexData[0] = (float) (legendCorner[0] + xOffset);
415 barVertexData[1] = (float) (legendCorner[1] + normSpriteMargin + yOffset) + 0.5f * (deltaHeight - barHeight);
417 barVertexData[4] = barVertexData[0] + (float) lineWidth;
418 barVertexData[5] = barVertexData[1];
420 barVertexData[8] = barVertexData[0];
421 barVertexData[9] = barVertexData[1] + barHeight;
423 barVertexData[12] = barVertexData[4];
424 barVertexData[13] = barVertexData[9];
426 for (Integer link : links) {
427 Polyline currentLine = (Polyline) GraphicController.getController().getObjectFromId(link);
429 drawLegendItem(drawingTools, colorMap, currentLine, barVertexData, lineVertexData);
431 /* Update the vertex data's vertical position */
432 lineVertexData[1] += deltaHeight;
433 lineVertexData[5] += deltaHeight;
434 lineVertexData[9] += deltaHeight;
436 barVertexData[1] += deltaHeight;
437 barVertexData[5] += deltaHeight;
438 barVertexData[9] += deltaHeight;
439 barVertexData[13] += deltaHeight;
443 float [] spritePosition = new float[] {lineVertexData[8] + (float) xOffset, (float) (legendCorner[1] + yOffset), Z_FRONT};
445 /* Draw the sprite only if there are valid links */
446 if (nbValidLinks > 0) {
447 drawingTools.draw(legendSprite, AnchorPosition.LOWER_LEFT, new Vector3d(spritePosition));
450 /* Restore the transformation stacks */
451 modelViewStack.pop();
452 projectionStack.pop();
454 /* Output the position if required */
455 Double [] legendPosition = new Double[2];
457 if (axesDims[0] == 0.0) {
461 if (axesDims[1] == 0.0) {
465 legendPosition[0] = (legendCorner[0] - axesPos[0]) / axesDims[0];
466 legendPosition[1] = 1.0 - (legendCorner[1] + legendDims[1] - axesPos[1]) / axesDims[1];
468 if (legendLocation != LegendLocation.BY_COORDINATES) {
469 legend.setPosition(legendPosition);
474 * Draw the legend item corresponding to the given polyline.
475 * It draws either a horizontal line or bar depending on the polyline's properties (style, fill and line modes).
476 * @param drawingTools the DrawingTools {@see DrawingTools} used to draw the Legend.
477 * @param colorMap the colorMap used.
478 * @param polyline the given polyline.
479 * @param barVertexData a bar's vertex data (4 consecutive (x,y,z,w) quadruplets: lower-left, lower-right, upper-left and upper-right corners.
480 * @param lineVertexData a line's vertex data (3 consecutive (x,y,z,w) quadruplets: left, middle and right vertices).
481 * @throws org.scilab.forge.scirenderer.SciRendererException if the draw fail.
483 private void drawLegendItem(DrawingTools drawingTools, ColorMap colorMap, Polyline polyline, float[] barVertexData, float[] lineVertexData) throws SciRendererException {
484 int polylineStyle = polyline.getPolylineStyle();
486 int lineColor = polyline.getLineColor();
487 double lineThickness = polyline.getLineThickness();
488 short linePattern = polyline.getLineStyleAsEnum().asPattern();
490 boolean isBar = (polylineStyle == 6) || (polylineStyle == 7);
491 boolean barDrawn = isBar || polyline.getFillMode();
493 /* Draw a bar if the curve is a bar or if it is filled */
495 barVertices.setData(barVertexData, 4);
497 DefaultGeometry bar = new DefaultGeometry();
498 bar.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
500 Appearance barAppearance = new Appearance();
501 barAppearance.setFillColor(ColorFactory.createColor(colorMap, polyline.getBackground()));
502 bar.setVertices(barVertices);
503 bar.setIndices(rectangleIndices);
506 if (isBar || polyline.getLineMode()) {
507 bar.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
508 bar.setWireIndices(rectangleOutlineIndices);
510 barAppearance.setLineColor(ColorFactory.createColor(colorMap, polyline.getLineColor()));
511 barAppearance.setLineWidth((float) lineThickness);
512 barAppearance.setLinePattern(linePattern);
514 bar.setLineDrawingMode(Geometry.LineDrawingMode.NONE);
517 drawingTools.draw(bar, barAppearance);
520 /* Draw a line otherwise */
522 lineVertices.setData(lineVertexData, 4);
524 /* A line must also be drawn for the vertical polyline style (3), whatever line mode's value */
525 if (polyline.getLineMode() || polylineStyle == 3) {
526 DefaultGeometry line = new DefaultGeometry();
527 line.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
528 line.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS_STRIP);
529 line.setVertices(lineVertices);
530 Appearance lineAppearance = new Appearance();
531 lineAppearance.setLineColor(ColorFactory.createColor(colorMap, lineColor));
532 lineAppearance.setLineWidth((float) lineThickness);
533 lineAppearance.setLinePattern(linePattern);
535 drawingTools.draw(line, lineAppearance);
540 if (polylineStyle == 4) {
543 * Overlap can occur between the arrow heads of the bar's two smallest segments and the adjacent items.
544 * To do: adjust arrow size to correct this.
546 visitor.getArrowDrawer().drawArrows(polyline.getParentAxes(), barVertices, rectangleOutlineIndices,
547 polyline.getArrowSizeFactor(), lineThickness, lineColor, false);
549 visitor.getArrowDrawer().drawArrows(polyline.getParentAxes(), lineVertices, lineIndices,
550 polyline.getArrowSizeFactor(), lineThickness, lineColor, false);
554 if (polyline.getMarkMode()) {
555 Appearance lineAppearance = new Appearance();
556 lineAppearance.setLineWidth((float) lineThickness);
557 Texture markTexture = markManager.getMarkSprite(polyline, colorMap, lineAppearance);
559 drawingTools.draw(markTexture, AnchorPosition.CENTER, barVertices);
561 drawingTools.draw(markTexture, AnchorPosition.CENTER, lineVertices);
568 * Updates the legend by disposing its sprite.
569 * @param id the legend id.
570 * @param property the property to update.
572 public void update(Integer id, int property) {
573 if (textureMap.containsKey(id)) {
574 if (SPRITE_PROPERTIES.contains(property)) {
581 * Disposes the Legend sprite corresponding to the given id.
582 * @param id the legend id.
584 public void dispose(Integer id) {
585 Texture texture = textureMap.get(id);
586 if (texture != null) {
587 textureManager.dispose(texture);
588 textureMap.remove(id);
593 * Disposes all the Legend resources.
595 public void disposeAll() {
596 visitor.getCanvas().getBuffersManager().dispose(rectangleVertices);
597 visitor.getCanvas().getBuffersManager().dispose(lineVertices);
598 visitor.getCanvas().getBuffersManager().dispose(barVertices);
599 visitor.getCanvas().getBuffersManager().dispose(lineIndices);
600 visitor.getCanvas().getBuffersManager().dispose(rectangleIndices);
601 visitor.getCanvas().getBuffersManager().dispose(rectangleOutlineIndices);
603 textureManager.dispose(textureMap.values());
608 * Returns the legend text texture.
609 * @param colorMap the color map.
610 * @param legend the Legend.
611 * @return the text sprite.
613 private Texture getTexture(ColorMap colorMap, Legend legend) {
614 Texture texture = textureMap.get(legend.getIdentifier());
615 if (texture == null) {
616 this.legendSpriteDrawer = new LegendSpriteDrawer(colorMap, legend);
617 texture = textureManager.createTexture();
618 texture.setDrawer(legendSpriteDrawer);
619 textureMap.put(legend.getIdentifier(), texture);
625 * Determines and returns the number of valid links for the given Legend object.
626 * @param legend the given Legend.
627 * @return the number of valid links.
629 private int getNumberValidLinks(Legend legend) {
630 int nbValidLinks = 0;
631 Integer [] links = legend.getLinks();
633 for (Integer link : links) {
634 Polyline currentLine = (Polyline) GraphicController.getController().getObjectFromId(link);
636 if (currentLine != null) {
645 * Updates the links and text properties of the Legend depending
646 * on the number of valid links provided (the number of links
647 * to non-null objects).
648 * To do: use the graphic controller to perform the update;
649 * move the link update from LegendDrawer to somewhere more appropriate.
650 * @param legend the Legend to update.
651 * @param nbValidLinks the number of valid links.
653 private void updateLinks(Legend legend, int nbValidLinks) {
655 ArrayList <Integer> newLinks = new ArrayList<Integer>(0);
657 Integer[] newDims = new Integer[2];
660 * In case there are no valid links, we create a single empty String
661 * in order to retain the Legend's font properties.
663 if (nbValidLinks == 0) {
666 newDims[0] = nbValidLinks;
671 newStrings = new String[newDims[0]];
673 if (nbValidLinks == 0) {
674 newStrings[0] = new String("");
677 Integer[] links = legend.getLinks();
678 String[] strings = legend.getTextStrings();
680 for (int i = 0; i < links.length; i++) {
681 Polyline currentLine = (Polyline) GraphicController.getController().getObjectFromId(links[i]);
683 /* Text strings are stored in reverse order relative to links. */
684 if (currentLine != null) {
685 newLinks.add(links[i]);
687 newStrings[nbValidLinks - i1 - 1] = new String(strings[strings.length - i - 1]);
692 /* Update the legend's links and text */
693 legend.setLinks(newLinks);
695 legend.setTextArrayDimensions(newDims);
696 legend.setTextStrings(newStrings);