/*
 * @(#)PDFLookAndFeel.java  1.0  2008-09-22
 * 
 * Copyright (c) 2008 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
package ch.randelshofer.pdf.plaf;

import ch.randelshofer.gui.icon.ButtonStateIcon;
import ch.randelshofer.gui.border.ScrollBarThumbBorder;
import ch.randelshofer.gui.border.ColorBorder;
import ch.randelshofer.gui.border.ImageBevelBorder;
import org.monte.media.image.Images;
import ch.randelshofer.pdf.plaf.color.GradientColor;
import ch.randelshofer.gui.icon.SliderThumbIcon;
import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.DimensionUIResource;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.IconUIResource;
import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicLookAndFeel;

/**
 * PDFLookAndFeel.
 *
 * @author Werner Randelshofer, Hausmatt 10, CH-6405 Immensee
 * @version 1.0 2008-09-22 Created.
 */
public class PDFLookAndFeel extends BasicLookAndFeel {

    protected final static String commonDir = "/ch/randelshofer/pdf/plaf/images/";
    private static PDFLookAndFeel instance;
    private UIDefaults defaults;

    public static PDFLookAndFeel getInstance() {
        if (instance == null) {
            instance = new PDFLookAndFeel();
        }
        return instance;
    }

    @Override
    public String getName() {
        return "PDF Look and Feel";
    }

    @Override
    public String getID() {
        return "PDF";
    }

    @Override
    public String getDescription() {
        return "PDF Look and Feel";
    }

    @Override
    public boolean isNativeLookAndFeel() {
        return false;
    }

    @Override
    public boolean isSupportedLookAndFeel() {
        return true;
    }

    @Override
    public UIDefaults getDefaults() {
        if (defaults == null) {
            UIDefaults table = super.getDefaults();
            initColorDefaults(table);
            defaults = table;
        }
        return defaults;
    }

    public boolean getBoolean(Object key) {
        return getDefaults().getBoolean(key);
    }

    public Color getColor(Object key) {
        return getDefaults().getColor(key);
    }

    public Font getFont(Object key) {
        return getDefaults().getFont(key);
    }

    public Border getBorder(Object key) {
        return getDefaults().getBorder(key);
    }
    public Insets getInsets(Object key) {
        return getDefaults().getInsets(key);
    }


    public Icon getIcon(Object key) {
        return getDefaults().getIcon(key);
    }
    public Object get(Object key) {
        UIManager.get(key);
        return getDefaults().get(key);
    }


