/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*	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);
	}
}
