X-Git-Url: http://git.nikiroo.be/?p=jvcard.git;a=blobdiff_plain;f=src%2Fcom%2Fgooglecode%2Flanterna%2Fgui2%2FAbstractListBox.java;fp=src%2Fcom%2Fgooglecode%2Flanterna%2Fgui2%2FAbstractListBox.java;h=0000000000000000000000000000000000000000;hp=d4f14174957ecc180c40847ab2b28ab460ef3529;hb=f06c81000632cfb5f525ca458f719338f55f9f66;hpb=a73a906356c971b080c36368e71a15d87e8b8d31 diff --git a/src/com/googlecode/lanterna/gui2/AbstractListBox.java b/src/com/googlecode/lanterna/gui2/AbstractListBox.java deleted file mode 100644 index d4f1417..0000000 --- a/src/com/googlecode/lanterna/gui2/AbstractListBox.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * This file is part of lanterna (http://code.google.com/p/lanterna/). - * - * lanterna 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. - * - * This program 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 this program. If not, see . - * - * Copyright (C) 2010-2015 Martin - */ -package com.googlecode.lanterna.gui2; - -import com.googlecode.lanterna.TerminalTextUtils; -import com.googlecode.lanterna.Symbols; -import com.googlecode.lanterna.TerminalPosition; -import com.googlecode.lanterna.TerminalSize; -import com.googlecode.lanterna.input.KeyStroke; - -import java.util.ArrayList; -import java.util.List; - -/** - * Base class for several list box implementations, this will handle things like list of items and the scrollbar. - * @param Should always be itself, see {@code AbstractComponent} - * @param Type of items this list box contains - * @author Martin - */ -public abstract class AbstractListBox> extends AbstractInteractableComponent { - private final List items; - private int selectedIndex; - private ListItemRenderer listItemRenderer; - - /** - * This constructor sets up the component so it has no preferred size but will ask to be as big as the list is. If - * the GUI cannot accommodate this size, scrolling and a vertical scrollbar will be used. - */ - protected AbstractListBox() { - this(null); - } - - /** - * This constructor sets up the component with a preferred size that is will always request, no matter what items - * are in the list box. If there are more items than the size can contain, scrolling and a vertical scrollbar will - * be used. Calling this constructor with a {@code null} value has the same effect as calling the default - * constructor. - * - * @param size Preferred size that the list should be asking for instead of invoking the preferred size calculation, - * or if set to {@code null} will ask to be big enough to display all items. - */ - protected AbstractListBox(TerminalSize size) { - this.items = new ArrayList(); - this.selectedIndex = -1; - setPreferredSize(size); - setListItemRenderer(createDefaultListItemRenderer()); - } - - @Override - protected InteractableRenderer createDefaultRenderer() { - return new DefaultListBoxRenderer(); - } - - /** - * Method that constructs the {@code ListItemRenderer} that this list box should use to draw the elements of the - * list box. This can be overridden to supply a custom renderer. Note that this is not the renderer used for the - * entire list box but for each item, called one by one. - * @return {@code ListItemRenderer} to use when drawing the items in the list - */ - protected ListItemRenderer createDefaultListItemRenderer() { - return new ListItemRenderer(); - } - - ListItemRenderer getListItemRenderer() { - return listItemRenderer; - } - - /** - * This method overrides the {@code ListItemRenderer} that is used to draw each element in the list box. Note that - * this is not the renderer used for the entire list box but for each item, called one by one. - * @param listItemRenderer New renderer to use when drawing the items in the list box - * @return Itself - */ - public synchronized T setListItemRenderer(ListItemRenderer listItemRenderer) { - if(listItemRenderer == null) { - listItemRenderer = createDefaultListItemRenderer(); - if(listItemRenderer == null) { - throw new IllegalStateException("createDefaultListItemRenderer returned null"); - } - } - this.listItemRenderer = listItemRenderer; - return self(); - } - - @Override - public synchronized Result handleKeyStroke(KeyStroke keyStroke) { - try { - switch(keyStroke.getKeyType()) { - case Tab: - return Result.MOVE_FOCUS_NEXT; - - case ReverseTab: - return Result.MOVE_FOCUS_PREVIOUS; - - case ArrowRight: - return Result.MOVE_FOCUS_RIGHT; - - case ArrowLeft: - return Result.MOVE_FOCUS_LEFT; - - case ArrowDown: - if(items.isEmpty() || selectedIndex == items.size() - 1) { - return Result.MOVE_FOCUS_DOWN; - } - selectedIndex++; - return Result.HANDLED; - - case ArrowUp: - if(items.isEmpty() || selectedIndex == 0) { - return Result.MOVE_FOCUS_UP; - } - selectedIndex--; - return Result.HANDLED; - - case Home: - selectedIndex = 0; - return Result.HANDLED; - - case End: - selectedIndex = items.size() - 1; - return Result.HANDLED; - - case PageUp: - if(getSize() != null) { - setSelectedIndex(getSelectedIndex() - getSize().getRows()); - } - return Result.HANDLED; - - case PageDown: - if(getSize() != null) { - setSelectedIndex(getSelectedIndex() + getSize().getRows()); - } - return Result.HANDLED; - - default: - } - return Result.UNHANDLED; - } - finally { - invalidate(); - } - } - - @Override - protected synchronized void afterEnterFocus(FocusChangeDirection direction, Interactable previouslyInFocus) { - if(items.isEmpty()) { - return; - } - - if(direction == FocusChangeDirection.DOWN) { - selectedIndex = 0; - } - else if(direction == FocusChangeDirection.UP) { - selectedIndex = items.size() - 1; - } - } - - /** - * Adds one more item to the list box, at the end. - * @param item Item to add to the list box - * @return Itself - */ - public synchronized T addItem(V item) { - if(item == null) { - return self(); - } - - items.add(item); - if(selectedIndex == -1) { - selectedIndex = 0; - } - invalidate(); - return self(); - } - - /** - * Removes all items from the list box - * @return Itself - */ - public synchronized T clearItems() { - items.clear(); - selectedIndex = -1; - invalidate(); - return self(); - } - - /** - * Looks for the particular item in the list and returns the index within the list (starting from zero) of that item - * if it is found, or -1 otherwise - * @param item What item to search for in the list box - * @return Index of the item in the list box or -1 if the list box does not contain the item - */ - public synchronized int indexOf(V item) { - return items.indexOf(item); - } - - /** - * Retrieves the item at the specified index in the list box - * @param index Index of the item to fetch - * @return The item at the specified index - * @throws IndexOutOfBoundsException If the index is less than zero or equals/greater than the number of items in - * the list box - */ - public synchronized V getItemAt(int index) { - return items.get(index); - } - - /** - * Checks if the list box has no items - * @return {@code true} if the list box has no items, {@code false} otherwise - */ - public synchronized boolean isEmpty() { - return items.isEmpty(); - } - - /** - * Returns the number of items currently in the list box - * @return Number of items in the list box - */ - public synchronized int getItemCount() { - return items.size(); - } - - /** - * Returns a copy of the items in the list box as a {@code List} - * @return Copy of all the items in this list box - */ - public synchronized List getItems() { - return new ArrayList(items); - } - - /** - * Sets which item in the list box that is currently selected. Please note that in this context, selected simply - * means it is the item that currently has input focus. This is not to be confused with list box implementations - * such as {@code CheckBoxList} where individual items have a certain checked/unchecked state. - * @param index Index of the item that should be currently selected - * @return Itself - */ - public synchronized T setSelectedIndex(int index) { - selectedIndex = index; - if(selectedIndex < 0) { - selectedIndex = 0; - } - if(selectedIndex > items.size() - 1) { - selectedIndex = items.size() - 1; - } - invalidate(); - return self(); - } - - /** - * Returns the index of the currently selected item in the list box. Please note that in this context, selected - * simply means it is the item that currently has input focus. This is not to be confused with list box - * implementations such as {@code CheckBoxList} where individual items have a certain checked/unchecked state. - * @return The index of the currently selected row in the list box, or -1 if there are no items - */ - public int getSelectedIndex() { - return selectedIndex; - } - - /** - * Returns the currently selected item in the list box. Please note that in this context, selected - * simply means it is the item that currently has input focus. This is not to be confused with list box - * implementations such as {@code CheckBoxList} where individual items have a certain checked/unchecked state. - * @return The currently selected item in the list box, or {@code null} if there are no items - */ - public synchronized V getSelectedItem() { - if (selectedIndex == -1) { - return null; - } else { - return items.get(selectedIndex); - } - } - - /** - * The default renderer for {@code AbstractListBox} and all its subclasses. - * @param Type of the items the list box this renderer is for - * @param Type of list box - */ - public static class DefaultListBoxRenderer> implements InteractableRenderer { - private int scrollTopIndex; - - /** - * Default constructor - */ - public DefaultListBoxRenderer() { - this.scrollTopIndex = 0; - } - - @Override - public TerminalPosition getCursorLocation(T listBox) { - int selectedIndex = listBox.getSelectedIndex(); - int columnAccordingToRenderer = listBox.getListItemRenderer().getHotSpotPositionOnLine(selectedIndex); - if(columnAccordingToRenderer == -1) { - return null; - } - return new TerminalPosition(columnAccordingToRenderer, selectedIndex - scrollTopIndex); - } - - @Override - public TerminalSize getPreferredSize(T listBox) { - int maxWidth = 5; //Set it to something... - int index = 0; - for (V item : listBox.getItems()) { - String itemString = listBox.getListItemRenderer().getLabel(listBox, index++, item); - int stringLengthInColumns = TerminalTextUtils.getColumnWidth(itemString); - if (stringLengthInColumns > maxWidth) { - maxWidth = stringLengthInColumns; - } - } - return new TerminalSize(maxWidth + 1, listBox.getItemCount()); - } - - @Override - public void drawComponent(TextGUIGraphics graphics, T listBox) { - //update the page size, used for page up and page down keys - int componentHeight = graphics.getSize().getRows(); - int componentWidth = graphics.getSize().getColumns(); - int selectedIndex = listBox.getSelectedIndex(); - List items = listBox.getItems(); - ListItemRenderer listItemRenderer = listBox.getListItemRenderer(); - - if(selectedIndex != -1) { - if(selectedIndex < scrollTopIndex) - scrollTopIndex = selectedIndex; - else if(selectedIndex >= componentHeight + scrollTopIndex) - scrollTopIndex = selectedIndex - componentHeight + 1; - } - - //Do we need to recalculate the scroll position? - //This code would be triggered by resizing the window when the scroll - //position is at the bottom - if(items.size() > componentHeight && - items.size() - scrollTopIndex < componentHeight) { - scrollTopIndex = items.size() - componentHeight; - } - - graphics.applyThemeStyle(graphics.getThemeDefinition(AbstractListBox.class).getNormal()); - graphics.fill(' '); - - TerminalSize itemSize = graphics.getSize().withRows(1); - for(int i = scrollTopIndex; i < items.size(); i++) { - if(i - scrollTopIndex >= componentHeight) { - break; - } - listItemRenderer.drawItem( - graphics.newTextGraphics(new TerminalPosition(0, i - scrollTopIndex), itemSize), - listBox, - i, - items.get(i), - selectedIndex == i, - listBox.isFocused()); - } - - graphics.applyThemeStyle(graphics.getThemeDefinition(AbstractListBox.class).getNormal()); - if(items.size() > componentHeight) { - graphics.putString(componentWidth - 1, 0, Symbols.ARROW_UP + ""); - - graphics.applyThemeStyle(graphics.getThemeDefinition(AbstractListBox.class).getInsensitive()); - for(int i = 1; i < componentHeight - 1; i++) - graphics.putString(componentWidth - 1, i, Symbols.BLOCK_MIDDLE + ""); - - graphics.applyThemeStyle(graphics.getThemeDefinition(AbstractListBox.class).getNormal()); - graphics.putString(componentWidth - 1, componentHeight - 1, Symbols.ARROW_DOWN + ""); - - //Finally print the 'tick' - int scrollableSize = items.size() - componentHeight; - double position = (double)scrollTopIndex / ((double)scrollableSize); - int tickPosition = (int)(((double) componentHeight - 3.0) * position); - graphics.applyThemeStyle(graphics.getThemeDefinition(AbstractListBox.class).getInsensitive()); - graphics.putString(componentWidth - 1, 1 + tickPosition, " "); - } - } - } - - /** - * The default list item renderer class, this can be extended and customized it needed. The instance which is - * assigned to the list box will be called once per item in the list when the list box is drawn. - * @param Type of the items in the list box - * @param Type of the list box class itself - */ - public static class ListItemRenderer> { - /** - * Returns where on the line to place the text terminal cursor for a currently selected item. By default this - * will return 0, meaning the first character of the selected line. If you extend {@code ListItemRenderer} you - * can change this by returning a different number. Returning -1 will cause lanterna to hide the cursor. - * @param selectedIndex Which item is currently selected - * @return Index of the character in the string we want to place the terminal cursor on, or -1 to hide it - */ - public int getHotSpotPositionOnLine(int selectedIndex) { - return 0; - } - - /** - * Given a list box, an index of an item within that list box and what the item is, this method should return - * what to draw for that item. The default implementation is to return whatever {@code toString()} returns when - * called on the item. - * @param listBox List box the item belongs to - * @param index Index of the item - * @param item The item itself - * @return String to draw for this item - */ - public String getLabel(T listBox, int index, V item) { - return item != null ? item.toString() : ""; - } - - /** - * This is the main drawing method for a single list box item, it applies the current theme to setup the colors - * and then calls {@code getLabel(..)} and draws the result using the supplied {@code TextGUIGraphics}. The - * graphics object is created just for this item and is restricted so that it can only draw on the area this - * item is occupying. The top-left corner (0x0) should be the starting point when drawing the item. - * @param graphics Graphics object to draw with - * @param listBox List box we are drawing an item from - * @param index Index of the item we are drawing - * @param item The item we are drawing - * @param selected Will be set to {@code true} if the item is currently selected, otherwise {@code false}, but - * please notice what context 'selected' refers to here (see {@code setSelectedIndex}) - * @param focused Will be set to {@code true} if the list box currently has input focus, otherwise {@code false} - */ - public void drawItem(TextGUIGraphics graphics, T listBox, int index, V item, boolean selected, boolean focused) { - if(selected && focused) { - graphics.applyThemeStyle(graphics.getThemeDefinition(AbstractListBox.class).getSelected()); - } - else { - graphics.applyThemeStyle(graphics.getThemeDefinition(AbstractListBox.class).getNormal()); - } - String label = getLabel(listBox, index, item); - label = TerminalTextUtils.fitString(label, graphics.getSize().getColumns()); - graphics.putString(0, 0, label); - } - } -}