    protected void initColorDefaults(UIDefaults table) {
        FontUIResource font = new FontUIResource("Arial", Font.PLAIN, 13); 
        FontUIResource emphasizedFont = new FontUIResource("Arial", Font.BOLD, 13); 
        Object textFieldBorder = new PDFTextFieldBorder.UIResource(
                commonDir + "TextField.borders.png",
                new Insets(5,4,4,4), new Insets(3,3,3,3)
                );
        Object[] uiDefaults = {
            "Button.opaque", Boolean.FALSE,
            "Label.font", font,
            "Label.opaque", Boolean.FALSE,
            "Label.border", null,
            "ScrollBar.minimumThumbSize", new DimensionUIResource(24, 24),
            "ScrollBar.smallMinimumThumbSize", new DimensionUIResource(18, 18),
            "ScrollBar.maximumThumbSize", new DimensionUIResource(Integer.MAX_VALUE, Integer.MAX_VALUE),
            "ScrollBar.hThumbBorder", new ScrollBarThumbBorder(Images.createImage(PDFLookAndFeel.class, commonDir + "ScrollBar.hThumbs.png"), 5, false, new Insets(0,14,0,14), new Insets(0,0,0,0), true),
            "ScrollBar.hTrack", makeImageBevelBorder(commonDir + "ScrollBar.hTrack.png", new Insets(0,0,0,0)),
            "ScrollBar.sep.hButtons", makeImageBevelBorders(commonDir + "ScrollBar.sep.hButtons.png", new Insets(14, 26, 0, 26), 4, false),
            "ScrollBar.vThumbBorder", new ScrollBarThumbBorder(Images.createImage(PDFLookAndFeel.class, commonDir + "ScrollBar.vThumbs.png"), 5, true, new Insets(14,0,14,0), new Insets(0,0,0,0), true),
            "ScrollBar.vTrack", makeImageBevelBorder(commonDir + "ScrollBar.vTrack.png", new Insets(0,0,0,0)),
            "ScrollBar.sep.vButtons", makeImageBevelBorders(commonDir + "ScrollBar.sep.vButtons.png", new Insets(26, 14, 26, 0), 4, true),
            "ScrollBar.focusable", Boolean.FALSE,
            "Slider.horizontalTracks", makeImageBevelBorders(commonDir + "Slider.horizontalTracks.png", new Insets(5, 4, 0, 4), 2, false),
            "Slider.roundThumb", new SliderThumbIcon(Images.createImage(PDFLookAndFeel.class, commonDir + "Slider.roundThumbs.png"), 6, true),
            "SplitPane.opaque", Boolean.TRUE,
            "SplitPane.background", new ColorUIResource(0x999999),
            "SplitPane.thumbDimple", new ImageIcon(Images.createImage(PDFLookAndFeel.class, commonDir + "SplitPane.thumbDimple.png")),
            "SplitPane.border", null,
            "SplitPane.dividerSize", 9,
            "SplitPaneDivider.border", null,
            "TextField.font", font,
            "TextField.border", textFieldBorder,
            "TextField.opaque", Boolean.FALSE,
            // "TextField.popupHandler", textComponentPopupHandler,
            "TextField.background", new ColorUIResource(0xffffff),
            "TextField.selectionBackground", new ColorUIResource(0xb5d5ff),
            "TextField.selectionForeground", new ColorUIResource(0x0),
            "TextField.autoSelect", Boolean.TRUE,
           // "TextField.visualMargin", new InsetsUIResource(5,3,3,3),
            "TextField.margin", new InsetsUIResource(1,1,1,1),
            "ToolBar.border", new BorderUIResource.CompoundBorderUIResource(
                    new ColorBorder.UIResource(new Color(0x666666),new Insets(0,0,1,0)),
                    new BorderUIResource.EmptyBorderUIResource(1,5,1,5)),
            "ToolBar.background", new GradientColor(new Color(0xe9e9e9), new Color(0xe9e9e9), new Color(0xcccccc)),
            "ToolBar.separatorSize", new DimensionUIResource(10,28),
            "ToolBarSeparator.foreground", new ColorUIResource(0x999999),
            "Viewport.background", new ColorUIResource(0x999999),
            "ScrollPane.viewportBorder", makeImageBevelBorder(commonDir + "ScrollPane.viewportBorder.png", new Insets(4,0,0,0), new Insets(0,0,0,0), false),
            
            //
            // PDF-specific elements
            "ThumbnailsPanel.font", font,
            "ThumbnailsPanel.selectionFont", emphasizedFont,
            "ThumbnailsPanel.iconTextGap", new Integer(2),
            "ThumbnailsPanel.foreground", new ColorUIResource(0x0),
            "ThumbnailsPanel.background", new ColorUIResource(0x999999),
            "ThumbnailsPanel.selectionForeground", new ColorUIResource(0xffffff),
            "ThumbnailsPanel.selectionBackground", new ColorUIResource(0x0066cc),
            "ThumbnailsPanel.thumbnailBorders", makeImageBevelBorders(commonDir+"thumbnail.borders.png", new Insets(7,7,8,7), new Insets(3,4,5,4), 2, true, false),
 /*           makeImage("images/thumbnail.border.png"),
            new Insets(6, 6, 8, 6),
            new Insets(1, 2, 3, 2)),*/
            "PagePanel.border", new BorderUIResource.EmptyBorderUIResource(3,4,6,4),
            "Page.border", new ImageBevelBorder(
            makeImage("images/page.border.png"),
            new Insets(9, 8, 10, 8),
            new Insets(3, 4, 6, 4), false),
            "View.nextPageIcon", new ButtonStateIcon(makeImage("images/view.nextPage.png"), 6, true),
            "View.previousPageIcon", new ButtonStateIcon(makeImage("images/view.previousPage.png"), 6, true),
            "View.fitWidthIcon", new ButtonStateIcon(makeImage("images/view.fitWidth.png"), 6, true),
            "View.fitPageIcon", new ButtonStateIcon(makeImage("images/view.fitPage.png"), 6, true),
            "View.rotatePageIcon", new ButtonStateIcon(makeImage("images/view.rotatePage.png"), 6, true),
            "View.openInNewWindowIcon", new ButtonStateIcon(makeImage("images/view.openInNewWindow.png"), 6, true),
            "View.printIcon", new ButtonStateIcon(makeImage("images/view.print.png"), 6, true),
        };
        table.putDefaults(uiDefaults);
    }

