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

📄 itempicker.java

📁 手机视频开发
💻 JAVA
字号:
/*
 *
 * Copyright (c) 2007, Sun Microsystems, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of Sun Microsystems nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.sun.perseus.demo.picturedecorator;

import java.util.Vector;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.m2g.SVGImage;
import javax.microedition.m2g.ScalableGraphics;

import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGElement;
import org.w3c.dom.svg.SVGLocatableElement;
import org.w3c.dom.svg.SVGRect;
import org.w3c.dom.svg.SVGSVGElement;


/**
 * The <code>ItemPicker</code> canvas creates thumbnails of the various props
 * from its associated props images and displays them in a grid.
 * The user can use the arrow keys to select a thumbnail (which gets highlighted)
 * and use the fire button to select the desired item or the '*' key to cancel
 * the picker.
 */
public class ItemPicker extends Canvas {
    /**
     * The SVG Namespace URI.
     */
    public static final String SVG_NAMESPACE_URI = "http://www.w3.org/2000/svg";

    /**
     * The XLink Namespace URI.
     */
    public static final String XLINK_NAMESPACE_URI = "http://www.w3.org/1999/xlink";

    /**
     * Desired thumbnail width
     */
    public static final int THUMBNAIL_WIDTH = 60;

    /**
     * Desired thumbnail height
     */
    public static final int THUMBNAIL_HEIGHT = 60;

    /**
     * The desired padding for each thumbnail
     */
    public static final int THUMBNAIL_PADDING = 5;

    /**
     * Offscreen where the thumbnails are rendered.
     */
    private Image offscreen;

    /**
     * Selected row
     */
    private int selectedRow;

    /**
     * Selected col
     */
    private int selectedCol;

    /**
     * Number of rows
     */
    private int nr;

    /**
     * Number of columns
     */
    private int nc;

    /**
     * The highest number of rows.
     */
    private int maxR;

    /**
     * The highest number of columns
     */
    private int maxC;

    /**
     * The grid's top margin
     */
    private int topMargin;

    /**
     * The grid's left margin
     */
    private int leftMargin;

    /**
     * The display to use
     */
    private Display display;

    /**
     * The associated PhotoFrame instance where the image is decorated
     * with items selected in this picker.
     */
    private PhotoFrame frame;

    /**
     * ScalableGraphics used to render the SVG image
     */
    private ScalableGraphics sg;

    /**
     * The use element used to render items.
     */
    private SVGLocatableElement use;

    /**
     * The root svg element.
     */
    private SVGSVGElement svg;

    /**
     * True when the user is in the process of selecting an item.
     */
    private boolean selecting;

    /**
     * The list of displayed items.
     */
    private Vector items;

    /**
     * The SVGImage where the items are defined.
     */
    private SVGImage svgImage;

    /**
     * @param frame the associated PhotoFrame instance.
     * @param svgImage the svgImage where items are defined.
     * @param svgImage the SVGImage containing all the props definitions.
     */
    public ItemPicker(final PhotoFrame frame, final SVGImage svgImage, final Display display) {
        if ((svgImage == null) || (frame == null) || (display == null)) {
            throw new NullPointerException();
        }

        this.display = display;
        this.frame = frame;
        this.svgImage = svgImage;

        // Save the original viewport width / height
        int originalWidth = svgImage.getViewportWidth();
        int originalHeight = svgImage.getViewportHeight();

        // Prepare an offscreen raster
        offscreen = Image.createImage(getWidth(), getHeight());

        Graphics g = offscreen.getGraphics();
        sg = ScalableGraphics.createInstance();

        // We will render the SVG image in thumbnails
        svgImage.setViewportWidth(THUMBNAIL_WIDTH);
        svgImage.setViewportHeight(THUMBNAIL_HEIGHT);

        // Create an offscreen buffer where we will draw the different 
        // items in a grid-like layout.
        int width = getWidth();
        int height = getHeight();

        int pad = THUMBNAIL_PADDING;
        int iconWidth = THUMBNAIL_WIDTH;
        int iconHeight = THUMBNAIL_HEIGHT;

        nc = (width - pad) / (iconWidth + pad);
        nr = (height - pad) / (iconHeight + pad);

        topMargin = (height - (nr * iconHeight) - ((nr - 1) * pad)) / 2;
        leftMargin = (width - (nc * iconWidth) - ((nc - 1) * pad)) / 2;

        items = new Vector();

        Document doc = svgImage.getDocument();

        svg = (SVGSVGElement)svgImage.getDocument().getDocumentElement();
        PhotoFrame.locateProps(svg, 0, 0, items, items);

        int nItems = items.size();

        // Append a <use> element that we will use for rendering into the 
        // offscreen.
        use = (SVGLocatableElement)doc.createElementNS(SVG_NAMESPACE_URI, "use");
        svg.appendChild(use);

        SVGRect viewBox = svg.getRectTrait("viewBox");

        // Now, we render up to the maximum number of items.
        int curRow = 0;
        int curCol = 0;
        int tx = leftMargin;
        int ty = topMargin;

        for (int ci = 0; ci < nItems; ci++) {
            SVGElement item = (SVGElement)items.elementAt(ci);
            use.setTraitNS(XLINK_NAMESPACE_URI, "href", "#" + item.getId());

            SVGRect bbox = use.getBBox();

            if (bbox == null) {
                System.out.println("Bounding Box was null for " + item.getId());
            }

            bbox = pad(bbox);

            svg.setRectTrait("viewBox", bbox);

            // Render icon
            sg.bindTarget(g);
            sg.render(tx, ty, svgImage);
            sg.releaseTarget();

            curCol++;
            tx += iconWidth;
            tx += pad;

            if (curCol == nc) {
                curCol = 0;
                tx = leftMargin;
                curRow++;
                ty += iconHeight;
                ty += pad;

                if (curRow == nr) {
                    // We have rendered the maximum number of props.
                    break;
                }
            }
        }

        use.setTrait("display", "none");

        maxC = items.size() % nc;
        maxR = items.size() / nc;

        if (maxC == 0) {
            maxC = nc;
        } else {
            maxR += 1;
        }

        if (items.size() >= (nr * nc)) {
            maxC = nc;
            maxR = nr;
        }

        // Restore the original viewport width / height
        svgImage.setViewportWidth(width);
        svgImage.setViewportHeight(height);
        svg.setRectTrait("viewBox", viewBox);
    }

