defaultlookandfeel.java

来自「j2me设计的界面包」· Java 代码 · 共 1,456 行 · 第 1/4 页

JAVA
1,456
字号
/*
 * 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.plaf;

import com.sun.lwuit.TextField;
import com.sun.lwuit.geom.Dimension;
import com.sun.lwuit.Graphics;
import com.sun.lwuit.Image;
import com.sun.lwuit.Button;
import com.sun.lwuit.CheckBox;
import com.sun.lwuit.ComboBox;
import com.sun.lwuit.Component;
import com.sun.lwuit.Label;
import com.sun.lwuit.List;
import com.sun.lwuit.RadioButton;
import com.sun.lwuit.TextArea;
import com.sun.lwuit.list.ListCellRenderer;
import com.sun.lwuit.list.ListModel;
import com.sun.lwuit.Font;
import com.sun.lwuit.TabbedPane;
import com.sun.lwuit.events.FocusListener;
import com.sun.lwuit.geom.Rectangle;
import java.util.Calendar;
import java.util.Date;

/**
 * Used to render the default look of LWUIT
 *
 * @author Chen Fishbein
 */
public class DefaultLookAndFeel extends LookAndFeel implements FocusListener {

    private static final long DAY = 1000 * 60 * 60 * 24;
    private Image[] chkBoxImages = null;
    private Image comboImage = null;
    private Image[] rButtonImages = null;
    private static int DAY_SPACE_W = 12;
    private static int DAY_SPACE_H = 15;
    private long tickerSpeed = 50;
    private boolean tickWhenFocused = true;

    /** Creates a new instance of DefaultLookAndFeel */
    public DefaultLookAndFeel() {
    }

    /**
     * @inheritDoc
     */
    public void bind(Component cmp) {
        if (tickWhenFocused && cmp instanceof Label) {
            ((Label) cmp).addFocusListener(this);
        }
    }

    /**
     * Gets the ticker speed
     * 
     * @return ticker speed in milliseconds
     */
    public long getTickerSpeed() {
        return tickerSpeed;
    }

    /**
     * Sets the ticker speed
     * 
     * @param tickerSpeed the speed in milliseconds
     */
    public void setTickerSpeed(long tickerSpeed) {
        this.tickerSpeed = tickerSpeed;
    }

    /**
     * This method allows to set all Labels, Buttons, CheckBoxes, RadioButtons
     * to start ticking when the text is too long. 
     * @param tickWhenFocused
     */
    public void setTickWhenFocused(boolean tickWhenFocused) {
        this.tickWhenFocused = tickWhenFocused;
    }

    /**
     * Sets images for checkbox checked/unchecked modes
     * 
     * @param checked the image to draw in order to represent a checked checkbox
     * @param unchecked the image to draw in order to represent an uncheck checkbox
     */
    public void setCheckBoxImages(Image checked, Image unchecked) {
        if (checked == null || unchecked == null) {
            chkBoxImages = null;
        } else {
            chkBoxImages = new Image[]{checked, unchecked};
        }
    }

    /**
     * Sets image for the combo box dropdown drawing
     * 
     * @param picker picker image
     */
    public void setComboBoxImage(Image picker) {
        comboImage = picker;
    }

    /**
     * Sets images for radio button selected/unselected modes
     * 
     * @param selected the image to draw in order to represent a selected radio button
     * @param unselected the image to draw in order to represent an unselected radio button
     */
    public void setRadioButtonImages(Image selected, Image unselected) {
        if (selected == null || unselected == null) {
            rButtonImages = null;
        } else {
            rButtonImages = new Image[]{selected, unselected};
        }
    }

    /**
     * @inheritDoc
     */
    public void drawButton(Graphics g, Button b) {
        drawComponent(g, b, getIconFromState(b), null, 0);
    }

    /**
     * @inheritDoc
     */
    public void drawCheckBox(Graphics g, CheckBox cb) {
        if (chkBoxImages != null) {
            drawComponent(g, cb, getIconFromState(cb), chkBoxImages[cb.isSelected() ? 1 : 0], 0);
        } else {
            Style style = cb.getStyle();
            int height = cb.getHeight();
            drawComponent(g, cb, getIconFromState(cb), null, height + cb.getGap());

            int gradientColor;
            if (cb.hasFocus()) {
                g.setColor(style.getFgSelectionColor());
                gradientColor = style.getBgSelectionColor();
            } else {
                g.setColor(style.getFgColor());
                gradientColor = style.getBgColor();
            }

            int width = height;

            int tX = cb.getX() + style.getPadding(Component.LEFT);
            int tY = cb.getY() + style.getPadding(Component.TOP) + (cb.getHeight() - style.getPadding(Component.TOP) - style.getPadding(Component.BOTTOM)) / 2 - height / 2;
            g.translate(tX, tY);
            int x = scaleCoordinate(1.04f, 16, width);
            int y = scaleCoordinate(4.0f, 16, height);
            int rectWidth = scaleCoordinate(10.9515f, 16, width);
            int rectHeight = scaleCoordinate(10f, 16, height);

            // brighten or darken the color slightly
            int destColor = findDestColor(gradientColor);

            g.fillLinearGradient(gradientColor, destColor, x + 1, y + 1, rectWidth - 2, rectHeight - 1, false);
            g.drawRoundRect(x, y, rectWidth, rectHeight, 5, 5);

            if (cb.isSelected()) {
                int color = g.getColor();
                g.setColor(0x111111);
                g.translate(0, 1);
                fillCheckbox(g, width, height);
                g.setColor(color);
                g.translate(0, -1);
                fillCheckbox(g, width, height);
            }
            g.translate(-tX, -tY);
        }
    }

    private static void fillCheckbox(Graphics g, int width, int height) {
        int x1 = scaleCoordinate(2.0450495f, 16, width);
        int y1 = scaleCoordinate(9.4227722f, 16, height);
        int x2 = scaleCoordinate(5.8675725f, 16, width);
        int y2 = scaleCoordinate(13.921746f, 16, height);
        int x3 = scaleCoordinate(5.8675725f, 16, width);
        int y3 = scaleCoordinate(11f, 16, height);
        g.fillTriangle(x1, y1, x2, y2, x3, y3);

        x1 = scaleCoordinate(14.38995f, 16, width);
        y1 = scaleCoordinate(0.88766801f, 16, height);
        g.fillTriangle(x1, y1, x2, y2, x3, y3);
    }

    private static int round(float x) {
        int rounded = (int) x;
        if (x - rounded > 0.5f) {
            return rounded + 1;
        }
        return rounded;
    }

    /**
     * Takes a floating point coordinate on a virtual axis and rusterizes it to 
     * a coordinate in the pixel surface. This is a very simple algorithm since
     * anti-aliasing isn't supported.
     * 
     * @param coordinate a position in a theoretical plain
     * @param plain the amount of space in the theoretical plain
     * @param pixelSize the amount of pixels available on the screen
     * @return the pixel which we should color
     */
    private static int scaleCoordinate(float coordinate, float plain, int pixelSize) {
        return round(coordinate / plain * pixelSize);
    }

    /**
     * @inheritDoc
     */
    public void drawLabel(Graphics g, Label l) {
        drawComponent(g, l, l.getIcon(), null, 0);
    }

    /**
     * @inheritDoc
     */
    public void drawRadioButton(Graphics g, RadioButton rb) {
        if (rButtonImages != null) {
            drawComponent(g, rb, getIconFromState(rb), rButtonImages[rb.isSelected() ? 1 : 0], 0);
        } else {
            Style style = rb.getStyle();
            int height = rb.getHeight();

            drawComponent(g, rb, getIconFromState(rb), null, height + rb.getGap());
            if (rb.hasFocus()) {
                g.setColor(style.getFgSelectionColor());
            } else {
                g.setColor(style.getFgColor());
            }
            height -= (style.getPadding(Component.TOP) + style.getPadding(Component.BOTTOM));
            int x = rb.getX() + style.getPadding(Component.LEFT);
            int y = rb.getY() + style.getPadding(Component.TOP);

            g.drawArc(x, y, height, height, 0, 360);
            if (rb.isSelected()) {
                int color = g.getColor();
                int destColor = findDestColor(color);
                g.fillRadialGradient(color, destColor, x + 3, y + 3, height - 5, height - 5);
            }
        }
    }

    /**
     * @inheritDoc
     */
    public void drawComboBox(Graphics g, ComboBox cb) {
        int border = 2;
        Style style = cb.getStyle();
        int leftPadding = style.getPadding(Component.LEFT);
        int rightPadding = style.getPadding(Component.RIGHT);

        setFG(g, cb);

        ListModel model = cb.getModel();
        ListCellRenderer renderer = cb.getRenderer();
        Object value = model.getItemAt(model.getSelectedIndex());
        int comboImageWidth;
        if (comboImage != null) {
            comboImageWidth = comboImage.getWidth();
        } else {
            comboImageWidth = style.getFont().getHeight();
        }
        if (model.getSize() > 0) {
            Component cmp = renderer.getListCellRendererComponent(cb, value, model.getSelectedIndex(), cb.hasFocus());
            cmp.setX(cb.getX() + leftPadding);
            cmp.setY(cb.getY() + style.getPadding(Component.TOP));
            cmp.setWidth(cb.getWidth() - comboImageWidth - 2 * rightPadding - leftPadding);
            cmp.setHeight(cb.getHeight() - style.getPadding(Component.TOP) - style.getPadding(Component.BOTTOM));
            cmp.paint(g);
        }

        g.setColor(style.getBgColor());
        int y = cb.getY();
        int height = cb.getHeight();
        int width = comboImageWidth + border;
        int x = cb.getX() + cb.getWidth() - comboImageWidth - rightPadding - border;
        if (comboImage != null) {
            g.fillRect(x, y, width, height);
            g.drawImage(comboImage, x, y + height / 2 - comboImage.getHeight() / 2);
        } else {
            int color = g.getColor();

            // brighten or darken the color slightly
            int destColor = findDestColor(color);

            g.fillLinearGradient(g.getColor(), destColor, x, y, width, height, false);
            g.setColor(color);
            g.drawRect(x, y, width, height - 1);

            width--;
            height--;

            //g.drawRect(x, y, width, height);
            g.translate(x + 1, y + 1);
            g.setColor(0x111111);
            int x1 = scaleCoordinate(2.5652081f, 16, width);
            int y1 = scaleCoordinate(4.4753664f, 16, height);
            int x2 = scaleCoordinate(8.2872691f, 16, width);
            int y2 = scaleCoordinate(10f, 16, height);
            int x3 = scaleCoordinate(13.516078f, 16, width);
            int y3 = y1;
            g.fillTriangle(x1, y1, x2, y2, x3, y3);
            g.translate(-1, -1);
            g.setColor(color);
            g.fillTriangle(x1, y1, x2, y2, x3, y3);
            //g.setColor(style.getFgColor());
            //g.fillTriangle(x1 + 2, y1 + 2, x2, y2 - 2, x3 - 2, y3 + 2);

            g.translate(-x, -y);
        }

    }

    /**
     * Finds a suitable destination color for gradient values
     */
    private int findDestColor(int color) {
        // brighten or darken the color slightly
        int sourceR = color >> 16 & 0xff;
        int sourceG = color >> 8 & 0xff;
        int sourceB = color & 0xff;
        if (sourceR > 128 && sourceG > 128 && sourceB > 128) {
            // darken
            sourceR = Math.max(sourceR >> 1, 0);
            sourceG = Math.max(sourceG >> 1, 0);
            sourceB = Math.max(sourceB >> 1, 0);
        } else {
            // brighten
            sourceR = Math.min(sourceR << 1, 0xff);
            sourceG = Math.min(sourceG << 1, 0xff);
            sourceB = Math.min(sourceB << 1, 0xff);
        }
        return ((sourceR << 16) & 0xff0000) | ((sourceG << 8) & 0xff00) | (sourceB & 0xff);
    }

    /**
     * @inheritDoc
     */

⌨️ 快捷键说明

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