/*******************************************************************************
* 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.IValueProvider;
import org.jboss.tools.common.model.ui.attribute.IListContentProvider;
import org.jboss.tools.common.model.ui.attribute.adapter.DefaultValueAdapter;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.jboss.tools.common.model.ui.widgets.IWidgetSettings;
public class MultipleChoiceFieldEditor extends ExtendedFieldEditor
implements IPropertyFieldEditor, IListEditor, IFieldEditor, PropertyChangeListener {
protected IPropertyEditor propertyEditor;
protected IValueProvider valueProvider;
protected ILabelProvider labelProvider;
protected IListContentProvider listContentProvider;
protected Composite list;
protected Button[] boxes = new Button[0];
protected Composite buttonsParent;
Map<String,Choice> choicesMap = new HashMap<String,Choice>();
ArrayList<Choice> choicesArray = new ArrayList<Choice>();
public MultipleChoiceFieldEditor() {}
public MultipleChoiceFieldEditor(IWidgetSettings settings) {
super(settings);
}
private void addChoice(Choice c) {
choicesMap.put(c.name, c);
choicesArray.add(c);
}
private void removeChoice(Choice c) {
choicesMap.remove(c.name);
choicesArray.remove(c);
}
class Choice extends SelectionAdapter {
String name;
boolean selected;
boolean allowed = true;
Button box;
public Choice(String name) {
this.name = name;
addChoice(this);
}
public void setSelected(boolean b) {
selected = b;
if(box != null && !box.isDisposed()) box.setSelection(selected);
}
public void setAllowed(boolean b) {
allowed = b;
if(box != null && !box.isDisposed()) {
int color = (allowed) ? SWT.COLOR_BLACK : SWT.COLOR_DARK_RED;
box.setForeground(Display.getDefault().getSystemColor(color));
}
}
public void widgetSelected(SelectionEvent e) {
selected = box.getSelection();
fireValueChange();
}
public void create() {
if(buttonsParent == null || buttonsParent.isDisposed()) return;
if(box == null || box.isDisposed()) {
box = new Button(buttonsParent, SWT.CHECK);
box.setText(name);
box.addSelectionListener(this);
}
}
public void dispose() {
if(box != null && !box.isDisposed()) {
box.dispose();
box = null;
removeChoice(this);
}
}
}
protected Choice getChoice(String name, boolean create) {
Choice c = (Choice)choicesMap.get(name);
if(c == null && create) c = new Choice(name);
if(c != null) c.create();
return c;
}
public void setPropertyEditor(IPropertyEditor propertyEditor) {
this.propertyEditor = propertyEditor;
if (propertyEditor!=null) {
valueProvider = (IValueProvider)propertyEditor.getAdapter(IValueProvider.class);
listContentProvider = (IListContentProvider)propertyEditor.getAdapter(IListContentProvider.class);
labelProvider = (ILabelProvider)propertyEditor.getAdapter(ILabelProvider.class);
}
valueProvider.addValueChangeListener(this);
}
protected void adjustForNumColumns(int numColumns) {
Control control = getLabelComposite();
((GridData)control.getLayoutData()).horizontalSpan = numColumns;
((GridData)list.getLayoutData()).horizontalSpan = numColumns - 1;
}
protected void doFillIntoGrid(Composite parent, int numColumns) {
Control control = getLabelComposite(parent);
GridData gd = new GridData();
gd.horizontalSpan = numColumns;
control.setLayoutData(gd);
list = createListControl(parent);
gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = numColumns - 1;
gd.grabExcessHorizontalSpace = true;
list.setLayoutData(gd);
}
protected void doLoad() {}
protected void doLoadDefault() {}
protected void doStore() {}
public int getNumberOfControls() {
return 2;
}
public void setLabelProvider(ILabelProvider labelProvider) {
this.labelProvider = labelProvider;
}
public void setListContentProvider(IListContentProvider listContentProvider) {
this.listContentProvider = listContentProvider;
}
public Control[] getControls(Composite parent) {
return new Control[] {getLabelComposite(parent), createListControl(parent)};
}
boolean propertyChangeEnabled = true;
public void propertyChange(PropertyChangeEvent evt) {
if(!propertyChangeEnabled) return;
super.propertyChange(evt);
valueProvider.removeValueChangeListener(this);
if (IPropertyEditor.VALUE.equals(evt.getPropertyName())) {
updateChoices();
} else if (IPropertyEditor.LIST_CONTENT.equals(evt.getPropertyName())) {
DefaultValueAdapter a = (DefaultValueAdapter)propertyEditor.getInput();
a.load();
String newValue = (String)valueProvider.getValue();
valueProvider.setValue(""); //$NON-NLS-1$
resetChoices();
valueProvider.setValue(newValue);
}
valueProvider.addValueChangeListener(this);
}
protected Control getListControl() {
return list;
}
protected Composite createListControl(Composite parent) {
if (list == null ||list.isDisposed()) {
ScrolledComposite sp = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
sp.setLayoutData(new GridData(GridData.FILL_BOTH));
list = sp;
sp.setLayout(new GridLayout());
Composite c = new Composite(sp, SWT.NONE);
buttonsParent = c;
c.setLayoutData(new GridData(GridData.FILL_BOTH));
sp.setContent(c);
c.setLayout(new GridLayout());
resetChoices();
} else {
checkParent(list, parent);
}
return list;
}
protected void updateChoices() {
Set<String> m = new HashSet<String>();
m.addAll(choicesMap.keySet());
String[] es = (String[])listContentProvider.getElements(null);
Set<String> ess = new HashSet<String>();
for (int i = 0; i < es.length; i++) {
ess.add(es[i]);
}
String value = (String)valueProvider.getValue();
if(value == null) value = ""; //$NON-NLS-1$
StringTokenizer st = new StringTokenizer(value, ",;"); //$NON-NLS-1$
String[] vs = new String[st.countTokens()];
Set<String> vss = new HashSet<String>();
for (int i = 0; i < vs.length; i++) {
vs[i] = st.nextToken();
vss.add(vs[i]);
}
for (int i = 0; i < vs.length; i++) {
Choice c = getChoice(vs[i], true);
c.setSelected(true);
c.setAllowed(ess.contains(vs[i]));
m.remove(vs[i]);
}
for (int i = 0; i < es.length; i++) {
Choice c = getChoice(es[i], true);
c.setSelected(vss.contains(es[i]));
c.setAllowed(true);
m.remove(es[i]);
}
String[] obs = (String[]) m.toArray(new String[0]);
for (int i = 0; i < obs.length; i++) {
Choice c = getChoice(obs[i], false);
if(c != null) {
c.dispose();
choicesMap.remove(obs[i]);
}
}
boolean isEmpty = (es.length == 0 && vs.length == 0);
updateEmpty(isEmpty);
}
Label empty = null;
void updateEmpty(boolean isEmpty) {
if(isEmpty == (empty != null && !empty.isDisposed())) return;
if(isEmpty) {
empty = new Label(buttonsParent, SWT.NONE);
empty.setText("Choice list is empty.");
} else {
if(empty != null) {
if(!empty.isDisposed()) empty.dispose();
empty = null;
}
}
}
public void resetChoices() {
updateChoices();
buttonsParent.pack();
buttonsParent.layout();
}
protected void fireValueChange() {
StringBuffer sb = new StringBuffer();
Choice[] cs= (Choice[])choicesArray.toArray(new Choice[0]);
for (int i = 0; i < cs.length; i++) {
if(!cs[i].selected) continue;
if(sb.length() > 0) sb.append(',');
sb.append(cs[i].name);
}
propertyChangeEnabled = false;
valueProvider.setValue(sb.toString());
propertyChangeEnabled = true;
}
public void setEnabled(boolean enabled){
// TODO;
super.setEnabled(enabled);
if (getListControl()!=null) {
getListControl().setEnabled(enabled);
}
}
public void setFocus() {
if(list != null && !list.isDisposed()) {
list.setFocus();
}
}
public void cut() {}
public void copy() {}
public void paste() {}
public void delete() {}
}