/*******************************************************************************
 * Copyright (c) 2004, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Sebastian Davids - bug 69254
 *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 430873
 *******************************************************************************/

package org.eclipse.jface.viewers;

import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

/**
 * A concrete viewer based either on an SWT <code>Combo</code> control or <code>CCombo</code>
 * control. This class is intended as an alternative to the JFace <code>ListViewer</code>, which displays
 * its content in a combo box rather than a list. Wherever possible, this class attempts to behave
 * like ListViewer. <p>
 *
 * This class is designed to be instantiated with a pre-existing SWT combo control
 * and configured with a domain-specific content provider, label provider, element
 * filter (optional), and element sorter (optional).
 * </p>
 *
 * @see org.eclipse.jface.viewers.ListViewer
 * @since 3.0 (made non-final in 3.4)
 */
public class ComboViewer extends AbstractListViewer {

    /**
     * This viewer's list control if this viewer is instantiated with a combo control; otherwise
     * <code>null</code>.
     *
     * @see #ComboViewer(Combo)
     */
    private Combo combo;

    /**
     * This viewer's list control if this viewer is instantiated with a CCombo control; otherwise
     * <code>null</code>.
     *
     * @see #ComboViewer(CCombo)
     * @since 3.3
     */
    private CCombo ccombo;

    /**
     * Creates a combo viewer on a newly-created combo control under the given parent.
     * The viewer has no input, no content provider, a default label provider,
     * no sorter, and no filters.
     *
     * @param parent the parent control
     */
    public ComboViewer(Composite parent) {
        this(parent, SWT.READ_ONLY | SWT.BORDER);
    }

    /**
     * Creates a combo viewer on a newly-created combo control under the given parent.
     * The combo control is created using the given SWT style bits.
     * The viewer has no input, no content provider, a default label provider,
     * no sorter, and no filters.
     *
     * @param parent the parent control
     * @param style the SWT style bits
     */
    public ComboViewer(Composite parent, int style) {
        this(new Combo(parent, style));
    }

    /**
     * Creates a combo viewer on the given combo control.
     * The viewer has no input, no content provider, a default label provider,
     * no sorter, and no filters.
     *
     * @param list the combo control
     */
    public ComboViewer(Combo list) {
        this.combo = list;
        hookControl(list);
    }

    /**
     * Creates a combo viewer on the given CCombo control.
     * The viewer has no input, no content provider, a default label provider,
     * no sorter, and no filters.
     *
     * @param list the CCombo control
     * @since 3.3
     */
    public ComboViewer(CCombo list) {
        this.ccombo = list;
        hookControl(list);
    }

    @Override
	protected void listAdd(String string, int index) {
        if (combo == null) {
            ccombo.add(string, index);
        } else {
            combo.add(string, index);
        }
    }

    @Override
	protected void listSetItem(int index, String string) {
        if (combo == null) {
            ccombo.setItem(index, string);
        } else {
            combo.setItem(index, string);
        }
    }

    @Override
	protected int[] listGetSelectionIndices() {
        if (combo == null) {
            return new int[] { ccombo.getSelectionIndex() };
        }
        return new int[] { combo.getSelectionIndex() };
    }

    @Override
	protected int listGetItemCount() {
        if (combo == null) {
            return ccombo.getItemCount();
        }
        return combo.getItemCount();
    }

    @Override
	protected void listSetItems(String[] labels) {
        if (combo == null) {
            ccombo.setItems(labels);
        } else {
            combo.setItems(labels);
        }
    }

    @Override
	protected void listRemoveAll() {
        if (combo == null) {
            ccombo.removeAll();
        } else {
            combo.removeAll();
        }
    }

    @Override
	protected void listRemove(int index) {
        if (combo == null) {
            ccombo.remove(index);
        } else {
            combo.remove(index);
        }
    }

    @Override
	public Control getControl() {
        if (combo == null) {
            return ccombo;
        }
        return combo;
    }

    /**
	 * Returns this list viewer's list control. If the viewer was not created on
	 * a CCombo control, some kind of unchecked exception is thrown.
	 *
	 * @return the list control
     * @since 3.3
	 */
    public CCombo getCCombo() {
        Assert.isNotNull(ccombo);
        return ccombo;
    }

    /**
     * Returns this list viewer's list control. If the viewer was not created on
	 * a Combo control, some kind of unchecked exception is thrown.
     *
     * @return the list control
     */
    public Combo getCombo() {
    	Assert.isNotNull(combo);
        return combo;
    }

    /*
     * Do nothing -- combos only display the selected element, so there is no way
     * we can ensure that the given element is visible without changing the selection.
     * Method defined on StructuredViewer.
     */
    @Override
	public void reveal(Object element) {
    }


    @Override
	protected void listSetSelection(int[] ixs) {
        if (combo == null) {
            for (int ix : ixs) {
                ccombo.select(ix);
            }
        } else {
            for (int ix : ixs) {
                combo.select(ix);
            }
        }
    }

    @Override
	protected void listDeselectAll() {
        if (combo == null) {
            ccombo.deselectAll();
            ccombo.clearSelection();
        } else {
            combo.deselectAll();
            combo.clearSelection();
        }
    }

    @Override
	protected void listShowSelection() {
    }
}
