/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 1998, 1999 Wabasoft <www.wabasoft.com> * * Copyright (C) 2000-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine 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. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.ui; import totalcross.sys.*; import totalcross.ui.event.*; import totalcross.ui.gfx.*; import totalcross.ui.image.Image; import totalcross.ui.image.ImageException; import totalcross.util.Hashtable; /** * Button is a push button control. It supports multilined text, a standalone image, * or text mixed with images. Image buttons have a fade look when not enabled. * If you want a sticky button, set the isSticky field or use the PushButtonGroup class * selecting the CHECK mode. * <p> * Here is an example showing a push button being used: * * <pre> * public class MyProgram extends MainWindow * { * Button btn1,btn2; * * public void initUI() * { * add(btn1 = new Button("Push me\nPlease"), CENTER,TOP); * add(btn2 = new Button(new Image("myimage.png")), CENTER,AFTER+3); * } * * public void onEvent(Event event) * { * if (event.type == ControlEvent.PRESSED) * { * if (event.target == btn1) * { * ... handle btn1 being pressed * </pre> */ public class Button extends Control { /** Specifies no border for this button. Used in the setBorder method. */ public static final byte BORDER_NONE = 0; /** Specifies a single-lined border for this button. Used in the setBorder method. */ public static final byte BORDER_SIMPLE = 1; /** Specifies a 3d border for this button. Used in the setBorder method. */ public static final byte BORDER_3D = 2; /** Specifies a vertical 3d-gradient border for this button. Used in the setBorder method. * Note that, in this mode, the back and fore colors are set using the borderColor3DG, * topColor3DG and bottomColor3DG properties. */ public static final byte BORDER_3D_VERTICAL_GRADIENT = 3; /** Specifies a horizontal 3d-gradient border for this button. Used in the setBorder method. * Note that, in this mode, the back and fore colors are set using the borderColor3DG, * topColor3DG and bottomColor3DG properties. */ public static final byte BORDER_3D_HORIZONTAL_GRADIENT = 4; // guich@tc110_11 /** Specifies that the image passed in the constructor is a gray image that will be * recolorized and resized to the text's size. To create the image that will work with * this border type, do this: * <ol> * <li> Get an empty image from somewhere in the web (<a href='http://www.aaa-buttons.com/'>this site</a> is a good place; choose a light background image to prevent problems described in step 5). * <li> Do not resize the button. * <li> Convert the button to grayscale (you can download irfanview and choose menu Image / Convert to Grayscale * <li> When saving the image (as png), don't forget to save the transparent color (irfanview has an option to save it in the save dialog). * <li> Images with a smooth round border should have the background colorized to the target background color; otherwise, the results will not be perfect. * </ol> * <p> * Important: you must set the button colors before calling setBorder. * Here's a sample: * <pre> Button btn = new Button("B�rbara\nHazan", new Image("button1.png"), CENTER, 8); btn.setBackColor(backColor); btn.borderColor3DG = 0x008800; // used to colorize the image btn.setFont(font.asBold()); btn.setBorder(Button.BORDER_GRAY_IMAGE); add(btn,CENTER,CENTER); * </pre> * @since TotalCross 1.12 */ public static final byte BORDER_GRAY_IMAGE = 5; // guich@tc112_25 /** Specifies a rounded border for this button. Used in the setBorder method. Note that you MUST use PREFERRED when specifying button's height. * @since TotalCross 3.04 */ public static final byte BORDER_ROUND = 6; /** Set to true to draw the button borders if transparentBackground is true. * @since TotalCross 1.15 */ public boolean drawBordersIfTransparentBackground; // guich@tc115_74 /** The current frame in a multi-frame image. */ public int currentFrame; // defaults to 0 // guich@tc122_46: added auto-repeat for button /** Set to true to enable auto-repeat feature for this button. The PRESSED event will be sent while this button is held. * @see #INITIAL_DELAY * @see #AUTO_DELAY * @since TotalCross 1.22 */ public boolean autoRepeat; // guich@tc122_47 private TimerEvent autoRepeatTimer; /** The initial delay to start the auto-repeat. Defaults to 600ms. */ public int INITIAL_DELAY = 600; /** The frequency in which the PRESSED event will be posted after the INITIAL_DELAY was reached. Defaults to 150ms. */ public int AUTO_DELAY = 150; protected String text; protected Image img,img0,imgDis; protected boolean armed; protected byte border = BORDER_3D; protected int tx0,ty0,ix0,iy0; protected int fColor,pressColor=-1; protected int fourColors[] = new int[4]; private int txtPos,tiGap,maxTW; private boolean fixPressColor; private static Hashtable htGrays; private Image colorized; private Image npback; private boolean isAndroidStyle; private boolean skipPaint; private Rect clip; private int localCommonGap; private String []lines; private int []linesW; /** Sets the image that will be displayed when the user press this button. * Only works on Imaged buttons. * Here's a sample: * <pre> * Image img = btn.getImage(); * img = img.getFrameInstance(0); // gets a copy of the image * img.applyColor(Color.RED); // colorize as red * btn.pressedImage = img; * // another option: btn.pressedImage = btn.getImage().getFadedInstance(Color.RED); * </pre> * @since TotalCross 1.15 */ public Image pressedImage; // guich@tc115_26 /** If ui style is vista and border is BORDER_NONE, setting this to false will make * the button have a vista-like background. Otherwise, it will have a flat background. * @since TotalCross 1.0 beta 4. */ public boolean flatBackground = true; /** The corner radius of this button when BORDER_3D_GRADIENT border style is active. * Set to 10 when setBorder is called. */ public int cornerRadius3DG; /** The border width of this button when BORDER_3D_GRADIENT border style is active. * Set to 2 when setBorder is called. */ public int borderWidth3DG; /** The border color of this button when BORDER_3D_GRADIENT border style is active. * Set to 0x00108A when setBorder is called. */ public int borderColor3DG; /** The top color of this button when BORDER_3D_GRADIENT border style is active. * Set to 0xDCDCFF when setBorder is called. */ public int topColor3DG; /** The bottom color of this button when BORDER_3D_GRADIENT border style is active. * Set to Color.BLUE when setBorder is called. */ public int bottomColor3DG; /** Change to a color value to highlight the button's text. The highlight is made * drawing the button in x-1,y-1; x+1,y-1; x-1,y+1; x+1,y+1 positions. * Defaults to -1. * @since TotalCross 1.12 * @deprecated Fix the typo, use Control.textShadowColor instead. */ public int hightlightColor = -1; // guich@tc112_29 /** Set commonGap to a value to make all further buttons with the same internal * gap. * Remember to save the current value and restore it when done. * Changing this also affects the size of the ScrollBars created. * The value is stored locally on the constructor so it works later if the screen is resized. */ public static int commonGap; // guich@300_3 /** Set to true to make this button sticky: it keeps pressed until the next click. * Note that this disables autoRepeat. * @since TotalCross 1.25 */ public boolean isSticky; // guich@tc125_32 /** Used when the textPosition is RIGHT_OF. Specifies the text that will be used * as reference to center this button's text with that one. Usually, you find the biggest * text of a set of buttons and place it here. * @since TotalCross 1.27 */ public String relativeToText; // guich@tc126_28 /** Set to true to put a line under the text. Here's an example: * <pre> Button btLink; btLink = new Button("(Guide 124...)"); btLink.underlinedText = true; btLink.setBorder(BORDER_NONE); btLink.setForeColor(Color.BLUE); add(btLink,LEFT,TOP,FILL, PREFERRED); * </pre> * @since TotalCross 2.0 */ public boolean underlinedText; /** The height of the image based on the button's height, ranging from 1 to 100. Used when an image is passed as parameter in one of the constructors. */ public int imageHeightFactor; /** Fills the button when pressed even if transparentBackground is set. */ public boolean fillWhenPressedOnTransparentBackground; /** Creates a button that shows the given text and image. * @param text The text to be displayed * @param img The image to be displayed * @param textPosition Where to place the text (supports only LEFT, TOP, RIGHT, * BOTTOM, CENTER - no adjustments!). Also supports RIGHT_OF, which uses the relativeToText field * as another button to be used as reference to be able to center the title among a set of buttons; the text will be placed at the right) * @param gap The space between the text and the image * @since TotalCross 1.0 */ public Button(String text, Image img, int textPosition, int gap) { if (text != null) setText(text); this.img = this.img0 = img; this.tiGap = gap; txtPos = textPosition; this.localCommonGap = commonGap; } /** Creates a button displaying the given text. */ public Button(String text) { this(text,null,0,0); } /** Sets the text that is displayed in the button. */ public void setText(String text) { this.text = text; lines = Convert.tokenizeString(text,'\n'); onFontChanged(); if (txtPos == 0) img = null; Window.needsPaint = true; } /** Creates a button with the given image. The transparentColor property of * the Image must be set before calling this constructor. */ public Button(Image img) { this(null,img,0,0); } /** Sets the image that is displayed in the button. The transparentColor property of the Image must be set before calling this method.<br> Note: this method does not resize the button to fit the image.*/ public void setImage(Image img) { this.img = img; if (txtPos == 0) text = null; onBoundsChanged(false); Window.needsPaint = true; } /** Sets the color that the button's background will go ('armed color') when the button gets a PENDOWN event. The default is the cursor color for the background. In Android user interface style, using a bright color may result in a white background. Use a darker color in this case. @since SuperWaba 4.21 @param newColor New color to set as the background when pressed. */ public void setPressedColor(int newColor) // vik@421_28 { pressColor = newColor; fixPressColor = true; // don't allow it change } /** Sets the style of the border. * @see #BORDER_NONE * @see #BORDER_SIMPLE * @see #BORDER_3D * @see #BORDER_3D_HORIZONTAL_GRADIENT * @see #BORDER_3D_VERTICAL_GRADIENT * @see #BORDER_GRAY_IMAGE */ public void setBorder(byte border) { this.border = border; switch (border) { case BORDER_ROUND: transparentBackground = true; break; case BORDER_3D: // guich@tc112_30 case BORDER_3D_HORIZONTAL_GRADIENT: case BORDER_3D_VERTICAL_GRADIENT: cornerRadius3DG = 10; borderWidth3DG = 2; borderColor3DG = 0x00108A; topColor3DG = 0xDCDCFF; bottomColor3DG = Color.BLUE; break; case BORDER_GRAY_IMAGE: // guich@tc112_25 String key = img.hashCode()+"|"+borderColor3DG+"|"+backColor; if (htGrays == null) htGrays = new Hashtable(3); colorized = (Image)htGrays.get(key); if (colorized == null) { try { colorized = img.getFrameInstance(0); colorized.applyColor(borderColor3DG); htGrays.put(key,colorized); } catch (ImageException e) { //flsobral@tc150: colorized will remain null. } } img = null; // guich@tc113_6: will be set again in onBoundsChanged break; } } /** Gets the text displayed in the button. */ public String getText() { return text!=null?text:"image"; } /** Returns the preffered width of this control. */ public int getPreferredWidth() { int border = this.border < 2 ? this.border : 2; // guich@tc112_31 int prefW; int tw = text == null ? 0 : maxTW; int iw = (this.border == BORDER_GRAY_IMAGE || img == null) ? 0 : img.getWidth(); // guich@tc120_1: using a gray image does not take the image into consideration switch (txtPos) { case BOTTOM: case TOP: prefW = Math.max(tw,iw); break; case CENTER_OF: case RIGHT_OF: case LEFT: case RIGHT: prefW = tw + getGap(tiGap) + iw; break; case CENTER: prefW = Math.max(tw,iw)+1; if (img != null) border = 0; if (this.border == BORDER_GRAY_IMAGE) prefW += getGap(tiGap)*2; break; // guich@tc112_26 - guich@tc113_6: use tiGap too default: prefW = tw + iw; } if (border == BORDER_ROUND) prefW += getPreferredHeight(); return prefW + ((localCommonGap+border) << 1) + (img != null && text == null ? 1 : 0); // guich@tc100b4_16: add an extra pixel if image-only } /** Returns the preffered height of this control. */ public int getPreferredHeight() { int border = this.border < 2 ? this.border : 2; // guich@tc112_31 int prefH; int th = text == null ? 0 : ((uiVista?1:0)+fmH*lines.length); int ih = (this.border == BORDER_GRAY_IMAGE || img == null) ? 0 : img.getHeight(); // guich@tc120_1: using a gray image does not take the image into consideration switch (txtPos) { case BOTTOM: case TOP: prefH = th + getGap(tiGap) + ih; break; case CENTER_OF: case RIGHT_OF: case LEFT: case RIGHT: prefH = Math.max(th,ih); break; case CENTER: prefH = Math.max(th,ih)+1; if (img != null) border = 0; if (this.border == BORDER_GRAY_IMAGE) prefH += getGap(tiGap)*2; break; // guich@tc112_26 - guich@tc113_6: use tiGap too default: prefH = th + ih; } return prefH + ((localCommonGap+border) << 1) + (img != null && text == null ? 1 : 0); // guich@tc100b4_16: add an extra pixel if image-only } /** Press and depress this Button to simulate that the user had clicked on it. * Does not generate events. * If isSticky is true, inverts the button state. * @see #isSticky * @since SuperWaba 5.5 */ public void simulatePress() // guich@550_27 { if (isSticky) press(armed = !armed); else { press(true); Vm.safeSleep(100);// on win32 is needed, but and in the devices? press(false); } } /** Returns true if the button is pressed or not. Only makes sense if <code>isSticky</code> is true. * You can change the button state programatically using simulatePress. * @see #simulatePress() * @see #isSticky * @since TotalCross 1.25 */ public boolean isPressed() // guich@tc125_32 { return armed; } /** Called by the system to pass events to the button. */ public void onEvent(Event event) { PenEvent pe; if (isEnabled()) switch (event.type) { case TimerEvent.TRIGGERED: if (autoRepeatTimer != null && autoRepeatTimer.triggered && armed) { if (autoRepeatTimer.millis == INITIAL_DELAY) autoRepeatTimer.millis = AUTO_DELAY; postPressedEvent(); } break; case KeyEvent.ACTION_KEY_PRESS: // guich@550_15 simulatePress(); postPressedEvent(); break; case PenEvent.PEN_DOWN: armed = isSticky ? !armed: true; repaintNow(); if (!isSticky && autoRepeat) autoRepeatTimer = addTimer(INITIAL_DELAY); break; case PenEvent.PEN_UP: if (autoRepeat && autoRepeatTimer != null) disableAutoRepeat(); if (!isSticky && armed) press(armed = false); pe = (PenEvent)event; if ((!Settings.fingerTouch || !hadParentScrolled()) && isInsideOrNear(pe.x,pe.y)) postPressedEvent(); break; case PenEvent.PEN_DRAG: pe = (PenEvent)event; boolean lArmed = isInsideOrNear(pe.x,pe.y); if (armed != lArmed) press(armed = lArmed); break; case ControlEvent.FOCUS_OUT: if (!isSticky) armed = false; } } private void disableAutoRepeat() // luciana@570_22 { removeTimer(autoRepeatTimer); autoRepeatTimer = null; armed = false; Window.needsPaint = true; // guich@tc123_3 } /** Simulate the press or release of this button. Does not generate events. */ public void press(boolean pressed) { if (transparentBackground && !isAndroidStyle) // guich@tc114_77: repaint now the parent's background otherwise it will leave dirt in the background { boolean eus = Window.enableUpdateScreen; Window.enableUpdateScreen = false; skipPaint = true; parent.repaintNow(); skipPaint = false; Window.enableUpdateScreen = eus; } armed = pressed; // some drawing routines does not receive the armed parameter, so we must set it here. repaintNow(); } /** Called by the system to draw the button. it cuts the text if the button is too small. */ public void onPaint(Graphics g) { if (skipPaint) return; boolean isRound = border == BORDER_ROUND; if (isAndroidStyle) { if (!Settings.isOpenGL && !Settings.onJavaSE) { g.getClip(clip); g.backColor = g.getPixel(clip.x,clip.y); // use color painted by the parent g.fillRect(0,0,width,height); } } else if (!isRound && (!transparentBackground || (armed && fillWhenPressedOnTransparentBackground) || drawBordersIfTransparentBackground)) paintBackground(g); if (isRound) { g.backColor = backColor; g.fillRoundRect(0,0,width,height,height/2); } else if (isAndroidStyle) paintImage(g, true, 0,0); int border = txtPos == CENTER ? 0 : Math.min(2,this.border); // guich@tc112_31 g.setClip(border,border,width-(border<<1),height-(border<<1)); // guich@101: cut text if button is too small - guich@510_4 int tx=tx0; int ty=ty0; int ix=ix0; int iy=iy0; boolean is3d = border == BORDER_3D_HORIZONTAL_GRADIENT || border == BORDER_3D_VERTICAL_GRADIENT; if (armed && !isAndroidStyle && (is3d || uiVista || (img != null && text == null))) // guich@tc100: if this is an image-only button, let the button be pressed { int inc = is3d ? borderWidth3DG : 1; tx += inc; ix += inc; ty += inc; iy += inc; } g.foreColor = fColor; if (img != null) paintImage(g, false, ix,iy); if (text != null) paintText(g,tx,ty); } protected void onFontChanged() { if (text != null) { if (linesW == null || linesW.length != lines.length) linesW = new int[lines.length]; int []linesW = this.linesW; maxTW = 0; for (int i = lines.length-1; i >= 0; i--) { linesW[i] = fm.stringWidth(lines[i]); maxTW = Math.max(maxTW, linesW[i]); } } onBoundsChanged(false); } protected void onBoundsChanged(boolean screenChanged) { int tiGap = getGap(this.tiGap); if (imageHeightFactor != 0 && img0 != null) try { img = Settings.enableWindowTransitionEffects ? img0.smoothScaledFixedAspectRatio(height*imageHeightFactor/100,true) : img0.hwScaledFixedAspectRatio(height*imageHeightFactor/100,true); if (img.getWidth() > this.width-4) img = Settings.enableWindowTransitionEffects ? img0.smoothScaledFixedAspectRatio(width-4,false) : img0.hwScaledFixedAspectRatio(width-4,false); img.setCurrentFrame(currentFrame); imgDis = null; } catch (Throwable t) {img = img0;} isAndroidStyle = uiAndroid && this.border == BORDER_3D; if (isAndroidStyle && clip == null) clip = new Rect(); npback = null; int th=0,iw=0,ih=0; if (isAndroidStyle && width > 0 && height > 0) transparentBackground = true; // compute where to draw each item to keep it centered if (text != null) { th = fmH * lines.length; tx0 = (width - maxTW) / 2; ty0 = (height - th) / 2; } if (border == BORDER_GRAY_IMAGE) // guich@tc113_6: recompute image's { if (colorized != null) //flsobral@tc150: colorized may now be null if there was not enough memory to create it at setBorder try { img = colorized.getSmoothScaledInstance(width,height); } catch (ImageException e) { //flsobral@tc150: keep old value } } if (img != null) { iw = img.getWidth(); ih = img.getHeight(); ix0 = (width - iw) >> 1; iy0 = (height- ih) >> 1; } if (txtPos != 0) { int restH = (height - (ih + tiGap + th)) >> 1; int restW = (width - (iw + tiGap + maxTW)) >> 1; switch (txtPos) { case TOP: ty0 = restH; iy0 = ty0 + th + tiGap; break; case BOTTOM: iy0 = restH; ty0 = iy0 + ih + tiGap; break; case LEFT: tx0 = restW; ix0 = tx0 + maxTW + tiGap; break; case RIGHT: ix0 = restW; tx0 = ix0 + iw + tiGap; break; case RIGHT_OF: // guich@tc126_28 { if (relativeToText == null) throw new NullPointerException("When using RIGHT_OF, you must set the Button's relativeToText field."); int rw = 0; if (relativeToText.indexOf('\n') == -1) rw = fm.stringWidth(relativeToText); else { String []relToLines = Convert.tokenizeString(relativeToText,'\n'); rw = fm.getMaxWidth(relToLines, 0, relToLines.length); } ix0 = (width - (iw + tiGap + rw)) >> 1;; tx0 = ix0 + iw + tiGap + (rw-maxTW)/2; break; } case CENTER: break; } } } protected void onColorsChanged(boolean colorsChanged) { boolean enabled = isEnabled(); npback = null; if (!enabled && autoRepeatTimer != null) disableAutoRepeat(); fColor = enabled ? foreColor : Color.getCursorColor(foreColor); // guich@tc110_49: use getCursorColor so a white forecolor shows up as changed if (!isAndroidStyle) Graphics.compute3dColors(enabled,backColor,foreColor,fourColors); if (!fixPressColor) pressColor = Color.getCursorColor(backColor); // guich@450_35: only assign a new color if none was set. - guich@567_11: moved to outside the if above if (!isAndroidStyle) fourColors[1] = pressColor; } /** Paint button's background. */ protected void paintBackground(Graphics g) { boolean enabled = isEnabled(); if (!transparentBackground || (armed && fillWhenPressedOnTransparentBackground)) { if (border == BORDER_GRAY_IMAGE) { g.backColor = backColor; g.fillRect(0,0,width,height); return; } if (border == BORDER_3D_HORIZONTAL_GRADIENT || border == BORDER_3D_VERTICAL_GRADIENT) { g.drawRoundGradient(0,0,width - 1, height - 1, cornerRadius3DG,cornerRadius3DG,cornerRadius3DG,cornerRadius3DG,borderColor3DG,borderColor3DG,border == BORDER_3D_VERTICAL_GRADIENT); if (armed) g.drawRoundGradient(borderWidth3DG,borderWidth3DG,width - 1, height - 1,cornerRadius3DG,cornerRadius3DG - borderWidth3DG,cornerRadius3DG - borderWidth3DG,cornerRadius3DG,armed && fixPressColor ? pressColor : topColor3DG,enabled ? bottomColor3DG : topColor3DG,border == BORDER_3D_VERTICAL_GRADIENT); // guich@tc120_42: use pressColor if defined else g.drawRoundGradient(0,0,width - borderWidth3DG - 1, height - borderWidth3DG - 1,cornerRadius3DG,cornerRadius3DG - borderWidth3DG,cornerRadius3DG - borderWidth3DG,cornerRadius3DG,armed && fixPressColor ? pressColor : topColor3DG, enabled ? bottomColor3DG : topColor3DG,border == BORDER_3D_VERTICAL_GRADIENT); // guich@tc120_42 return; } switch (Settings.uiStyle) { case Settings.Flat: g.backColor = img == null && armed ? pressColor : backColor; // guich@tc100b4_13: also check if img is null g.fillRect(0,0,width,height); break; case Settings.Android: case Settings.Vista: // guich@573_6 { if (border == BORDER_NONE && flatBackground) // guich@582_14 { g.backColor = armed && fixPressColor ? pressColor : backColor; g.fillRect(0,0,width,height); } else if (enabled) g.fillVistaRect(0,0,width,height,backColor, armed,false); else // guich@582_14 - commented if (border != BORDER_NONE) { g.backColor = backColor; g.fillRect(0,0,width,height); if (border != BORDER_NONE) g.drawVistaRect(0,0,width,height,fColor,fColor,fColor,fColor); } break; } } } if (border != BORDER_NONE && !isAndroidStyle && !(uiVista && !enabled)) g.draw3dRect(0,0,width,height,armed ?Graphics.R3D_LOWERED:Graphics.R3D_RAISED,false,border == BORDER_SIMPLE,fourColors); } /** Paint button's text. */ protected void paintText(Graphics g, int tx, int ty) { int shade = !isEnabled() ? -1 : textShadowColor != -1 ? textShadowColor : hightlightColor; if (underlinedText) g.backColor = foreColor; for (int i = 0; i < lines.length; i++, ty += fmH) { int txx = tx + ((maxTW - linesW[i]) >> 1); g.drawText(lines[i], txx, ty, shade != -1, shade); if (underlinedText) g.fillRect(txx,ty+fm.ascent+1, linesW[i], (fmH-1)>>3); } } protected void paintImage(Graphics g, boolean bkg, int ix, int iy) { boolean enabled = isEnabled(); if (bkg) // only in uiAndroid try { if (npback == null) npback = NinePatch.getInstance().getNormalInstance(NinePatch.BUTTON,width,height,backColor,false); NinePatch.tryDrawImage(g, enabled ? armed ? NinePatch.getInstance().getPressedInstance(npback, backColor, pressColor) : npback : NinePatch.getInstance().getNormalInstance(NinePatch.BUTTON,width,height,Color.interpolate(parent.backColor,backColor),false),ix,iy); } catch (ImageException ie) {ie.printStackTrace();} else if (!enabled) { if (img != null && imgDis == null) // guich@tc110_50 - guich@tc310: moved to here the generation of the disabled image try { imgDis = img.getFadedInstance(); } catch (ImageException e) { imgDis = img; } g.drawImage(imgDis,ix,iy); } else g.drawImage(armed && pressedImage != null ? pressedImage : img,ix,iy); } /** Returns the image that is assigned to this Button, or null if none. */ public Image getImage() { return img; } }