/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package org.geogebra.common.euclidian; //import java.awt.Graphics2D; import java.util.Iterator; import java.util.NoSuchElementException; import org.geogebra.common.awt.GGraphics2D; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoList; /** * List to store Drawable objects for fast drawing. */ public class DrawableList { /** first drawable in the list */ public Link head; private Link tail; private int size = 0; /** * Number of drawables in list * * @return number of drawables in list */ public final int size() { return size; } /** * Inserts d at the end of the list. * * @param d * Drawable to be inserted */ public final void add(Drawable d) { if (d == null) { return; } if (head == null) { head = new Link(d, null); tail = head; } else { // Michael Borcherds 2008-02-29 BEGIN // add in the list according to when we want it drawn GeoElement priority = d.getGeoElement(); Link cur = head; Link last = head; while ((cur.d.getGeoElement().drawBefore(priority, false)) && !cur.equals(tail)) { last = cur; cur = cur.next; } if (cur.equals(head)) { if (cur.d.getGeoElement().drawBefore(priority, false)) {// add // at // end // (list // size=1) Link temp = new Link(d, null); tail.next = temp; tail = temp; } else { // add at start of list Link temp2 = head; head = new Link(d, null); head.next = temp2; } } else if (cur.equals(tail)) { if ((cur.d.getGeoElement().drawBefore(priority, false))) { // add at end Link temp = new Link(d, null); tail.next = temp; tail = temp; } else { // add one from end Link temp = new Link(d, null); temp.next = last.next; last.next = temp; } } else { // add in middle // Application.debug("middle"); // Link temp = new Link(d, null); // temp.next=cur.next; // cur.next = temp; Link temp = new Link(d, null); temp.next = last.next; last.next = temp; } // Michael Borcherds 2008-02-29 END } size++; } /** * Inserts d at the end of the list only if the list doesn't already contain * d. * * @param d * drawable to be added */ public final void addUnique(Drawable d) { if (!contains(d)) { add(d); } } /** * Returns true iff d is in this list. * * @param d * Drawable to be looked for * @return true iff d is in this list. */ public final boolean contains(Drawable d) { Link cur = head; while (cur != null) { if (cur.d == d) { return true; } cur = cur.next; } return false; } /** * Removes d from list. * * @param d * Drawable to be removed */ public final void remove(Drawable d) { Link prev = null; Link cur = head; while (cur != null) { // found algo to remove if (cur.d == d) { if (prev == null) { // remove from head head = cur.next; if (head == null) { tail = null; } } else { // standard case prev.next = cur.next; if (prev.next == null) { tail = prev; } } size--; return; } // not yet found prev = cur; cur = cur.next; } } /** * Draws all drawables in the list. * * @param g2 * Graphic to be used */ public final void drawAll(GGraphics2D g2) { Link cur = head; while (cur != null) { // defined check needed in case the GeoList changed its size // don't draw GeoList as combos here GeoElement geo = cur.d.getGeoElement(); if (geo.isDefined() && !(geo.isGeoList() && ((GeoList) geo).drawAsComboBox()) && !(geo.isGeoInputBox())) { if (cur.d.needsUpdate()) { cur.d.setNeedsUpdate(false); cur.d.update(); } cur.d.draw(g2); } cur = cur.next; } } /** * Updates all drawables in list */ public final void updateAll() { Link cur = head; while (cur != null) { cur.d.update(); cur = cur.next; } } /** * Update all elements when view was updated */ public final void updateAllForView() { Link cur = head; while (cur != null) { cur.d.updateForView(); cur = cur.next; } } /** * Updates fot size for all drawables in list */ public final void updateFontSizeAll() { Link cur = head; while (cur != null) { cur.d.updateFontSize(); cur = cur.next; } } /** * Empties the list */ public void clear() { head = null; tail = null; size = 0; } /** * Linked list of drawables */ public static class Link { /** drawable */ public Drawable d; /** next element */ public Link next; /** * @param a * drawable * @param n * next */ Link(Drawable a, Link n) { d = a; next = n; } } /** * Returns iterator pointing to head of the list * * @return iterator pointing to head of the list */ public DrawableIterator getIterator() { return new DrawableIterator(); } /** * Allows iteration over the list * */ public class DrawableIterator implements Iterator<Drawable> { private Link it; /** * Creates new drawable iterator */ DrawableIterator() { reset(); } @Override final public Drawable next() { if (it == null) { throw new NoSuchElementException(); } Drawable ret = it.d; it = it.next; return ret; } @Override final public boolean hasNext() { return (it != null); } /** * Resets the iterator to the head of the list */ final public void reset() { it = head; } @Override final public void remove() { // do nothing } } }