📄 list.java
字号:
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.lwuit;
import com.sun.lwuit.animations.Motion;
import com.sun.lwuit.geom.Dimension;
import com.sun.lwuit.geom.Rectangle;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.events.DataChangedListener;
import com.sun.lwuit.events.SelectionListener;
import com.sun.lwuit.list.DefaultListCellRenderer;
import com.sun.lwuit.list.DefaultListModel;
import com.sun.lwuit.list.ListCellRenderer;
import com.sun.lwuit.list.ListModel;
import com.sun.lwuit.plaf.Style;
import com.sun.lwuit.plaf.UIManager;
import java.util.Vector;
/**
* A set of elements that is rendered using a {@link com.sun.lwuit.list.ListCellRenderer}
* and are extracted via the {@link com.sun.lwuit.list.ListModel}.
* <p>A list can represent many UI concepts ranging from a carousel to a "todo" checklist, this
* is made possible thanks to extensive use of Swing's style of MVC. Specifically a list
* component is relatively simple, it invokes the model in order to extract the displayed/selected
* information and shows it to the user by invoking the cell renderer.
* <p>The list class itself is completely decoupled from everything, thus it allows us to extract its
* content from any source (e.g. network, storage etc.) and display the information in any form
* (e.g. checkboxed elemenents, icons etc.).
*
* @see com.sun.lwuit.list
* @author Chen Fishbein
*/
public class List extends Component {
/**
* Indicates the list isn't fixed and that selection is movable
*/
public static final int FIXED_NONE = 0;
/**
* Indicates that the list is not fixed in place but cycles its elements
*/
public static final int FIXED_NONE_CYCLIC = 1;
/**
* Indicates the list selection will only reach the edge when there are no more
* elements in the list.
*/
public static final int FIXED_NONE_ONE_ELEMENT_MARGIN_FROM_EDGE = 2;
/**
* Allows to test for fixed none
*/
private static final int FIXED_NONE_BOUNDRY = 9;
/**
* Indicates the list selection is fixed into place at the top of the list
* or at the left of the list
*/
public static final int FIXED_LEAD = 10;
/**
* Indicates the list selection is fixed into place at the bottom of the list
* or at the right of the list
*/
public static final int FIXED_TRAIL = 11;
/**
* Indicates the list selection is fixed into place at the center of the list
*/
public static final int FIXED_CENTER = 12;
/**
* @see setRenderingPrototype
*/
private Object renderingPrototype;
/**
* Indicates whether selection is fixable to place in which case all the
* elements in the list move and selection stays in place. Fixed selection
* can be one of: FIXED_NONE, FIXED_TRAIL, FIXED_LEAD, FIXED_CENTER
*/
private int fixedSelection;
private ListModel model;
private ListCellRenderer renderer = new DefaultListCellRenderer();
private int orientation = VERTICAL;
/**
* Indicates the list orientation is VERTICAL
*/
public static final int VERTICAL = 0;
/**
* Indicates the list orientation is HORIZONTAL
*/
public static final int HORIZONTAL = 1;
private static final String id = "List";
private EventDispatcher dispatcher = new EventDispatcher();
private Dimension elemSize;
private Dimension selectedElemSize;
private boolean inputOnFocus = true;
private boolean numericKeyActions = true;
private boolean paintFocusBehindList = true;
/**
* Indicates the gap between each item in the list
*/
private int itemGap = 2;
/**
* Indicates the surrounding border gap
*/
private int borderGap = 2;
private Listeners listener;
/**
* Indicates the position within the current animation, 0 means no animation
* is in progress
*/
private int animationPosition;
private int destination;
private Motion listMotion;
/**
* Creates a new instance of List
*
* @param items set of items placed into the list model
*/
public List(Vector items) {
this(new DefaultListModel(items));
}
/**
* Creates a new instance of List
*
* @param items set of items placed into the list model
*/
public List(Object[] items) {
this(new DefaultListModel(items));
}
/**
* Creates a new instance of List with an empty default model
*/
public List() {
this(new DefaultListModel());
}
/**
* Creates a new instance of List with the given model
*
* @param model the model instance
*/
public List(ListModel model) {
setModel(model);
}
/**
* @inheritDoc
*/
void initComponentImpl() {
super.initComponentImpl();
dataChanged(0, 0);
// lazily bind listeners to prevent a memory leak in cases where models
// are stored separately from view
bindListeners();
}
/**
* @inheritDoc
*/
void deinitializeImpl() {
super.deinitializeImpl();
// cleanup to allow garbage collection even if the user keeps the model in
// memory which is a valid use case
if(listener != null) {
model.removeDataChangedListener(listener);
model.removeSelectionListener(listener);
listener = null;
}
}
/**
* @inheritDoc
*/
protected void initComponent() {
if (isSmoothScrolling()) {
getComponentForm().registerAnimated(this);
}
}
/**
* Callback to allow subclasses to react to a change in the model
*
* @param status the type data change; REMOVED, ADDED or CHANGED
* @param index item index in a list model
*/
protected void modelChanged(int status, int index) {
}
/**
* @inheritDoc
*/
public boolean isScrollableY() {
return getPreferredH() > getHeight() && (fixedSelection < FIXED_NONE_BOUNDRY) &&
orientation == VERTICAL;
}
/**
* @inheritDoc
*/
public boolean isScrollableX() {
return getPreferredW() > getWidth() && (fixedSelection < FIXED_NONE_BOUNDRY) &&
orientation != VERTICAL;
}
/**
*
* Returns the number of elements in the list, shorthand for
* getModel().getSize()
*
* @return the number of elements in the list
*/
public int size() {
return model.getSize();
}
/**
* Returns the current selected offset in the list
*
* @return the current selected offset in the list
*/
public int getSelectedIndex() {
return model.getSelectedIndex();
}
/**
* Sets the current selected offset in the list, by default this implementation
* will scroll the list to the selection if the selection is outside of the screen
*
* @param index the current selected offset in the list
*/
public void setSelectedIndex(int index) {
setSelectedIndex(index, true);
}
/**
* Sets the current selected offset in the list
*
* @param index the current selected offset in the list
* @param scrollToSelection indicates whether scrolling to selection should
* occur if the selection is outside of view
*/
public void setSelectedIndex(int index, boolean scrollToSelection) {
model.setSelectedIndex(index);
if(scrollToSelection) {
Dimension size = getElementSize(false);
Rectangle rect;
if (getOrientation() == VERTICAL) {
rect = new Rectangle(getX(), (size.getHeight() + itemGap) * Math.max(0, index - 2), size);
} else {
rect = new Rectangle((size.getWidth() + itemGap) * Math.max(0, index - 2), getY(), size);
}
scrollRectToVisible(rect);
}
}
/**
* Returns the current selected item in the list or null for no selection
*
* @return the current selected item in the list
*/
public Object getSelectedItem() {
int idx = model.getSelectedIndex();
if(idx < model.getSize()) {
return model.getItemAt(idx);
}
return null;
}
/**
* Sets the current selected item in the list
*
* @param item the current selected item in the list
*/
public void setSelectedItem(Object item) {
int size = model.getSize();
for (int iter = 0; iter < size; iter++) {
if (model.getItemAt(iter) == item) {
model.setSelectedIndex(iter);
break;
}
}
}
/**
* Returns the model underlying the list
*
* @return the model underlying the list
*/
public ListModel getModel() {
return model;
}
void dataChanged(int status, int index) {
setShouldCalcPreferredSize(true);
elemSize = null;
selectedElemSize = null;
if(getSelectedIndex() >= model.getSize()) {
setSelectedIndex(Math.max(model.getSize() - 1, 0));
}
modelChanged(status, index);
repaint();
}
private void bindListeners() {
if(listener == null) {
listener = new Listeners();
model.addDataChangedListener(listener);
model.addSelectionListener(listener);
}
}
/**
* Replaces/sets the model underlying the list
*
* @param model the new model underlying the list
*/
public void setModel(ListModel model) {
if (this.model != null) {
setShouldCalcPreferredSize(true);
model.removeDataChangedListener(listener);
model.removeSelectionListener(listener);
listener = null;
}
this.model = model;
if(isInitialized()) {
bindListeners();
}
repaint();
}
/**
* Indicate whether pressing the number keys should trigger an action
*/
public boolean isNumericKeyActions() {
return numericKeyActions;
}
/**
* Indicate whether pressing the number keys should trigger an action
*
* @param numericKeyActions true to trigger an action on number keys
*/
public void setNumericKeyActions(boolean numericKeyActions) {
this.numericKeyActions = numericKeyActions;
}
private class Listeners implements DataChangedListener, SelectionListener {
public void dataChanged(int status, int index) {
List.this.dataChanged(status, index);
}
public void selectionChanged(int oldSelected, int newSelected) {
repaint();
}
}
/**
* Sets the renderer which is used to draw list elements
*
* @param renderer cell renderer instance
*/
public void setListCellRenderer(ListCellRenderer renderer) {
if (this.renderer != null) {
//calculate the item list size and the list size.
elemSize = null;
selectedElemSize = null;
setShouldCalcPreferredSize(true);
}
this.renderer = renderer;
}
/**
* Returns the renderer which is used to draw list elements
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -