/*
 * Copyright 2004-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.tools.jconsole;

import java.awt.event.*;
import java.beans.*;
import java.util.*;

import javax.swing.*;

/**
 * A combo box to control the visible time range for one or more Plotter components.
 * When used with two or more Plotters, it also acts to coordinate the range between
 * them.
 */
@SuppressWarnings("serial")
public class TimeComboBox extends JComboBox implements ItemListener, PropertyChangeListener {
    private ArrayList<Plotter> plotters = new ArrayList<Plotter>();

    public TimeComboBox(Plotter... plotterArray) {
        super(Plotter.rangeNames);

        addItemListener(this);

        if (plotterArray != null && plotterArray.length > 0) {
            plotters.addAll(Arrays.asList(plotterArray));
            selectValue(plotterArray[0].getViewRange());
            for (Plotter plotter : plotters) {
                plotter.addPropertyChangeListener(this);
            }
        }
    }

    public void addPlotter(Plotter plotter) {
        plotters.add(plotter);
        if (plotters.size() == 1) {
            selectValue(plotter.getViewRange());
        }
        plotter.addPropertyChangeListener(this);
    }

    public void itemStateChanged(ItemEvent ev) {
        for (Plotter plotter : plotters) {
            plotter.setViewRange(Plotter.rangeValues[getSelectedIndex()]);
        }
    }

    private void selectValue(int value) {
        // Set the selected value
        for (int i = 0; i < Plotter.rangeValues.length; i++) {
            if (Plotter.rangeValues[i] == value) {
                setSelectedItem(Plotter.rangeNames[i]);
            }
        }
        // Make sure all plotters show this value
        if (plotters.size() > 1) {
            for (Plotter plotter : plotters) {
                plotter.setViewRange(value);
            }
        }
    }

    public void propertyChange(PropertyChangeEvent ev) {
        if (ev.getPropertyName() == "viewRange") {
            selectValue((Integer)ev.getNewValue());
        }
    }
}
