/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.ui.attribute.editor;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import org.jboss.tools.common.model.ui.IListEditor;
import org.jboss.tools.common.model.ui.IStructuredChangeListener;
import org.jboss.tools.common.model.ui.IStructuredEditor;
import org.jboss.tools.common.model.ui.IValueProvider;
import org.jboss.tools.common.model.ui.StructuredChange;
import org.jboss.tools.common.model.ui.StructuredChangedEvent;
import org.jboss.tools.common.model.ui.attribute.IListContentProvider;
import org.jboss.tools.common.model.ui.attribute.adapter.StructuredListAdapter;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
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.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.jboss.tools.common.model.ui.widgets.IWidgetSettings;
public class ListStructuredFieldEditor extends ExtendedFieldEditor
implements IPropertyFieldEditor, IStructuredEditor, IListEditor, IFieldEditor, PropertyChangeListener
{
// IPropertyEditor
protected IPropertyEditor propertyEditor;
protected IValueProvider valueProvider;
// IStructuredEditor
protected IStructuredChangeListener structuredChangeListener;
// protected IStructuredContentProvider structuredContentProvider;
protected StructuredListAdapter.INewValueProvider newStructuredElementProvider;
// IListEditor
protected ILabelProvider labelProvider;
protected IListContentProvider listContentProvider;
// ListStructuredFieldEditor
private List list;
private Composite buttonBox;
private static int ADD = 0, REMOVE = 1, UP = 2, DOWN = 3;
private Button[] buttons = new Button[4];
private SelectionListener selectionListener;
private Composite mainPanel;
private java.util.List<Object> elements;
public ListStructuredFieldEditor() {}
public ListStructuredFieldEditor(IWidgetSettings settings) {
super(settings);
}
private void doAdd() {
setPresentsDefaultValue(false);
Object[] input = getNewInputObjects();
for (int i = 0; i < input.length; i++) {
String s = this.labelProvider.getText(input[i]);
int index = list.getSelectionIndex();
int target = -1;
if (index >= 0) {
elements.add(index + 1, input[i]);
list.add(s, target = index + 1);
} else {
elements.add(i, input[i]);
list.add(s, target = i);
}
selectionChanged(target);
}
}
protected Object[] getNewInputObjects() {
Object value = newStructuredElementProvider.getValue();
Object[] values = (value == null) ? new Object[0] : (value instanceof Object[]) ? (Object[])value : new Object[]{value};
if (!allowDuplicates()) {
Set<Object> set = new HashSet<Object>();
ArrayList<Object> l = new ArrayList<Object>();
set.addAll(elements);
for (int i = 0; i < values.length; i++) {
if(set.contains(values[i])) continue;
l.add(values[i]);
set.add(values[i]);
}
values = (Object[])l.toArray(new Object[0]);
}
return values;
}
protected void adjustForNumColumns(int numColumns) {
Control control = getLabelComposite();
((GridData)control.getLayoutData()).horizontalSpan = numColumns;
((GridData)list.getLayoutData()).horizontalSpan = numColumns - 1;
}
private void createButtons(Composite parent) {
buttons[ADD] = createButton(parent, "ListEditor.add"); //$NON-NLS-1$
buttons[REMOVE] = createButton(parent, "ListEditor.remove"); //$NON-NLS-1$
buttons[UP] = createButton(parent, "ListEditor.up"); //$NON-NLS-1$
buttons[DOWN] = createButton(parent, "ListEditor.down"); //$NON-NLS-1$
}
private Button createButton(Composite parent, String key) {
Button b = new Button(parent, SWT.PUSH);
b.setText(JFaceResources.getString(key));
b.setFont(parent.getFont());
GridData d = new GridData(GridData.FILL_HORIZONTAL);
d.heightHint = convertVerticalDLUsToPixels(b, 14/*IDialogConstants.BUTTON_HEIGHT*/);
int widthHint = convertHorizontalDLUsToPixels(b, IDialogConstants.BUTTON_WIDTH);
d.widthHint = Math.max(widthHint, b.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
b.setLayoutData(d);
b.addSelectionListener(getSelectionListener());
return b;
}
public void createSelectionListener() {
selectionListener = new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
if (event.widget == buttons[ADD]) {
doAdd();
} else if (event.widget == buttons[REMOVE]) {
doRemove();
} else if (event.widget == buttons[UP]) {
doUp();
} else if (event.widget == buttons[DOWN]) {
doDown();
} else if (event.widget == list) {
selectionChanged(-1);
}
}
};
}
protected void doFillIntoGrid(Composite parent, int numColumns) {
Control control = getLabelComposite(parent);
assignLabelLayoutData(control, numColumns);
list = createListControl(parent);
assignListLayoutData(list, numColumns);
buttonBox = getButtonBoxControl(parent);
assignButtonLayoutData(buttonBox);
}
private void assignLabelLayoutData(Control control, int numColumns) {
GridData gd = new GridData();
gd.horizontalSpan = numColumns;
control.setLayoutData(gd);
}
private void assignListLayoutData(Control control, int numColumns) {
GridData gd = new GridData(GridData.FILL_BOTH);
//gd.verticalAlignment = GridData.FILL;
gd.horizontalSpan = numColumns - 1;
gd.grabExcessHorizontalSpace = true;
control.setLayoutData(gd);
}
private void assignButtonLayoutData(Control control) {
GridData gd = new GridData();
gd.verticalAlignment = GridData.BEGINNING;
control.setLayoutData(gd);
}
protected void doLoad() {
}
protected void doLoadDefault() {
}
protected void doStore() {
}
private void doDown() {
swap(false);
}
protected Composite getButtonBoxControl(Composite parent) {
if (buttonBox == null) {
buttonBox = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
buttonBox.setLayout(layout);
createButtons(buttonBox);
buttonBox.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent event) {
for (int i = 0; i < buttons.length; i++) buttons[i] = null;
buttonBox = null;
}
});
} else {
checkParent(buttonBox, parent);
}
selectionChanged(0);
return buttonBox;
}
protected Composite getMainPanel(Composite parent) {
if (mainPanel == null) {
mainPanel = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginWidth = 0;
mainPanel.setLayout(layout);
list = createListControl(mainPanel);
GridData gd = new GridData(GridData.FILL_BOTH);
//gd.verticalAlignment = GridData.FILL;
// gd.horizontalSpan = numColumns - 1;
gd.grabExcessHorizontalSpace = true;
list.setLayoutData(gd);
buttonBox = getButtonBoxControl(mainPanel);
gd = new GridData();
gd.verticalAlignment = GridData.BEGINNING;
buttonBox.setLayoutData(gd);
updateSelectionDependentActions();
} else
checkParent(mainPanel, parent);
return mainPanel;
}
protected List getListControl() {
return list;
}
protected List createListControl(Composite parent) {
if (list == null) {
list = new List(parent, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL | SWT.H_SCROLL);
list.setFont(parent.getFont());
list.addSelectionListener(getSelectionListener());
list.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent event) {
list = null;
}
});
list.setItems(getItems());
} else {
if(mainPanel != null) {
checkParent(mainPanel, parent);
} else {
checkParent(list, parent);
}
}
return list;
}
private java.util.List<Object> createElements() {
java.util.List<Object> elements = new ArrayList<Object>();
if (this.listContentProvider!=null)
elements.addAll(Arrays.asList(listContentProvider.getElements(this)));
return elements;
}
private String[] getItems() {
if (this.elements==null) {
elements = createElements();
}
Iterator i = elements.iterator();
ArrayList<String> list = new ArrayList<String>();
while (i.hasNext()) {
Object o = i.next();
String s = this.labelProvider.getText(o);
list.add(s);
}
return list.toArray(new String[list.size()]);
}
public int getNumberOfControls() {
return 2;
}
private SelectionListener getSelectionListener() {
if (selectionListener == null)
createSelectionListener();
return selectionListener;
}
protected Shell getShell() {
if (buttons[ADD] == null)
return null;
return buttons[ADD].getShell();
}
private void doRemove() {
setPresentsDefaultValue(false);
int index = list.getSelectionIndex();
if (index >= 0) {
list.remove(index);
elements.remove(index);
index = list.getItemCount() <= index ? list.getItemCount() - 1 : index;
selectionChanged(index);
}
}
private void selectionChanged(int newSelection) {
// make StructuredChangedEvent and notify StructuredChangeListener
StructuredChange change = new StructuredChange(elements);
StructuredChangedEvent event = new StructuredChangedEvent(listContentProvider, change);
structuredChangeListener.structureChanged(event);
if(newSelection >= 0 && newSelection < list.getItemCount()) {
list.select(newSelection);
}
updateSelectionDependentActions();
}
private void updateSelectionDependentActions() {
int index = list.getSelectionIndex();
int size = list.getItemCount();
buttons[REMOVE].setEnabled(index >= 0);
buttons[UP].setEnabled(size > 1 && index > 0);
buttons[DOWN].setEnabled(size > 1 && index >= 0 && index < size - 1);
}
public void setFocus() {
if (list != null) list.setFocus();
}
private void swap( boolean up) {
setPresentsDefaultValue(false);
int index = list.getSelectionIndex();
int target = up ? index - 1 : index + 1;
if (index >= 0) {
String[] selection = list.getSelection();
Assert.isTrue(selection.length == 1);
list.remove(index);
list.add(selection[0], target);
list.setSelection(target);
// elements
Object o = elements.get(index);
elements.remove(index);
elements.add(target, o);
}
selectionChanged(target);
}
private void doUp() {
swap(true);
}
public void setEnabled(boolean enabled, Composite parent){
super.setEnabled(enabled,parent);
createListControl(parent).setEnabled(enabled);
buttons[ADD].setEnabled(enabled);
if(!enabled) {
buttons[REMOVE].setEnabled(enabled);
buttons[UP].setEnabled(enabled);
buttons[DOWN].setEnabled(enabled);
} else {
updateSelectionDependentActions();
}
}
// IStructuredEditor
public void setStructuredChangeListener(IStructuredChangeListener structuredChangeListener) {
this.structuredChangeListener = structuredChangeListener;
}
public void setStructuredContentProvider(IStructuredContentProvider structuredContentProvider) {
//this.structuredContentProvider = structuredContentProvider;
}
public void setNewStructuredElementProvider(StructuredListAdapter.INewValueProvider valueProvider) {
newStructuredElementProvider = valueProvider;
}
// IListEditor
public void setLabelProvider(ILabelProvider labelProvider) {
this.labelProvider = labelProvider;
}
public void setListContentProvider(IListContentProvider listContentProvider) {
this.listContentProvider = listContentProvider;
// this.structuredContentProvider = listContentProvider;
}
// IFieldEditor
public Control[] getControls(Composite parent) {
// return new Control[] {getLabelComposite(parent), getListControl(parent), getButtonBoxControl(parent)};
return new Control[] {getLabelComposite(parent), getMainPanel(parent)};
}
// IPropertyFieldEditor
public void setPropertyEditor(IPropertyEditor propertyEditor) {
this.propertyEditor = propertyEditor;
if (propertyEditor!=null) {
valueProvider = (IValueProvider)propertyEditor.getAdapter(IValueProvider.class);
// IStructuredEditor
structuredChangeListener = (IStructuredChangeListener)propertyEditor.getAdapter(IStructuredChangeListener.class);
listContentProvider = (IListContentProvider)propertyEditor.getAdapter(IListContentProvider.class);
newStructuredElementProvider = (StructuredListAdapter.INewValueProvider)propertyEditor.getAdapter(StructuredListAdapter.INewValueProvider.class);
// IListEditor
labelProvider = (ILabelProvider)propertyEditor.getAdapter(ILabelProvider.class);
}
valueProvider.addValueChangeListener(this);
}
protected boolean allowDuplicates()
{
return false;
}
public void propertyChange(PropertyChangeEvent evt) {
super.propertyChange(evt);
valueProvider.removeValueChangeListener(this);
if (IPropertyEditor.VALUE.equals(evt.getPropertyName())) {
elements = null;
if(list!=null) {
list.setItems(getItems());
list.redraw();
}
}
valueProvider.addValueChangeListener(this);
}
public void setEnabled(boolean enabled){
super.setEnabled(enabled);
if (getListControl()!=null) {
getListControl().setEnabled(enabled);
}
}
public void cut() {
}
public void copy() {
}
public void paste() {
}
public void delete() {
}
}