// This file is part of AceWiki. // Copyright 2008-2013, AceWiki developers. // // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU // Lesser General Public License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If // not, see http://www.gnu.org/licenses/. package ch.uzh.ifi.attempto.preditor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import nextapp.echo.app.event.ActionEvent; import nextapp.echo.app.event.ActionListener; /** * This class represents the content of a menu block. The content consists of menu items. * * @author Tobias Kuhn */ class MenuBlockContent implements ActionListener { private static final long serialVersionUID = 2320151987455571216L; private List<MenuItem> items = new ArrayList<MenuItem>(); private TreeMap<String, MenuEntry> entryMap = new TreeMap<String, MenuEntry>(); private Collection<MenuEntry> filteredEntries = entryMap.values(); private Map<String, MenuItem> idMap = new HashMap<String, MenuItem>(); private String name; private String filter = ""; private boolean isSorted = true; private Comparator<MenuItem> comparator; private ActionListener actionListener; /** * Creates a new menu block content object. * * @param name The name of the menu block. */ public MenuBlockContent(String name) { this.name = name; } /** * Sets the comparator to be used to sort the menu items. * * @param comparator The comparator. */ public void setComparator(Comparator<MenuItem> comparator) { this.comparator = comparator; } /** * Sets the action listener * * @param newActionListener The action listener. */ public void setActionListener(ActionListener newActionListener) { for (MenuItem m : items) { if (m instanceof MenuEntry) { if (actionListener != null) { m.removeActionListener(actionListener); } if (newActionListener != null) { m.addActionListener(newActionListener); } } } actionListener = newActionListener; } /** * Add the menu items. * * @param items The menu items to be added. */ public void addItems(List<MenuItem> items) { for (MenuItem item : items) { addItem(item); } } /** * Adds the menu item. * * @param item The menu item to be added. */ public void addItem(MenuItem item) { String id = item.getMenuItemID(); if (!(item instanceof MenuEntry && idMap.containsKey(id)) && !idMap.containsKey(id)) { if (item instanceof MenuEntry) { item.addActionListener(this); } items.add(item); idMap.put(id, item); if (item instanceof MenuEntry) { MenuEntry entry = (MenuEntry) item; entryMap.put(entry.getTextElement().getText().toLowerCase(), entry); } } isSorted = false; } /** * Returns the name of the menu block. * * @return The name of the menu block. */ public String getName() { return name; } /** * Returns true if the content is empty. * * @return true if the content is empty. */ public boolean isEmpty() { return items.isEmpty(); } /** * Returns the number of items, regardless of the current filter. * * @return The number of items. */ public int getUnfilteredItemCount() { return items.size(); } /** * Returns all menu items that are menu entries. * * @return A list of all menu entries. */ public List<MenuEntry> getEntries() { return new ArrayList<MenuEntry>(filteredEntries); } /** * Returns the number of menu entries (after filtering). * * @return The number of menu entries. */ public int getEntryCount() { return filteredEntries.size(); } /** * Returns all menu items. * * @return A list of all menu items. */ public List<MenuItem> getItems() { // TODO improve this method if (!isSorted && comparator != null) { Collections.sort(items, comparator); } if (filter.length() == 0) { return items; } List<MenuItem> filteredItems = new ArrayList<MenuItem>(); for (MenuItem item : items) { if (item instanceof MenuEntry) { // TODO this is not so nice: if (((MenuEntry) item).getTextElement().getText().toLowerCase().startsWith(filter)) { filteredItems.add(item); } } else { filteredItems.add(item); } } return filteredItems; } /** * Returns the menu entry with the given text or null if no such entry exists. If there are * more than one matching entry then the first of them is returned. The look-up is not case * sensitive. * * @param entryText The text of the menu entry to look for. * @return The menu entry. */ public MenuEntry getEntry(String entryText) { return entryMap.get(entryText.toLowerCase()); } /** * Returns a common string with maximal size such that each menu entry starts with the string. * E.g. "ar" is returned if the menu entries are "architect", "archive" and "artist". * * @return The common start string. */ public String getStartString() { String startString = null; for (MenuEntry entry : getEntries()) { String c = entry.getTextElement().getText().toLowerCase(); if (startString == null) { startString = c; } else { for (int i = startString.length(); i >= 0; i--) { if (c.startsWith(startString.substring(0, i))) break; startString = startString.substring(0, i-1); } } } return startString; } /** * Sets the filter. All entries that do not start with the given filter string become * invisible. * * @param filter The filter string. */ public void setFilter(String filter) { if (filter == null || filter.length() == 0) { this.filter = ""; filteredEntries = entryMap.values(); } else { this.filter = filter.toLowerCase(); // TODO find a better way to do this without using "°": filteredEntries = entryMap.subMap(this.filter, this.filter + "°").values(); } } public void actionPerformed(ActionEvent ev) { if (actionListener != null) { actionListener.actionPerformed(ev); } } }