    public void keyPressed(int keyCode) {
        int gameAction = getGameAction(keyCode);

        if (gameAction == RIGHT) {
            selectedCol++;

            if (selectedRow < (maxR - 1)) {
                if (selectedCol == nc) {
                    selectedCol = 0;
                    selectedRow++;
                }
            } else {
                // We are on the last row
                if (selectedCol == maxC) {
                    selectedCol = 0;
                    selectedRow = 0;
                }
            }

            repaint();
            serviceRepaints();
        } else if (gameAction == LEFT) {
            selectedCol--;

            if (selectedCol < 0) {
                if (selectedRow == 0) {
                    selectedCol = maxC - 1;
                    selectedRow = maxR - 1;
                } else {
                    selectedCol = nc - 1;
                    selectedRow--;
                }
            }

            repaint();
            serviceRepaints();
        } else if (gameAction == UP) {
            selectedRow--;

            if (selectedRow < 0) {
                selectedRow = maxR - 1;

                if (selectedCol >= maxC) {
                    selectedCol = maxC - 1;
                }
            }

            repaint();
            serviceRepaints();
        } else if (gameAction == DOWN) {
            selectedRow++;

            if (selectedRow == maxR) {
                selectedRow = 0;
            } else if (selectedRow == (maxR - 1)) {
                if (selectedCol >= maxC) {
                    selectedCol = maxC - 1;
                }
            }

            repaint();
            serviceRepaints();
        } else if (gameAction == FIRE) {
            if (selecting) {
                // The user is confirming his/her choice
                selecting = false;

                SVGElement item = (SVGElement)items.elementAt(selectedCol + (selectedRow * nc));
                frame.addProp(item.getId());
                display.setCurrent(frame);
            } else {
                selecting = true;
                repaint();
                serviceRepaints();
            }
        } else if (keyCode == KEY_STAR) {
            if (selecting) {
                selecting = false;
                repaint();
                serviceRepaints();
            } else {
                display.setCurrent(frame);
            }
        }
    }

    /**
     * Repaints this canvas with the current item selected.
     *
     * @param g the Graphics to paint into.
     */
    public void paint(final Graphics g) {
        g.drawImage(offscreen, 0, 0, Graphics.TOP | Graphics.LEFT);

        // Draw a rectangle over the currently selected item.
        g.setColor(180, 180, 180);

        int tx = leftMargin + (selectedCol * (THUMBNAIL_PADDING + THUMBNAIL_WIDTH));
        int ty = topMargin + (selectedRow * (THUMBNAIL_PADDING + THUMBNAIL_HEIGHT));
        g.drawRect(tx, ty, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);

        if (selecting) {
            SVGElement item = (SVGElement)items.elementAt(selectedCol + (selectedRow * nc));
            use.setTrait("display", "inline");
            use.setTraitNS(XLINK_NAMESPACE_URI, "href", "#" + item.getId());

            SVGRect bbox = pad(use.getBBox());
            SVGRect viewBox = svg.getRectTrait("viewBox");
            int viewportWidth = svgImage.getViewportWidth();
            int viewportHeight = svgImage.getViewportHeight();
            svg.setRectTrait("viewBox", bbox);

            int w = getWidth();

            if (w > getHeight()) {
                w = getHeight();
            }

            w = (int)(0.8f * w);
            svgImage.setViewportWidth(w);
            svgImage.setViewportHeight(w);

            g.setColor(255, 255, 255);
            g.fillRect((getWidth() - w) / 2, (getHeight() - w) / 2, w, w);
            g.setColor(180, 180, 180);
            g.drawRect((getWidth() - w) / 2, (getHeight() - w) / 2, w, w);

            sg.bindTarget(g);
            sg.render((getWidth() - w) / 2, (getHeight() - w) / 2, svgImage);
            sg.releaseTarget();

            svg.setRectTrait("viewBox", viewBox);
            svgImage.setViewportWidth(viewportWidth);
            svgImage.setViewportHeight(viewportHeight);
            use.setTrait("display", "none");
        }
    }

    /**
     * Helper method. Pads the input bounding box.
     *
     * @param bbox the box to pad.
     */
    static SVGRect pad(final SVGRect bbox) {
        float iconPadding = 0.1f; // 10% of the bounding box
        float hPad = bbox.getWidth() * iconPadding;
        float vPad = bbox.getHeight() * iconPadding;
        bbox.setX(bbox.getX() - hPad);
        bbox.setY(bbox.getY() - vPad);
        bbox.setWidth(bbox.getWidth() + (2 * hPad));
        bbox.setHeight(bbox.getHeight() + (2 * vPad));

        return bbox;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -