package org.expeditee.gui; import java.awt.Polygon; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.Map; import org.expeditee.items.Item; import org.expeditee.items.Text; public class FreeItems extends ArrayList { private static final long serialVersionUID = 1L; private static FreeItems _instance = new FreeItems(); private static FreeItems _cursor = new FreeItems(); private FreeItems() { } public static FreeItems getCursor() { return _cursor; } public static FreeItems getInstance() { return _instance; } @Override public void clear() { for (Item i : this) { i.invalidateAll(); i.invalidateFill(); } super.clear(); } @Override public Item remove(int index) { Item i = get(index); remove(i); return i; } @Override public boolean remove(Object o) { if (o instanceof Item) { ((Item) o).invalidateAll(); ((Item) o).invalidateFill(); } return super.remove(o); } /** * Return true if there is at least one item attached to the end of the * cursor. * * @return true if at least one item is attached to the cursor. */ public static boolean itemsAttachedToCursor() { return getInstance().size() > 0; } /** * Checks if only text items are attached to the cursor. * * @return true if at least one item is attached to the cursor and all items * attached are text items. */ public static boolean textOnlyAttachedToCursor() { if (!itemsAttachedToCursor()) return false; for (Item i : getInstance()) { if (!(i instanceof Text)) { return false; } } return true; } public static Item getItemAttachedToCursor() { if (itemsAttachedToCursor()) return getInstance().get(0); return null; } public static Text getTextAttachedToCursor() { if (textOnlyAttachedToCursor()) return (Text) getInstance().get(0); return null; } /** * Creates a list of the free text items. * @return the list of free text items */ public static Collection getTextItems() { Collection textItems = new LinkedList(); for (Item i : getInstance()) { if (i instanceof Text) { textItems.add((Text) i); } } return textItems; } public static Map> getGroupedText() { Map> groupedText = new HashMap>(); // Go throught the lineEnds Collection addedItems = new HashSet(); for (Item i : getInstance()) { if (!(i instanceof Text) || !i.isLineEnd()) { continue; } // Check for text inside the box Collection textList = new LinkedList(); for (Text enclosed : getInstance().getTextWithin(i)) { textList.add(enclosed.getText()); addedItems.add(enclosed); } if (textList.size() > 0) { groupedText.put(i.getText(), textList); } } // Now add the items that were not contained in any of the boxes Collection outsideList = new LinkedList(); for (Item i : getInstance()) { if (i instanceof Text && !i.isLineEnd() && !addedItems.contains(i)) { outsideList.add(i.getText()); } } groupedText.put("", outsideList); return groupedText; } /** * Gets a list of non-line-end text items within a specified rectangle in * the free items list. * * @param lineEnd * @return */ private Collection getTextWithin(Item lineEnd) { Polygon poly = lineEnd.getEnclosedShape(); Collection results = new LinkedHashSet(); for (Item i : this) { if (i.intersects(poly) && i instanceof Text && !i.isLineEnd()) { results.add((Text) i); } } return results; } public static boolean hasCursor() { return getCursor().size() > 0; } public static void setCursor(Collection cursor) { _cursor.clear(); _cursor.addAll(cursor); } }