/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tiny Look and Feel * * * * (C) Copyright 2003 - 2007 Hans Bickel * * * * For licensing information and credits, please refer to the * * comment in file de.muntjak.tinylookandfeel.TinyLookAndFeel * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ package de.muntjak.tinylookandfeel; import java.awt.*; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import javax.swing.*; import de.muntjak.tinylookandfeel.controlpanel.*; /** * TinyComboBoxButton * * @version 1.3 * @author Hans Bickel */ public class TinyComboBoxButton extends JButton { protected JComboBox comboBox; protected JList listBox; protected CellRendererPane rendererPane; protected Icon comboIcon; protected boolean iconOnly = false; private static BufferedImage focusImg; public final JComboBox getComboBox() { return comboBox; } public final void setComboBox(JComboBox cb) { comboBox = cb; } public final Icon getComboIcon() { return comboIcon; } public final void setComboIcon(Icon i) { comboIcon = i; } public final boolean isIconOnly() { return iconOnly; } public final void setIconOnly(boolean isIconOnly) { iconOnly = isIconOnly; } TinyComboBoxButton() { super(""); DefaultButtonModel model = new DefaultButtonModel() { public void setArmed(boolean armed) { super.setArmed(isPressed() ? true : armed); } }; setModel(model); // Set the background and foreground to the combobox colors. setBackground(UIManager.getColor("ComboBox.background")); setForeground(UIManager.getColor("ComboBox.foreground")); if(focusImg == null) { ImageIcon icon = TinyLookAndFeel.loadIcon("ComboBoxFocus.png", this); if(icon != null) { focusImg = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB); Graphics g = focusImg.getGraphics(); icon.paintIcon(this, g, 0, 0); } } } public TinyComboBoxButton(JComboBox cb, Icon i, boolean onlyIcon, CellRendererPane pane, JList list) { this(); comboBox = cb; comboIcon = i; rendererPane = pane; listBox = list; setEnabled(comboBox.isEnabled()); } /** * Mostly taken from the swing sources * @see javax.swing.JComponent#paintComponent(Graphics) */ public void paintComponent(Graphics g) { // Note: border was already painted in TinyButtonBorder boolean leftToRight = getComponentOrientation().isLeftToRight(); if(comboBox.isEnabled()) { if(comboBox.isEditable()) { g.setColor(Theme.textBgColor[Theme.style].getColor()); } else { g.setColor(comboBox.getBackground()); } } else { g.setColor(Theme.textDisabledBgColor[Theme.style].getColor()); } g.fillRect(1, 1, getWidth() - 2, getHeight() - 2); // paint border background - next parent is combo box Color bg = getParent().getParent().getBackground(); g.setColor(bg); g.drawRect(0, 0, getWidth() - 1, getHeight() - 1); Color col = null; if(!isEnabled()) { col = Theme.comboButtDisabledColor[Theme.style].getColor(); } else if(model.isPressed()) { col = Theme.comboButtPressedColor[Theme.style].getColor(); } else if(model.isRollover()) { col = Theme.comboButtRolloverColor[Theme.style].getColor(); } else { col = Theme.comboButtColor[Theme.style].getColor(); } g.setColor(col); Rectangle buttonRect = new Rectangle( getWidth() - Theme.comboButtonWidth[Theme.derivedStyle[Theme.style]], 1, Theme.comboButtonWidth[Theme.derivedStyle[Theme.style]], getHeight() - 2); switch(Theme.derivedStyle[Theme.style]) { case Theme.TINY_STYLE: drawTinyButton(g, buttonRect); break; case Theme.W99_STYLE: drawWinButton(g, buttonRect); break; case Theme.YQ_STYLE: drawXpButton(g, buttonRect, col); break; } // draw arrow if (isEnabled()) { g.setColor(Theme.comboArrowColor[Theme.style].getColor()); } else { g.setColor(Theme.comboArrowDisabledColor[Theme.style].getColor()); } switch(Theme.derivedStyle[Theme.style]) { case Theme.TINY_STYLE: drawTinyArrow(g, buttonRect); break; case Theme.W99_STYLE: drawWinArrow(g, buttonRect); break; case Theme.YQ_STYLE: drawXpArrow(g, buttonRect); break; } Insets insets = new Insets( Theme.comboInsets[Theme.style].top, Theme.comboInsets[Theme.style].left, Theme.comboInsets[Theme.style].bottom, 0); int width = getWidth() - (insets.left + insets.right); int widthFocus = width; int height = getHeight() - (insets.top + insets.bottom); if (height <= 0 || width <= 0) { return; } int left = insets.left; int top = insets.top; int right = left + (width - 1); int bottom = top + (height - 1); int iconWidth = Theme.comboButtonWidth[Theme.derivedStyle[Theme.style]]; int iconLeft = (leftToRight) ? right : left; // Let the renderer paint Component c = null; boolean mustResetOpaque = false; boolean savedOpaque = false; boolean paintFocus = false; if(!iconOnly && comboBox != null) { ListCellRenderer renderer = comboBox.getRenderer(); boolean renderPressed = getModel().isPressed(); c = renderer.getListCellRendererComponent(listBox, comboBox.getSelectedItem(), -1, renderPressed, false); c.setFont(rendererPane.getFont()); if (model.isArmed() && model.isPressed()) { if (isOpaque()) { c.setBackground(UIManager.getColor("Button.select")); } c.setForeground(comboBox.getForeground()); } else if (!comboBox.isEnabled()) { if (isOpaque()) { c.setBackground(Theme.textDisabledBgColor[Theme.style].getColor()); } else { comboBox.setBackground(Theme.textDisabledBgColor[Theme.style].getColor()); } c.setForeground(UIManager.getColor("ComboBox.disabledForeground")); } else if(comboBox.hasFocus() && !comboBox.isPopupVisible()) { if(comboBox.isEditable()) { c.setForeground(Theme.mainColor[Theme.style].getColor()); } else { c.setForeground(UIManager.getColor("ComboBox.selectionForeground")); } c.setBackground(UIManager.getColor("ComboBox.focusBackground")); if (c instanceof JComponent) { mustResetOpaque = true; JComponent jc = (JComponent) c; savedOpaque = jc.isOpaque(); jc.setOpaque(true); paintFocus = true; } } else { c.setForeground(comboBox.getForeground()); c.setBackground(comboBox.getBackground()); } int cWidth = width - (insets.right + iconWidth); // Fix for 4238829: should lay out the JPanel. boolean shouldValidate = false; if (c instanceof JPanel) { shouldValidate = true; } if (leftToRight) { rendererPane.paintComponent(g, c, this, left, top, cWidth, height, shouldValidate); } else { rendererPane.paintComponent(g, c, this, left + iconWidth, top, cWidth, height, shouldValidate); } if(paintFocus && Theme.derivedStyle[Theme.style] == Theme.YQ_STYLE && Theme.comboFocus[Theme.style]) { g.setColor(Color.black); Graphics2D g2d = (Graphics2D) g; Rectangle r = new Rectangle(left, top, 2, 2); TexturePaint tp = new TexturePaint(focusImg, r); g2d.setPaint(tp); g2d.draw(new Rectangle(left,top,cWidth, height)); } } if (mustResetOpaque) { JComponent jc = (JComponent) c; jc.setOpaque(savedOpaque); } } private void drawTinyButton(Graphics g, Rectangle r) { } private void drawWinButton(Graphics g, Rectangle r) { int x2 = r.x + r.width - 1; int y2 = r.y + r.height - 1; g.fillRect(r.x, r.y, r.width - 2, r.height - 2); if(model.isPressed()) { g.setColor(Theme.comboButtDarkColor[Theme.style].getColor()); g.drawRect(r.x, r.y + 1, r.width - 2, r.height - 3); } else { if(!isEnabled()) { g.setColor(Theme.comboButtLightDisabledColor[Theme.style].getColor()); } else { g.setColor(Theme.comboButtLightColor[Theme.style].getColor()); } g.drawLine(r.x + 1, r.y + 2, x2 - 3, r.y + 2); g.drawLine(r.x + 1, r.y + 2, r.x + 1, y2 - 3); if(!isEnabled()) { g.setColor(Theme.comboButtDarkDisabledColor[Theme.style].getColor()); } else { g.setColor(Theme.comboButtDarkColor[Theme.style].getColor()); } g.drawLine(x2 - 2, r.y + 2, x2 - 2, y2 - 3); g.drawLine(r.x + 1, y2 - 2, x2 - 2, y2 - 2); if(!isEnabled()) { g.setColor(Theme.comboButtBorderDisabledColor[Theme.style].getColor()); } else { g.setColor(Theme.comboButtBorderColor[Theme.style].getColor()); } g.drawLine(x2 - 1, r.y + 1, x2 - 1, y2 - 2); g.drawLine(r.x, y2 - 1, x2 - 1, y2 - 1); } } private void drawXpButton(Graphics g, Rectangle r, Color c) { int x2 = r.x + r.width; int y2 = r.y + r.height; int spread1 = Theme.comboSpreadLight[Theme.style]; int spread2 = Theme.comboSpreadDark[Theme.style]; if(!isEnabled()) { spread1 = Theme.comboSpreadLightDisabled[Theme.style]; spread2 = Theme.comboSpreadDarkDisabled[Theme.style]; } int h = r.height - 2; float spreadStep1 = 10.0f * spread1 / (h - 3); float spreadStep2 = 10.0f * spread2 / (h - 3); int halfY = h / 2; int yd; for(int y = 1; y < h - 1; y++) { if(y < halfY) { yd = halfY - y; g.setColor(ColorRoutines.lighten(c, (int)(yd * spreadStep1))); } else if(y == halfY) { g.setColor(c); } else { yd = y - halfY; g.setColor(ColorRoutines.darken(c, (int)(yd * spreadStep2))); } g.drawLine(r.x + 1, r.y + y + 1, r.x + r.width - 3, r.y + y + 1); } // draw the button border Color col = null; if(!isEnabled()) { col = Theme.comboButtBorderDisabledColor[Theme.style].getColor(); } else { col = Theme.comboButtBorderColor[Theme.style].getColor(); } g.setColor(col); g.drawLine(r.x + 2, r.y + 1, x2 - 4, r.y + 1); g.drawLine(r.x + 1, r.y + 2, r.x + 1, y2 - 3); g.drawLine(x2 - 3, r.y + 2, x2 - 3, y2 - 3); g.drawLine(r.x + 2, y2 - 2, x2 - 4, y2 - 2); // ecken col = new Color(col.getRed(), col.getGreen(), col.getBlue(), 128); g.setColor(col); g.drawLine(r.x + 1, r.y + 1, r.x + 1, r.y + 1); g.drawLine(x2 - 3, r.y + 1, x2 - 3, r.y + 1); g.drawLine(r.x + 1, y2 - 2, r.x + 1, y2 - 2); g.drawLine(x2 - 3, y2 - 2, x2 - 3, y2 - 2); } private void drawTinyArrow(Graphics g, Rectangle r) { } private void drawWinArrow(Graphics g, Rectangle r) { int x = r.x + (r.width - 6) / 2 - 2; int y = r.y + (r.height - 4) / 2; if(model.isPressed()) { x ++; y ++; } g.drawLine(x, y, x + 6, y); g.drawLine(x + 1, y + 1, x + 5, y + 1); g.drawLine(x + 2, y + 2, x + 4, y + 2); g.drawLine(x + 3, y + 3, x + 3, y + 3); if(!isEnabled()) { g.setColor(ColorRoutines.lighten(Theme.comboArrowDisabledColor[Theme.style].getColor(), 60)); g.drawLine(x + 4, y + 4, x + 4, y + 4); g.drawLine(x + 4, y + 3, x + 5, y + 3); g.drawLine(x + 5, y + 2, x + 6, y + 2); g.drawLine(x + 6, y + 1, x + 7, y + 1); } } private void drawXpArrow(Graphics g, Rectangle r) { int x = r.x + (r.width - 8) / 2 - 1; int y = r.y + (r.height - 6) / 2 + 1; g.drawLine(x + 1, y, x + 1, y); g.drawLine(x + 7, y, x + 7, y); g.drawLine(x, y + 1, x + 2, y + 1); g.drawLine(x + 6, y + 1, x + 8, y + 1); g.drawLine(x + 1, y + 2, x + 3, y + 2); g.drawLine(x + 5, y + 2, x + 7, y + 2); g.drawLine(x + 2, y + 3, x + 6, y + 3); g.drawLine(x + 3, y + 4, x + 5, y + 4); g.drawLine(x + 4, y + 5, x + 4, y + 5); } }