/******************************************************************************* * Copyright (c) 2008, 2011 Obeo. * 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: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipse.emf.eef.runtime.ui.gwt.editor.property; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.UniqueEList; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.edit.provider.IItemLabelProvider; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.TextBox; public abstract class FeatureEditor extends Composite { protected Object object; protected boolean isSortChoices; protected List<?> values; protected List<?> choiceOfValues; protected ListBox valueBox; protected ListBox choiceBox; protected EDataType eDataType; protected TextBox textBox; protected FeatureEditor(Object object, boolean isSortChoices, final EDataType eDataType) { this.object = object; this.isSortChoices = isSortChoices; this.eDataType = eDataType; Grid grid = new Grid(); grid.resize(1, 3); grid.getColumnFormatter().setWidth(0, "40%"); grid.getColumnFormatter().setWidth(1, "20%"); grid.getColumnFormatter().setWidth(2, "40%"); valueBox = new ListBox(true); valueBox.setVisibleItemCount(4); valueBox.setWidth("100%"); grid.setWidget(0, 0, valueBox); Grid buttonGrid = new Grid(); buttonGrid.resize(2, 2); Button upButton = new Button("Up ^"); buttonGrid.setWidget(0, 0, upButton); Button downButton = new Button("Down v"); buttonGrid.setWidget(1, 0, downButton); Button addButton = new Button("< Add"); buttonGrid.setWidget(0, 1, addButton); Button removeButton = new Button("Remove >"); buttonGrid.setWidget(1, 1, removeButton); grid.setWidget(0, 1, buttonGrid); if (eDataType != null) { textBox = new TextBox(); textBox.setWidth("100%"); grid.setWidget(0, 2, textBox); /* * textBox.addValueChangeHandler (new * ValueChangeHandler<String>() { public void * onValueChange(ValueChangeEvent<String> event) { List<Object> * result = isUnique() ? new UniqueEList<Object>(values) : new * ArrayList<Object>(values); try { Object value = * EcoreUtil.createFromString(eDataType, event.getValue()); * result.add(value); setValue(result); } catch * (RuntimeException exception) { // Ignore for now } } }); */ } else { choiceBox = new ListBox(true); choiceBox.setVisibleItemCount(4); choiceBox.setWidth("100%"); grid.setWidget(0, 2, choiceBox); } addButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { List<Object> result = isUnique() ? new UniqueEList<Object>(values) : new ArrayList<Object>(values); if (eDataType != null) { try { Object value = EcoreUtil.createFromString(eDataType, textBox.getValue()); result.add(value); } catch (RuntimeException exception) { // Ignore for now } } else { for (int i = 0, size = choiceBox.getItemCount(); i < size; ++i) { if (choiceBox.isItemSelected(i)) { result.add(choiceOfValues.get(i)); } } } setValue(result); } }); removeButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { List<Object> result = isUnique() ? new UniqueEList<Object>(values) : new ArrayList<Object>(values); for (int i = 0, size = valueBox.getItemCount(); i < size; ++i) { if (valueBox.isItemSelected(i)) { result.remove(values.get(i)); } } setValue(result); } }); upButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { EList<Object> result = new BasicEList<Object>(values); for (int i = 0, size = valueBox.getItemCount(); i < size; ++i) { if (valueBox.isItemSelected(i)) { if (i != 0) { result.move(i, i - 1); } } } setValue(result); } }); downButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { EList<Object> result = new BasicEList<Object>(values); for (int i = 0, size = valueBox.getItemCount(); i < size; ++i) { if (valueBox.isItemSelected(i)) { if (i + 1 < size) { result.move(i, i + 1); } } } setValue(result); } }); initWidget(grid); } protected void hook(ListBox listBox, List<?> values) { // Do nothing. } public void update() { IItemLabelProvider labelProvider = getLabelProvider(); List<?> oldValues = values; values = new ArrayList<Object>(getValues()); List<Object> oldValueSelection = new ArrayList<Object>(); int valueBoxItemCount = valueBox.getItemCount(); if (valueBoxItemCount != 0) { for (int i = 0; i < valueBoxItemCount; ++i) { if (valueBox.isItemSelected(i)) { oldValueSelection.add(oldValues.get(i)); } } valueBox.clear(); } for (Object value : values) { valueBox.addItem(labelProvider.getText(value)); if (oldValueSelection.contains(value) || oldValues != null && !oldValues.contains(value)) { valueBox.setItemSelected(valueBox.getItemCount() - 1, true); } } hook(valueBox, values); if (eDataType != null) { textBox.setValue(""); } else { List<Object> oldChoiceSelection = new ArrayList<Object>(); int choiceBoxItemCount = choiceBox.getItemCount(); if (choiceBoxItemCount != 0) { for (int i = 0; i < choiceBoxItemCount; ++i) { if (choiceBox.isItemSelected(i)) { oldChoiceSelection.add(choiceOfValues.get(i)); } } choiceBox.clear(); } Collection<?> basicChoices = getChoiceOfValues(); if (basicChoices == null) { choiceOfValues = null; } else { choiceOfValues = new ArrayList<Object>(basicChoices); if (isSortChoices) { createItems(choiceOfValues, labelProvider, null, true); } for (Object value : choiceOfValues) { choiceBox.addItem(labelProvider.getText(value)); if (oldChoiceSelection.contains(value) || oldValues != null && oldValues.contains(value) && !values.contains(value)) { choiceBox.setItemSelected(choiceBox.getItemCount() - 1, true); } } hook(choiceBox, choiceOfValues); } } } public static <T> String[] createItems(List<T> list, IItemLabelProvider labelProvider, String filter, boolean sorted) { String[] result; if (filter != null && filter.length() > 0) { sorted = true; } // If there are objects to populate... // if (list != null && list.size() > 0) { if (sorted) { List<T> unsortedList = new ArrayList<T>(list.size()); if (filter != null && filter.length() > 0) { for (int i = 0; i < list.size(); i++) { if (select(filter, labelProvider.getText(list.get(i)))) { unsortedList.add(list.get(i)); } } } else { unsortedList.addAll(list); } list.clear(); StringPositionPair[] pairs = new StringPositionPair[unsortedList.size()]; for (int i = 0, size = unsortedList.size(); i < size; ++i) { Object object = unsortedList.get(i); pairs[i] = new StringPositionPair(labelProvider.getText(object), i); } Arrays.sort(pairs); // Create a new array. // result = new String[unsortedList.size()]; // Fill in the result array with labels and re-populate the // original list in order. // for (int i = 0, size = unsortedList.size(); i < size; ++i) { result[i] = pairs[i].key; list.add(unsortedList.get(pairs[i].position)); } } else { // Create a new array. // result = new String[list.size()]; // Fill in the array with labels. // for (int i = 0, size = list.size(); i < size; ++i) { Object object = list.get(i); result[i] = labelProvider.getText(object); } } } else { result = new String[] { "" }; } return result; } protected abstract IItemLabelProvider getLabelProvider(); protected abstract List<?> getValues(); protected abstract Collection<?> getChoiceOfValues(); protected abstract boolean isMultiLine(); protected abstract boolean isUnique(); protected abstract void setValue(Object value); public static boolean select(String filter, String labelValue) { if (filter != null && filter.length() > 0) { if (filter.length() > labelValue.length()) { return false; } for (int i = 0; i < filter.length(); i++) { if (Character.toLowerCase(filter.charAt(i)) != Character.toLowerCase(labelValue.charAt(i))) { return false; } } } return true; } private static class StringPositionPair implements Comparable<StringPositionPair> { public String key; public int position; StringPositionPair(String key, int position) { this.key = key; this.position = position; } public int compareTo(StringPositionPair object) { if (object == this || key == object.key) { return 0; } else if (key == null) { return -1; } else { return key.compareTo(object.key); } } } }