    protected Image makeImage(String location) {
        URL resource = PDFLookAndFeel.class.getResource(location);
        if (resource == null) {
            System.err.println("Warning: PDFButtonBorder couldn't find resource for "+location);
            return null;
        }
        return Images.createImage(resource);
    }

    /**
     * Convenience method for installing a component's default Border 
     * object on the specified component if either the border is 
     * currently null or already an instance of UIResource.
     * @param c the target component for installing default border
     * @param defaultBorderName the key specifying the default border
     */
    public static void installBorder(JComponent c, String defaultBorderName) {
        Border b = c.getBorder();
        if (b == null || b instanceof UIResource) {
            c.setBorder(getInstance().getBorder(defaultBorderName));
        }
    }

    /**
     * Convenience method for initializing a components foreground
     * background and font properties with values from the current
     * defaults table.  The properties are only set if the current
     * value is either null or a UIResource.
     * 
     * @param c the target component for installing default color/font properties
     * @param defaultBgName the key for the default background
     * @param defaultFgName the key for the default foreground
     * @param defaultFontName the key for the default font
     * 
     * @see #installColors
     * @see UIManager#getColor
     * @see UIManager#getFont
     */
    public static void installColorsAndFont(JComponent c,
            String defaultBgName,
            String defaultFgName,
            String defaultFontName) {
        Font f = c.getFont();
        if (f == null || f instanceof UIResource) {
            c.setFont(getInstance().getFont(defaultFontName));
        }

        installColors(c, defaultBgName, defaultFgName);
    }

    /**
     * Convenience method for initializing a component's foreground
     * and background color properties with values from the current
     * defaults table.  The properties are only set if the current
     * value is either null or a UIResource.
     * 
     * @param c the target component for installing default color/font properties
     * @param defaultBgName the key for the default background
     * @param defaultFgName the key for the default foreground
     * 
     * @see #installColorsAndFont
     * @see UIManager#getColor
     */
    public static void installColors(JComponent c,
            String defaultBgName,
            String defaultFgName) {
        Color bg = c.getBackground();
        if (bg == null || bg instanceof UIResource) {
            c.setBackground(getInstance().getColor(defaultBgName));
        }

        Color fg = c.getForeground();
        if (fg == null || fg instanceof UIResource) {
            c.setForeground(getInstance().getColor(defaultFgName));
        }
    }
    protected Object makeBufferedImage(String location) {
        return Images.createImage(PDFLookAndFeel.class, location);
    }
    protected static Object makeIcons(String location, int states, boolean horizontal) {
        Icon[] icons = new Icon[states];
        
        BufferedImage[] images = Images.split(
                (Image) Images.createImage(PDFLookAndFeel.class, location),
                states, horizontal
                );
        
        for (int i=0; i < states; i++) {
            icons[i] = new IconUIResource(new ImageIcon(images[i]));
        }
        return icons;
    }
    protected Object makeImageBevelBorder(String location, Insets insets) {
        return makeImageBevelBorder(location, insets, false);
    }

    protected Object makeImageBevelBorder(String location, Insets insets, boolean fill) {
        return new ImageBevelBorder.UIResource(Images.createImage(PDFLookAndFeel.class, location), insets, insets, fill);
    }
    protected Object makeImageBevelBorder(String location, Insets imageInsets, Insets borderInsets, boolean fill) {
        return new ImageBevelBorder.UIResource(Images.createImage(PDFLookAndFeel.class, location), imageInsets, borderInsets, fill);
    }


    protected Object makeImageBevelBorders(String location, Insets insets, int states, boolean horizontal) {
        return makeImageBevelBorders(location, insets, insets, states, horizontal, true);
    }
    protected Object makeImageBevelBorders(String location, Insets imageInsets, Insets borderInsets, int states, boolean horizontal, boolean fill) {
        BufferedImage[] images = Images.split(
                Images.createImage(PDFLookAndFeel.class, location),
                states, horizontal
                );
        Border[] borders = new Border[states];
        for (int i=0; i < states; i++) {
            borders[i] = new ImageBevelBorder(images[i], imageInsets, borderInsets, fill);
        }
        return borders;
}
}
