/*******************************************************************************
 * Copyright (c) 2000, 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.omnetpp.common.ui;

import org.eclipse.core.commands.common.EventManager;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Composite;
import org.omnetpp.common.color.ColorFactory;

/**
 * This is a modified version of <code>org.eclipse.jface.preference.ColorSelector</code>.
 * The reasons to copy and modify it are (1) to make the color image a small rectangle,
 * and (2) to let it support a "grayed" state when the color image displays an X.
 *
 * <code>ColorSelector</code> is a wrapper for a button that displays a
 * selected <code>Color</code> and allows the user to change the selection.
 */
public class ColorSelector extends EventManager {
    /**
     * Property name that signifies the selected color of this
     * <code>ColorSelector</code> has changed.
     */
    public static final String PROP_COLORCHANGE = "colorValue";

    private Button fButton;
    private RGB fColorValue;

    /**
     * Create a new instance of the receiver and the button that it wraps in
     * the supplied parent <code>Composite</code>.
     */
    public ColorSelector(Composite parent) {
        fButton = new Button(parent, SWT.PUSH);
        fButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                open();
            }
        });
        fButton.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent event) {
                Image image = fButton.getImage();
                if (image != null)
                    image.dispose();
            }
        });
    }

    /**
     * Adds a property change listener to this <code>ColorSelector</code>.
     * Events are fired when the color in the control changes via the user
     * clicking an selecting a new one in the color dialog. No event is fired in
     * the case where <code>setColorValue(RGB)</code> is invoked.
     */
    public void addListener(IPropertyChangeListener listener) {
        addListenerObject(listener);
    }

    /**
     * Removes the given listener from this <code>ColorSelector</code>. Has
     * no affect if the listener is not registered.
     */
    public void removeListener(IPropertyChangeListener listener) {
        removeListenerObject(listener);
    }

    /**
     * Get the button control being wrapped by the selector.
     */
    public Button getButton() {
        return fButton;
    }

    /**
     * Return the currently displayed color, or null if no color was selected
     * (the button displays an X).
     */
    public RGB getColorValue() {
        return fColorValue;
    }

    /**
     * Set the current color value and update the control. A null value is also accepted,
     * and will display an X on the button.
     */
    public void setColorValue(RGB rgb) {
        fColorValue = rgb;
        updateColorImage();
    }

    /**
     * Set whether or not the button is enabled.
     */
    public void setEnabled(boolean state) {
        getButton().setEnabled(state);
    }

    /**
     * Update the image being displayed on the button using the current color
     * setting.
     */
    protected void updateColorImage() {
        Image oldImage = fButton.getImage();
        if (oldImage != null)
            oldImage.dispose();
        fButton.setImage(ColorFactory.createColorImage(fColorValue));
    }

    /**
     * Activate the editor for this selector. This causes the color selection
     * dialog to appear and wait for user input.
     */
    public void open() {
        ColorDialog colorDialog = new ColorDialog(fButton.getShell());
        colorDialog.setRGB(fColorValue);
        RGB newColor = colorDialog.open();
        if (newColor != null) {
            RGB oldValue = fColorValue;
            fColorValue = newColor;
            final Object[] finalListeners = getListeners();
            if (finalListeners.length > 0) {
                PropertyChangeEvent pEvent = new PropertyChangeEvent(this, PROP_COLORCHANGE, oldValue, newColor);
                for (int i = 0; i < finalListeners.length; ++i) {
                    IPropertyChangeListener listener = (IPropertyChangeListener) finalListeners[i];
                    listener.propertyChange(pEvent);
                }
            }
            updateColorImage();
        }
    }
}
