⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 funcanvaslist.java

📁 The Funambol J2ME Mail Client aims to be a light, easy to use, free email client for J2ME devices.
💻 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 + -