/*
 * @(#)ILBMView.java  1.3  2009-12-24
 *
 * Copyright (c) 1999-2009 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.view;

import org.monte.media.ilbm.ColorCyclingMemoryImageSource;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.activation.DataHandler;
import java.awt.Image;
import java.io.IOException;
import org.monte.media.ilbm.ILBMDecoder;
import ch.randelshofer.util.PropertyModel;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.io.InputStream;
import javax.swing.AbstractAction;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import org.jhotdraw.util.ResourceBundleUtil;

/**
 * This viewer displays images of type IFF ILBM.
 *
 * @version 1.3 2009-12-24 Added support for color cycling.
 * <br>1.2 2003-08-15 Method toString returns some additional info about the image.
 * <br>1.1   2000-09-28 Suffix '_' removed from instance variable names.
 * <br> 1.0  1999-10-19 Created.
 */
public class ILBMView extends ImageView {


    /** Menu items. */
    protected JCheckBoxMenuItem colorCyclingItem;
    /** Menu items. */
    protected JCheckBoxMenuItem blendColorCyclesItem;
    /**
     * Resource bundle for internationalisation.
     */
    protected ResourceBundleUtil labels;
    protected ColorCyclingMemoryImageSource imageSource;

    /** Initializes the Form */
    public ILBMView() {
        labels = ResourceBundleUtil.getBundle("ch.randelshofer.view.AbstractVideoView");
        initMoreComponents();

        // Toggle Color Cycling with TAB key
        // -------------------------------------
        // Normally, the focus subsystem consumes
        // focus traversal keys, such as Tab and Shift Tab.
        // By disabling the focus traversal keys, we can capture
        // the tab key.
        setFocusTraversalKeysEnabled(false);
        setRequestFocusEnabled(true);
        setFocusable(true);
        scrollPane.setFocusTraversalKeysEnabled(false);
        scrollPane.getViewport().setFocusTraversalKeysEnabled(false);
        imagePanel.setFocusTraversalKeysEnabled(false);
        imagePanel.setRequestFocusEnabled(true);
        imagePanel.setFocusable(true);
        imagePanel.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                imagePanel.requestFocus();
            }
        });
        getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "toggleColorCycle");
        getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "toggleColorCycle");
        getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "toggleColorCycle");
        getActionMap().put("toggleColorCycle", new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                colorCyclingItem.setSelected(!colorCyclingItem.isSelected());
                getViewProperties().put(
                        "colorCycling", String.valueOf(colorCyclingItem.isSelected()));
            }
        });
    }

    @Override
    public void mergeViewMenuItems(JMenu m) {
        super.mergeViewMenuItems(m);

        m.add(new JSeparator(), m.getMenuComponentCount() - 13);
        m.add(colorCyclingItem, m.getMenuComponentCount() - 13);
        m.add(blendColorCyclesItem, m.getMenuComponentCount() - 13);
    }

    private void initMoreComponents() {
        // Menu items for color cycling
        colorCyclingItem = new JCheckBoxMenuItem(labels.getString("colorCycling"));
        colorCyclingItem.setMnemonic(labels.getMnemonic("colorCyclingMnem"));
        colorCyclingItem.setAccelerator(labels.getKeyStroke("colorCyclingAcc"));
        colorCyclingItem.addItemListener(this);
        blendColorCyclesItem = new JCheckBoxMenuItem(labels.getString("blendColorCycles"));
        blendColorCyclesItem.setMnemonic(labels.getMnemonic("blendColorCyclesMnem"));
        blendColorCyclesItem.setAccelerator(labels.getKeyStroke("blendColorCyclesAcc"));
        blendColorCyclesItem.addItemListener(this);
    }
    @Override
    public void itemStateChanged(ItemEvent event) {
        super.itemStateChanged(event);

        Object source = event.getSource();
        PropertyModel p = getViewProperties();

        // Handle selection and deselection for JCheckBoxMenuItem's
        if (source == colorCyclingItem) {
            getViewProperties().put(
                    "colorCycling", String.valueOf(colorCyclingItem.isSelected()));
        }
        if (source == blendColorCyclesItem) {
            getViewProperties().put(
                    "blendColorCycles", String.valueOf(blendColorCyclesItem.isSelected()));
        }

    }

    @Override
    public void propertyChange(PropertyChangeEvent event) {
        super.propertyChange(event);

        Object source = event.getSource();
        String key = event.getPropertyName();

        if (source == getViewProperties()) {
            if (key.equals("colorCycling") || key.equals("blendColorCycles")) {
                updateColorCycling();
            }
        }
    }

    protected void updateColorCycling() {
        boolean b = getViewProperties().getProperty("colorCycling", "true").equals("true");
        colorCyclingItem.setSelected(b);

        if (imageSource != null) {
            imageSource.setColorCyclingStarted(b);
        }
        b = getViewProperties().getProperty("blendColorCycles", "false").equals("true");
        blendColorCyclesItem.setSelected(b);
        if (imageSource != null) {
            imageSource.setBlendedColorCycling(b);
        }
    }

    @Override
    protected void updateViewProperties() {
        super.updateViewProperties();
        updateColorCycling();
    }

    @Override
    public String getViewName() {
        return "IFF ILBM View";
    }

    @Override
    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append(super.toString());

        Image image = imagePanel.getImage();
        Object value;
        if (image != null) {
            value = image.getProperty("screenMode", this);
            if (value != Image.UndefinedProperty && value != null) {
                buf.append("\n   Screen Mode: ");
                buf.append(value);
            }
            value = image.getProperty("nbPlanes", this);
            if (value != Image.UndefinedProperty && value != null) {
                buf.append("\n   Number of Planes: ");
                buf.append(value);
            }
            value = image.getProperty("colorCycling", this);
            if (value != Image.UndefinedProperty && value != null) {
                buf.append("\n   Color Cycles: ");
                buf.append(value);
            }
        }
        return buf.toString();
    }
    @Override
    public void setCommandContext(String verb, DataHandler dh)
            throws IOException {
        dispose();
        if (dh != null) {
            InputStream in = dh.getInputStream();
            try {
                ILBMDecoder decoder = new ILBMDecoder(in);
                ArrayList<ColorCyclingMemoryImageSource> v = decoder.produce();
                if (v.size() > 0) {
                    imageSource = v.get(0);
                    imagePanel.setImage(getToolkit().createImage(imageSource));
                    colorCyclingItem.setEnabled(imageSource.isColorCyclingAvailable());
                    blendColorCyclesItem.setEnabled(imageSource.isColorCyclingAvailable());
                }
            } finally {
                in.close();
            }
        }
    }
}
