📄 funcanvaslist.java
字号:
/*
* Copyright (C) 2006-2007 Funambol
*
* 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; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.funambol.mailclient.ui.view;
import com.funambol.mailclient.mm.MessageInfo;
import com.funambol.mailclient.ui.controller.UIController;
import com.funambol.mailclient.ui.utils.UiUtils;
import com.funambol.util.Log;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
/**
* generic list class.
*
*
*/
abstract class FunCanvasList extends Canvas implements CommandListener {
/**
* the current active element
* i.e. the one that will have the command
* referred to
*/
private int activeElement = 0;
/**
* the first visible element
*/
private int firstVisible = 0;
/**
* the last visible element
*/
private int lastVisible = 0;
/**
* the current height we've painted element to,
* the next element should start painting
* itself from this h
*/
protected int current_paint_h = 0;
/**
* the array of objects
*/
protected Object[] elements;
protected String theTitle="";
protected Command fireCommand;
public int NEXT_ITEM = 1;
public int PREVIOUS_ITEM = -1;
public FunCanvasList() {
this(new Object[0]);
}
/**
* Creates a new instance of FunCanvasList
* @param elements the array of elements
*/
public FunCanvasList(Object [] elements) {
initCommands();
addCommands();
setElements(elements);
}
/**
* paint the element corresponding to given
* elementId.
* @return the height of the painted area
*/
abstract int paintElement(int elementId, Graphics g) ;
/**
* handle the non-navigation keypress, e.g.
* sending the keypress to the active element
*/
abstract void handleKey(int keyCode);
/**
* paint the title and return the height of the
* painted region
*/
abstract int paintTitle(Graphics g);
/**
* this method is called by default constructor
* and should create the commands
*/
abstract void initCommands();
/**
* called once by default constructor, should add the
* general commands (i.e. not the item-specific commands)
*/
abstract void addCommands();
/**
* called by setElements when a empty element array is set
*/
abstract void removeItemCommands();
/**
* called by setElements when a non-empty array is set
*/
abstract void addItemCommands();
/**
* this method must paint the background of the canvas
*/
abstract void paintBackground(Graphics graphics);
/**
* @return true if the element identified by elementid can be the active element
*/
abstract boolean isActivable(int elementId) ;
/**
* @return true if the the element identified by elementid is visible
*/
abstract boolean isVisible(int elementId);
/**
* handle the up / down navigation
*/
protected void keyPressed(int keyCode) {
int dir = getGameAction(keyCode);
if ( dir == Canvas.DOWN ) {//&& getActiveElement() < elements.length -1 ) {
getNextItem(NEXT_ITEM);
//scroll(1);
repaint();
} else if ( dir == Canvas.UP ) {// && getActiveElement() > 0 ) {
getNextItem(PREVIOUS_ITEM);
//scroll(-1);
repaint();
} else if (dir == Canvas.FIRE) {
commandAction(fireCommand, this);
} else handleKey(keyCode);
}
/**
* move the active element to the next activable ones
*/
private int toNextActivable(){
// Log.debug("Current Active Element is " + activeElement);
for (int i = 1; i< elements.length - getActiveElement(); i++) {
// Log.debug("checking element " + i);
if (isActivable(getActiveElement() + i)) {
// Log.debug("is activable");
setActiveElement(getActiveElement() + i);
return i;
}
// Log.debug("is not activable");
}
return 0;
}
/**
* move the active element to the previous activable ones
*/
private int toPreviousActivable() {
// Log.debug("Current Active Element is " + activeElement);
for (int i = 1; i < getActiveElement() +1; i++) {
// Log.debug("checking element " + (activeElement -i));
if (isActivable(getActiveElement() - i)) {
// Log.debug("is activable");
setActiveElement(getActiveElement() - i);
return -i;
}
// Log.debug("is not activable");
}
return 0;
}
/**
* change the active element
* @param amount the number of elements to step forward or back.
* it can be positive or negative, and the result will be a scroll up
* or down accordingly to the sign
*/
protected void scroll(int amount) {
if (elements == null || elements.length == 0) {
return;
}
// Log.debug(this, "amount = " + amount);
int steps = 0;
if (amount > 0) {
for (int i = 0; i< amount; i++) {
toNextActivable();
}
} else {
for (int i = 0; i< -amount; i++) {
toPreviousActivable();
}
}
if (getActiveElement() > lastVisible) {
// Log.debug("activelement >= lastvisible!");
for (int i = 0; i< amount; i++) {
toNextVisible();
}
}
if (getActiveElement() < firstVisible) {
firstVisible = getActiveElement();
}
}
/**
* bind given command to fire event
*
* @param command the command to be called when fire button
* (typically the central button) is pressed. set to null not to trigger
* any commandaction when fire button is pressed
*
*/
protected void setFireCommand(Command command) {
this.fireCommand = command;
}
/**
*
* @return the current title
*/
public String getTitle(){
// Log.debug(this, "getTitle called, returning the fake title '" + theTitle + "'");
return theTitle;
}
/**
* paint the title and the elements
*/
protected void paint(Graphics graphics) {
paintBackground(graphics);
int height = getHeight();
current_paint_h = 0 ;
current_paint_h+= paintTitle(graphics);
if (elements.length > 0) {
int i = firstVisible;
//Log.debug("Starting from " + i);
while (current_paint_h < height && i <elements.length) {
if (isVisible(i)) {
current_paint_h += paintElement(i, graphics);
}
i++;
}
if (i==elements.length && current_paint_h <= height) {
//this means we painted everything!
// Log.debug("i==elements.length && current_paint_h < height");
lastVisible = elements.length-1;
} else {
// we have to use i-2 because if element firstvisible +2
// is partially painted, the i output value is firstvisible +3
// and the last completely visible element is firstvisible +1
// so lastvisible is at i-2
lastVisible = Math.max(firstVisible, i-2);
}
}
}
/**
* handle keyrepeated events
* @param keycode the keycode of the key
*/
protected void keyRepeated(int keyCode) {
// keyPressed(keyCode);
int dir = getGameAction(keyCode);
if (dir == Canvas.DOWN && getActiveElement() < elements.length-1) {
scroll(1);
repaint();
} else if (dir == Canvas.UP && getActiveElement() >0) {
scroll(-1);
repaint();
}
}
/**
* set the title to the given title.
*
* passing the title does nothing, because we have to ignore it for
* compatibility issues with motorola devices.
*/
public void setTitle(String newTitle) {
//we have to ignore setTitle (null) because some motorola devices
//call this method when building the canvas
if (newTitle == null) {
// Log.debug("calls to setTitle (null): ignoring it");
return;
}
// Log.debug(this, "setting fake title to " + newTitle);
this.theTitle = newTitle;
// we need this check to be sure we have completed the initialization
// of the object, if removed the app will crash on some nokias (e.g. 6630)
if ( elements != null ) {
repaint();
}
}
/**
* set newElements array, calls
* addItemCommands or removeItemCommands if needed
* and calls repaint()
*
* @param newElements the new object array to be set
*/
protected void setElements(Object[] newElements) {
if (newElements == null) {
newElements = new Object[0];
}
if (elements == null) {
elements = new Object[0];
}
if (newElements.length > 0 && elements.length == 0) {
addItemCommands();
} if (newElements.length == 0 && elements.length != 0) {
removeItemCommands();
}
this.elements = newElements;
setActiveElement(Math.min(getActiveElement(), Math.max(0,elements.length-1)));
}
/**
* @return the index of the current active elements
*/
public int getActiveElement() {
return activeElement;
}
/**
* deactivate the current element and activate the given one
*
* @param newActiveElement the index of the new active element
*/
public void setActiveElement(int newActiveElement) {
deactivate(activeElement);
// Log.debug("Activating element" + newActiveElement);
activate(newActiveElement);
}
/**
* deactivate given element.
* default implementation does nothing
* @param activeElement the element to be deactivated
*/
protected void deactivate(int activeElement) {
}
/**
* activate the given element, if activable
* @param newActiveElement the element to be activated
*/
protected void activate(int newActiveElement){
if (elements.length > 0) {
newActiveElement = Math.min(newActiveElement, elements.length);
newActiveElement = Math.max(newActiveElement, 0);
if (isActivable(newActiveElement)) {
this.activeElement = newActiveElement;
}
}
/* if (activeElement < firstVisible) {
firstVisible = activeElement;
repaint();
}*/
}
/**
* reset the active element to the first element of the list
*/
public void rewindList() {
this.firstVisible = 0;
this.lastVisible = 0;
setActiveElement(0);
//we need this three scroll, the first two set correctly firstvisible
//and lastvisible, the third go back to the first element of the list.
scroll(-1);
scroll(1);
scroll(-1);
}
/**
* move firstvisible to the next visible element
*/
private int toNextVisible() {
for (int i = 1; i< elements.length - firstVisible; i++) {
// Log.debug("checking element " + i);
if (isVisible(firstVisible + i)) {
// Log.debug("is activable");
firstVisible += i;
return i;
}
// Log.debug("is not activable");
}
return 0;
}
/**
* Sets the loop list navigation message when
* up/down navigation is performed
* @param shift is the way of navigation
*/
public void getNextItem(int shift) {
int itemToSet = getActiveElement()+shift;
if (itemToSet>=elements.length) {
itemToSet=0;
rewindList();
shift=0;
} else if (itemToSet<0) {
itemToSet=elements.length-1;
shift=elements.length;
}
if (Math.abs(shift)>1) {
for (int i=0; i<shift; i++) {
scroll(NEXT_ITEM);
repaint();
}
} else {
scroll(shift);
}
setActiveElement(itemToSet);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -