/* * Copyright (c) 1996 by Jan Andersson, Torpa Konsult AB. * * Permission to use, copy, and distribute this software for * NON-COMMERCIAL purposes and without fee is hereby granted * provided that this copyright notice appears in all copies. * */ import java.awt.image.*; import java.awt.*; /** * A class that implements an image and/or string labelled button. * No fancy animations are supported. It's just a simple button with * image support.

* * It is (supposed to be) compatible with the awt.Button class, regarding * generated actions event etc. Image does not have to be preloaded and * the button is sized when the image size is known.

* * Note: not using preloaded images may cause problems with the layout, * depending on the layout manager used for the parent of the button. * When the image size is know the layout() function of the parent is * called. You might have to resize and/or reshape the parent when * the layout() function is called. See how this is done in the class * JanneToolbar. * * Sub-class of Canvas due to the awt design. * * * @version 1.11 96/08/27 * @author Jan Andersson, Torpa Konsult AB. (janne@torpa.se) */ public class JanneButton extends Canvas { /** * The image */ protected Image image = null; /** * Flag to keep track of if image size (yet) known */ protected boolean imageSizeKnown = false; /** * The label string (also used in action event for image buttons) */ protected String label; /** * Flag to keep track if image loaded */ protected boolean imageLoaded = false; /** * Button shadow border width */ protected int shadow = 2; /** * Button border width */ protected int border = 2; /** * The button state. */ protected boolean selected = false; /** * Resize image to actual size of button. */ protected boolean resizeImage = true; /** * Show label as well as image */ protected boolean showLabel = true; /** * Minimum width */ protected int minWidth = 10; /** * Constructs a Button with a string label and/or an image. * @param image the button image * @param label the button label (used in action events) * @param shadow the button shadow width * @param border the button border width * @param resizeImage true if image to be resized to actual width * of button. * @param showLabel if label to be displayed as well as image. * @param minWidth minimum width (pixels). Useful if you want * to have many buttons with the same width. */ public JanneButton(Image image, String label, int shadow, int border, boolean resizeImage, boolean showLabel, int minWidth) { this.image = image; if (image == null) imageSizeKnown = true; // kind of ;-) this.label = label; this.shadow = shadow; this.border = border; this.resizeImage = resizeImage; this.showLabel = showLabel; this.minWidth = minWidth; if (label == null || label.compareTo("-")==0) this.showLabel = false; } /** * Constructs a Button with a string label and/or an image. * @param image the button image * @param label the button label (used in action events) * @param shadow the button shadow width * @param border the button border width * @param resizeImage true if image to be resized to actual width * of button. * @param showLabel if label to be displayed as well as image. */ public JanneButton(Image image, String label, int shadow, int border, boolean resizeImage, boolean showLabel) { this(image, label, shadow, border, resizeImage, showLabel, 10); } /** * Constructs a Button with a string label and an image. * @param image the button image * @param label the button label (used in action events) * @param resizeImage true if image to be resized to actual width * @param showLabel if label to be displayed as well as image. * of button. */ public JanneButton(Image image, String label, boolean resizeImage, boolean showLabel) { this(image, label, 2, 2, resizeImage, showLabel, 10); } /** * Constructs a Button with an image. * @param image the button image * @param label the button label (only used in action events) */ public JanneButton(Image image, String label) { this(image, label, 2, 2, false, true, 10); } /** * Constructs a Button with an string label. * @param label the button label */ public JanneButton(String label) { this(null, label, 2, 2, false, true, 10); } /** * Gets the string label of the button. * @see #setLabel */ public String getLabel() { return label; } /** * Sets the string label of the button. * @param label the label to set the button with * @see #getLabel */ public void setLabel(String label) { this.label = label; layoutParent(); repaint(); } /** * Gets the image of the button. * @see #setImage */ public Image getImage() { return image; } /** * Sets the image of the button. * @param image the image to set the button with * @see #getImage */ public void setImage(Image image) { this.image = image; layoutParent(); repaint(); } /** * Gets the resizeImage flag of the button. * @see #setResizeImage */ public boolean getResizeImage() { return resizeImage; } /** * Sets the resizeImage flag of the button. * @param resizeImage true if image to be resized to actual width * of button. */ public void setResizeImage(boolean resizeImage) { this.resizeImage = resizeImage; layoutParent(); repaint(); } /** * Gets the showLabel flag of the button. * @see #setShowLabel */ public boolean getShowLabel() { return showLabel; } /** * Sets the showLabel flag of the button. * @param showLabel true if label to be displayed as well as image. */ public void setShowLabel(boolean showLabel) { this.showLabel = showLabel; layoutParent(); repaint(); } /** * Check if image size (yet) known */ public boolean imageSizeKnown() { return imageSizeKnown; } /** * Returns the parameter String of this button. */ protected String paramString() { return super.paramString() + ",label=" + label; } /** * Repaints the button when the image has changed. * Set flag if some bits loaded. * @return true if image has changed; false otherwise. */ public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) { if ((flags & SOMEBITS) != 0) { // part of the image is loaded; start painting imageLoaded = true; } if ((flags & (HEIGHT|WIDTH)) != 0) { // got the size; make sure we (re-) layout parent. imageSizeKnown = true; layoutParent(); } return super.imageUpdate(img, flags, x, y, w, h); } /** * Re-layout parent. Called when a button changes image, * size etc. */ protected void layoutParent() { Container parent = getParent(); if (parent != null) { parent.layout(); } } /** * Paints the button. * @param g the specified Graphics window */ public void paint(Graphics g) { Dimension size = size(); if (isVisible()) { if (isEnabled()) { if (selected) paintSelected(g, size); else paintUnSelected(g, size); } else if (!isEnabled()) paintDisabled(g, size); } } /** * Paints the button when selected. * @param g the specified Graphics window * @param size the button size * @see #paint */ protected void paintSelected(Graphics g, Dimension size) { Color c = getBackground(); g.setColor(c); draw3DRect(g, 0, 0, size.width, size.height, false); drawBody(g, size); } /** * Paints the button when not selected. * @param g the specified Graphics window * @param size the button size * @see #paint */ protected void paintUnSelected(Graphics g, Dimension size) { Color c = getBackground(); g.setColor(c); g.fillRect(0, 0, size.width, size.height); draw3DRect(g, 0, 0, size.width, size.height, true); drawBody(g, size); } /** * Paints the button when disabled. * @param g the specified Graphics window * @param size the button size * @see #paint */ protected void paintDisabled(Graphics g, Dimension size) { Color c = getBackground(); g.setColor(c); g.fillRect(0, 0, size.width, size.height); draw3DRect(g, 0, 0, size.width, size.height, true); // BUG ALERT: we should really do something "smart" to indicate // that an image is disabled here... drawBody(g, size); } /** * Draw a 3D Rectangle. * @param g the specified Graphics window * @param x, y, width, height * @param raised - true if border should be painted as raised. * @see #paint */ public void draw3DRect(Graphics g, int x, int y, int width, int height, boolean raised) { Color c = g.getColor(); Color brighter = c.brighter(); Color darker = c.darker(); // upper left corner g.setColor(raised ? brighter : darker); for (int i=0; i 0 && d.height > 0) imageSizeKnown = true; w = d.width - selOff; h = d.height - selOff; if (showLabel) { x = size.width/2 - d.width/2 + selOff; y = (size.height - labelH - border - shadow)/2 - d.height/2 + selOff; } else { x = size.width/2 - d.width/2 + selOff; y = size.height/2 - d.height/2 + selOff; } } g.drawImage(image, x, y, w, h, this); if (showLabel) { // draw label string, below image if (!isEnabled()) g.setColor(Color.gray); else g.setColor(getForeground()); labelY = size.height - fm.getDescent() - border - shadow - selOff; g.drawString(label, labelX, labelY); } } else { // no image; draw label string if (!isEnabled()) g.setColor(Color.gray); else g.setColor(getForeground()); g.drawString(label, labelX, labelY); } } /** * Returns the preferred size of this component. * @see #minimumSize * @see LayoutManager */ public Dimension preferredSize() { return minimumSize(); } /** * Returns the minimum size of this component. * @see #preferredSize * @see LayoutManager */ public synchronized Dimension minimumSize() { Dimension d = new Dimension(); Dimension labelDimension = new Dimension(); if (image == null || showLabel) { // get size of label FontMetrics fm = getFontMetrics(getFont()); labelDimension.width = Math.max(fm.stringWidth(label) + 2*(shadow+border), minWidth); labelDimension.height = fm.getAscent() + fm.getDescent() + 2*(shadow+border); if (image == null) d = labelDimension; } if (image != null) { // image used; get image size (If the height is not known // yet then the ImageObserver (this) will be notified later // and -1 will be returned). d.width = image.getWidth(this) ; d.height = image.getHeight(this); if (d.width > 0 && d.height > 0) { // size known; adjust for shadow and border d.width += 2*(shadow+border); d.height += 2*(shadow+border); d.width = Math.max(d.width, minWidth); if (showLabel) { // show label as well as image; adjust for label size if (labelDimension.width > d.width) d.width = labelDimension.width; d.height += labelDimension.height - 2*shadow - border; } } } return d; } /** * Enables the button. */ public synchronized void enable() { super.enable(); repaint(); // as suggested by Robert Neundlinger } /** * Disables the button. */ public synchronized void disable() { super.disable(); repaint(); // as suggested by Robert Neundlinger } /** * Called if the mouse is down. * @param evt the event * @param x the x coordinate * @param y the y coordinate */ public boolean mouseDown(Event evt, int x, int y) { // mark as selected and repaint selected = true; repaint(); return true; } /** * Called when the mouse exits the button. * @param evt the event * @param x the x coordinate * @param y the y coordinate */ public boolean mouseExit(Event evt, int x, int y) { if (selected) { // mark as un-selected and repaint selected = false; repaint(); } return true; } /** * Called if the mouse is up. * @param evt the event * @param x the x coordinate * @param y the y coordinate */ public boolean mouseUp(Event evt, int x, int y) { if (selected) { // mark as un-selected and repaint selected = false; repaint(); // generate action event Event event = new Event(this, Event.ACTION_EVENT, (Object) label); deliverEvent(event); } return true; } }