/*
ListPropertyEditor.java
(c) 2010-2012 Edward Swartz
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
*/
package org.ejs.gui.properties;
import java.util.List;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
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.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.ejs.gui.common.FontUtils;
import ejs.base.properties.IClassPropertyFactory;
import ejs.base.properties.ListFieldProperty;
/**
* @author ejs
*
*/
public class ListPropertyEditor implements IPropertyEditor {
private final ListFieldProperty property;
private ListViewer viewer;
protected Object currentElement;
private Composite editorHolder;
/**
* @param listFieldProperty
*/
public ListPropertyEditor(ListFieldProperty property) {
this.property = property;
}
/* (non-Javadoc)
*
*/
public IPropertyEditorControl createEditor(Composite parent) {
final Composite composite = new Composite(parent, SWT.BORDER);
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);
// first column: the items
createList(composite);
// second column: the editor for the selected item
editorHolder = new Composite(composite, SWT.NONE);
GridLayoutFactory.fillDefaults().applyTo(editorHolder);
parent.getShell().addShellListener(new ShellAdapter() {
@Override
public void shellActivated(ShellEvent e) {
updateEditor();
((Shell)e.widget).removeShellListener(this);
}
});
return new IPropertyEditorControl() {
@Override
public Control getControl() {
return composite;
}
@Override
public void reset() {
System.err.println(getClass() + " : TODO");
}
};
}
/**
* @param composite
*/
private void createList(Composite parent) {
Composite composite = new Composite(parent, SWT.BORDER_DOT);
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);
//GridDataFactory.fillDefaults().grab(true, true).minSize(100,-1).applyTo(composite);
GridDataFactory.fillDefaults().grab(true, true).minSize(50,-1).applyTo(composite);
viewer = new ListViewer(composite);
GridDataFactory.fillDefaults().grab(true,true).span(1, 4).applyTo(viewer.getControl());
//GridDataFactory.swtDefaults().span(1, 4).applyTo(viewer.getControl());
if (property.getElementClassFactory() != null) {
FontDescriptor desc = FontUtils.getFontDescriptor(JFaceResources.getTextFont());
desc = desc.setHeight(8);
final Font smallFont = desc.createFont(parent.getShell().getDisplay());
parent.addDisposeListener(new DisposeListener() {
/* (non-Javadoc)
* @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
*/
public void widgetDisposed(DisposeEvent e) {
smallFont.dispose();
}
});
final Button addButton = new Button(composite, SWT.PUSH);
addButton.setFont(smallFont);
GridDataFactory.swtDefaults().minSize(50, -1).applyTo(addButton);
addButton.setText("+");
addButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
addNewElement(addButton, property.getElementClassFactory());
}
});
final Button removeButton = new Button(composite, SWT.PUSH);
removeButton.setFont(smallFont);
GridDataFactory.swtDefaults().minSize(50, -1).applyTo(removeButton);
removeButton.setText("-");
removeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (currentElement != null) {
property.getList().remove(currentElement);
viewer.remove(currentElement);
updateList();
}
}
});
final Button upButton = new Button(composite, SWT.PUSH);
upButton.setFont(smallFont);
GridDataFactory.swtDefaults().minSize(50, -1).applyTo(upButton);
upButton.setText("↑");
upButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (currentElement != null) {
List<Object> list = property.getList();
int index = list.indexOf(currentElement);
if (index > 0) {
Object el = list.remove(index - 1);
list.add(index, el);
}
viewer.refresh();
updateList();
}
}
});
final Button downButton = new Button(composite, SWT.PUSH);
downButton.setFont(smallFont);
GridDataFactory.swtDefaults().minSize(50, -1).applyTo(downButton);
downButton.setText("↓");
downButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (currentElement != null) {
List<Object> list = property.getList();
int index = list.indexOf(currentElement);
if (index < list.size()) {
Object el = list.remove(index + 1);
list.add(index, el);
}
viewer.refresh();
updateList();
}
}
});
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
Object el = ((IStructuredSelection) event.getSelection()).getFirstElement();
removeButton.setEnabled(el != null);
}
});
}
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
Object el = ((IStructuredSelection) event.getSelection()).getFirstElement();
currentElement = el;
updateEditor();
}
});
viewer.setLabelProvider(new LabelProvider() {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
*/
@Override
public String getText(Object element) {
if (element instanceof IPropertyEditorProvider)
return ((IPropertyEditorProvider)element).getLabel(property);
return super.getText(element);
}
});
viewer.setContentProvider(new ArrayContentProvider());
List<Object> list = property.getList();
viewer.setInput(list);
if (list != null && list.size() > 0) {
Object el = list.get(0);
viewer.setSelection(new StructuredSelection(el));
}
}
/**
*
*/
protected void updateList() {
//if (property instanceof IPropertyProvider)
// ((IPropertyProvider) property).updateFromPropertyChange();
property.firePropertyChange();
}
/**
*
*/
protected void updateEditor() {
if (editorHolder != null) {
if (editorHolder.isDisposed())
return;
for (Control kid : editorHolder.getChildren())
kid.dispose();
if (currentElement != null) {
if (currentElement instanceof IPropertyEditorProvider) {
IPropertyEditorProvider pep = (IPropertyEditorProvider) currentElement;
IPropertyEditor editor = pep.createEditor(property);
if (editor != null) {
IPropertyEditorControl control = editor.createEditor(editorHolder);
GridDataFactory.fillDefaults().grab(true, true).applyTo(control.getControl());
// TODO: save editor control somewhere
editorHolder.getShell().layout(true, true);
//editorHolder.getShell().pack();
}
}
}
}
}
/**
* @param factory
*/
protected void addNewElement(final Control parent, final IClassPropertyFactory factory) {
String[] ids = factory.getIds();
Menu menu = new Menu(parent);
for (String id : ids) {
final String theId = id;
MenuItem item = new MenuItem(menu, SWT.PUSH);
item.setText(id);
item.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Object value = factory.create(theId);
property.getList().add(value);
viewer.add(value);
viewer.setSelection(new StructuredSelection(value));
updateList();
}
});
}
menu.setVisible(true);
}
}