package de.urszeidler.shr5.ecp.editor.pages;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
import org.eclipse.core.databinding.property.value.IValueProperty;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.emf.databinding.EMFUpdateValueStrategy;
import org.eclipse.emf.databinding.edit.EMFEditObservables;
import org.eclipse.emf.databinding.edit.EMFEditProperties;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EValidator.SubstitutionLabelProvider;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.nebula.jface.cdatetime.CDateTimeObservableValue;
import org.eclipse.nebula.widgets.cdatetime.CDT;
import org.eclipse.nebula.widgets.cdatetime.CDateTime;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.editor.FormPage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.wb.swt.ResourceManager;
import com.google.common.base.Joiner;
import com.google.common.collect.FluentIterable;
import de.urszeidler.eclipse.shr5.Shr5Package;
import de.urszeidler.eclipse.shr5.util.AdapterFactoryUtil;
import de.urszeidler.emf.commons.ui.util.EmfFormBuilder;
import de.urszeidler.emf.commons.ui.util.EmfFormBuilder.ReferenceManager;
import de.urszeidler.emf.commons.ui.util.FormbuilderEntry;
import de.urszeidler.emf.commons.ui.util.FormbuilderEntry.EntryFactory;
import de.urszeidler.shr5.ecp.Activator;
import de.urszeidler.shr5.ecp.editor.actions.DuplicateObjectAction;
import de.urszeidler.shr5.ecp.editor.actions.ExportObjectAction;
import de.urszeidler.shr5.ecp.editor.widgets.TreeTableWidget;
import de.urszeidler.shr5.ecp.preferences.PreferenceConstants;
import de.urszeidler.shr5.ecp.util.DefaultLabelProvider;
import de.urszeidler.shr5.ecp.util.ShadowrunEditingTools;
import de.urszeidler.shr5.ecp.util.ValidationLabelProvider;
/**
* This is a basic generic page to display eObjects in an form with an emfformbilder.
*/
public abstract class AbstractShr5Page<A extends EObject> extends FormPage implements IDoubleClickListener, ISelectionChangedListener {
public final class LabelEntry implements EntryFactory {
@Override
public void createEntry(Composite container, FormbuilderEntry entry, EObject object, DataBindingContext dbc, EmfFormBuilder emfFormBuilder) {
emfFormBuilder.createConfiguredLable(container, entry, object);
Label label = emfFormBuilder.createLabel(container);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
IObservableValue widgetObserver = WidgetProperties.text().observe(label);
IObservableValue objectObserver = EMFEditObservables.observeValue(getEditingDomain(), object, entry.getFeature());
entry.setUiObservable(widgetObserver);
entry.setObservable(objectObserver);
UpdateValueStrategy strategy = new EMFUpdateValueStrategy();
dbc.bindValue(widgetObserver, objectObserver, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), strategy);
}
}
public final class LabelEnumEntry implements EntryFactory {
@Override
public void createEntry(Composite container, FormbuilderEntry entry, EObject object, DataBindingContext dbc, EmfFormBuilder emfFormBuilder) {
emfFormBuilder.createConfiguredLable(container, entry, object);
final LabelProvider provider = emfFormBuilder.createLabelProvider(entry, object);
Label label = emfFormBuilder.createLabel(container);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
IObservableValue widgetObserver = WidgetProperties.text().observe(label);
IObservableValue objectObserver = EMFEditObservables.observeValue(getEditingDomain(), object, entry.getFeature());
entry.setUiObservable(widgetObserver);
entry.setObservable(objectObserver);
UpdateValueStrategy strategy = new EMFUpdateValueStrategy();
strategy.setConverter(new Converter(EObject.class, String.class) {
@Override
public Object convert(Object fromObject) {
return provider.getText(fromObject);
}
});
dbc.bindValue(widgetObserver, objectObserver, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), strategy);
}
}
public final class LabelMoneyEntry implements EntryFactory {
@Override
public void createEntry(Composite container, FormbuilderEntry entry, EObject object, DataBindingContext dbc, EmfFormBuilder emfFormBuilder) {
emfFormBuilder.createConfiguredLable(container, entry, object);
Label label = emfFormBuilder.createLabel(container);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
IObservableValue widgetObserver = WidgetProperties.text().observe(label);
IObservableValue objectObserver = EMFEditObservables.observeValue(getEditingDomain(), object, entry.getFeature());
entry.setUiObservable(widgetObserver);
entry.setObservable(objectObserver);
UpdateValueStrategy strategy = new EMFUpdateValueStrategy();
strategy.setConverter(new Converter(EObject.class, String.class) {
@Override
public Object convert(Object fromObject) {
return String.format("%,.0f %s", fromObject, store.getString(PreferenceConstants.CURRENCY_SYMBOL));
}
});
dbc.bindValue(widgetObserver, objectObserver, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), strategy);
}
}
public final class ReadOnlyLinkEntry implements EntryFactory {
private final FormToolkit formToolkit;
public ReadOnlyLinkEntry(FormToolkit formToolkit) {
super();
this.formToolkit = formToolkit;
}
@Override
public void createEntry(Composite container, FormbuilderEntry entry, EObject object, DataBindingContext dbc, EmfFormBuilder emfFormBuilder) {
createLinkRO(formToolkit, container, entry, object, emfFormBuilder);
}
};
/**
* A emf form factory to create and bind a date widget.
*/
public class DateEntryFactory implements EntryFactory {
private final FormToolkit formToolkit;
public DateEntryFactory(FormToolkit formToolkit) {
super();
this.formToolkit = formToolkit;
}
@Override
public void createEntry(Composite container, FormbuilderEntry entry, EObject object, DataBindingContext dbc, EmfFormBuilder emfFormBuilder) {
Label label = emfFormBuilder.createConfiguredLable(container, entry, object);
CDateTime dateTime = new CDateTime(container, CDT.DROP_DOWN | CDT.DATE_SHORT);
dateTime.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
formToolkit.adapt(dateTime);
formToolkit.paintBordersFor(dateTime);
emfFormBuilder.layoutRow(entry, label, dateTime);
IObservableValue widgetObserver = new CDateTimeObservableValue(dateTime);
IObservableValue objectObserver = EMFEditObservables.observeValue(getEditingDomain(), object, entry.getFeature());
// entry.setUiObservable(widgetObserver);
entry.setObservable(objectObserver);
dbc.bindValue(widgetObserver, objectObserver, new EMFUpdateValueStrategy(), new EMFUpdateValueStrategy());
}
}
protected ReferenceManager mananger;
protected EmfFormBuilder emfFormBuilder;
protected ILabelProvider labelprovider = new DefaultLabelProvider();
protected IPreferenceStore store;
protected LabelEntry labelEntryFactory = new LabelEntry();
public AbstractShr5Page(String id, String title) {
super(id, title);
}
public AbstractShr5Page(FormEditor editor, String id, String title) {
super(editor, id, title);
}
/**
* This is the main constructor usable for the editor.
*
* @param editor
* @param id
* @param title
* @param manager the mananger for refrenece features
*/
public AbstractShr5Page(FormEditor editor, String id, String title, ReferenceManager manager) {
this(editor, id, title);
this.mananger = manager;
store = Activator.getDefault().getPreferenceStore();
}
@Override
public void dispose() {
if (emfFormBuilder != null)
emfFormBuilder.dispose();
super.dispose();
}
/**
* Add some basic actions to the toolbar.
*
* @param toolbarManager
* @param object
* @param shell
*/
protected void addFillToolbar(final IToolBarManager toolbarManager, final EObject object, Shell shell) {
toolbarManager.add(new ExportObjectAction(shell, object));
toolbarManager.add(new DuplicateObjectAction(object));
}
/**
* Adds a validation button when there are error and displays them as tooltip.
*
* @param toolbarManager
* @param object
*/
protected void addValidationResult(final IToolBarManager toolbarManager, final EObject object) {
Diagnostic validate = Diagnostician.INSTANCE.validate(object, createValidationContext());
if (!validate.getChildren().isEmpty()) {
final String message = Joiner.on("\n").join(
FluentIterable.from(validate.getChildren()).transform(ShadowrunEditingTools.diagnosticToStringTransformer()));
final ImageDescriptor pluginImageDescriptor = ResourceManager.getPluginImageDescriptor("de.urszeidler.shr5.ecp", "images/error.gif");
Action action = new Action() {
@Override
public ImageDescriptor getImageDescriptor() {
return pluginImageDescriptor;
}
@Override
public void run() {
Diagnostic validate = Diagnostician.INSTANCE.validate(object, createValidationContext());
if (!validate.getChildren().isEmpty()) {
final String message = Joiner.on("\n").join(
FluentIterable.from(validate.getChildren()).transform(ShadowrunEditingTools.diagnosticToStringTransformer()));
this.setToolTipText(message);
} else {
toolbarManager.remove("validation");
}
}
};
action.setToolTipText(message);
action.setId("validation");
toolbarManager.add(action);
}
}
/**
* Simple Factory method to create the formbuilder.
*
* @param managedForm
*/
protected void createFormBuilder(IManagedForm managedForm) {
emfFormBuilder = createConfiguredFormBuilder(managedForm);
}
/**
* @param managedForm
* @return
*/
protected EmfFormBuilder createConfiguredFormBuilder(IManagedForm managedForm) {
EmfFormBuilder emfFormBuilder = new EmfFormBuilder(managedForm.getToolkit(), AdapterFactoryUtil.getInstance().getItemDelegator(),
AdapterFactoryUtil.getInstance().getLabelProvider(), getEditingDomain());
emfFormBuilder.setManager(mananger);
emfFormBuilder.setNullString(Messages.EmfFormbuilder_non_selected);
// emfFormBuilder.setBorderStyle(SWT.NONE);
emfFormBuilder.setDblListner(this);
emfFormBuilder.setSelectionChangeListener(this);
return emfFormBuilder;
}
/**
* Open a new editor for the object in the selection.
*/
@Override
public void doubleClick(DoubleClickEvent event) {
ISelection selection = event.getSelection();
ShadowrunEditingTools.openEditorForFirstSelection(selection);
}
@Override
public void selectionChanged(SelectionChangedEvent event) {
getSite().getSelectionProvider().setSelection(event.getSelection());
}
protected abstract EditingDomain getEditingDomain();
// protected abstract A getObject();
/**
* @param grpWert
*/
protected void addWertFeatures(Composite grpWert) {
emfFormBuilder.addTextEntry(Shr5Package.Literals.GELD_WERT__WERT_VALUE, grpWert);
emfFormBuilder.addTextEntry(Shr5Package.Literals.GELD_WERT__VERFUEGBARKEIT, grpWert);
emfFormBuilder.addTextEntry(Shr5Package.Literals.GELD_WERT__WERT, grpWert, new LabelMoneyEntry());
}
/**
* @param grpQuelle
*/
protected void addSourceFeature(Group grpQuelle) {
emfFormBuilder.addTextEntry(Shr5Package.Literals.QUELLE__SRC_BOOK, grpQuelle);
emfFormBuilder.addTextEntry(Shr5Package.Literals.QUELLE__PAGE, grpQuelle);
}
/**
* Creates the validation context.
*
* @return
*/
protected Map<Object, Object> createValidationContext() {
Map<Object, Object> context = new HashMap<Object, Object>();
context.put(SubstitutionLabelProvider.class, new ValidationLabelProvider());
return context;
}
protected GridData createControllGridData(int height) {
GridData controlGridData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 3);
controlGridData.heightHint = height;
return controlGridData;
}
protected TreeTableWidget createTreeTableWidget(Composite composite, EReference ref,IManagedForm managedForm, EObject object){
TreeTableWidget treeTableWidget = new TreeTableWidget(composite, labelprovider.getText(ref), SWT.NONE, object, ref, managedForm.getToolkit(), mananger, getEditingDomain(),
this,this);
GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
layoutData.heightHint = 300;
treeTableWidget.setLayoutData(layoutData);
managedForm.getToolkit().adapt(treeTableWidget);
managedForm.getToolkit().paintBordersFor(treeTableWidget);
return treeTableWidget;
}
/**
* @param toolkit
* @param container
* @param e
* @param object
* @param emfFormBuilder
*/
private void createLinkRO(final FormToolkit toolkit, Composite container, FormbuilderEntry e, EObject object, EmfFormBuilder emfFormBuilder) {
emfFormBuilder.createConfiguredLable(container, e, object);
final ImageHyperlink srcLink = toolkit.createImageHyperlink(container, SWT.NONE);
toolkit.paintBordersFor(srcLink);
srcLink.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 2, 1));
Object value = object.eGet(e.getFeature());
final String nullString = Messages.EmfFormbuilder_non_selected;
String element = value == null ? nullString : labelprovider.getText(value);
srcLink.setText(element);
srcLink.setImage(labelprovider.getImage(value));
// ISWTObservableValue uiObs = SWTObservables.observeText(srcLink);
IValueProperty property = null;
if (getEditingDomain() != null)
property = EMFEditProperties.value(getEditingDomain(), e.getFeature());
else
property = EMFProperties.value(e.getFeature());
final IObservableValue mObs = property.observe(object);
e.setObservable(mObs);
mObs.addValueChangeListener(new IValueChangeListener() {
@Override
public void handleValueChange(ValueChangeEvent event) {
Object value = event.getObservableValue().getValue();
srcLink.setText(value == null ? nullString : labelprovider.getText(value));
srcLink.setImage(labelprovider.getImage(value));
}
});
}
/**
* Creates the filter widget for a treeviewer.
* @param managedForm
* @param grpGegenstand
* @param createTreeTableWidget
*/
protected void createFilterWidgets(IManagedForm managedForm, Composite grpGegenstand, final TreeTableWidget createTreeTableWidget) {
Label lblFilter = new Label(grpGegenstand, SWT.NONE);
lblFilter.setToolTipText("Filter the view (* is a wildcard for many any and ? one any character)");
lblFilter.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
managedForm.getToolkit().adapt(lblFilter, true, true);
lblFilter.setText(Messages.VariousObjectsPage_lblFilter_text);
final PatternFilter filter = new PatternFilter() {
@Override
protected boolean isParentMatch(Viewer viewer, Object element) {
return viewer instanceof AbstractTreeViewer && super.isParentMatch(viewer, element);
}
};
final Text txtFiltertext = new Text(grpGegenstand, SWT.BORDER);
txtFiltertext.setMessage(Messages.VariousObjectsPage_txtFiltertext_text);
txtFiltertext.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
txtFiltertext.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
createTreeTableWidget.getTreeViewer().expandAll();
filter.setPattern(((Text)e.widget).getText());
createTreeTableWidget.getTreeViewer().refresh();
}
});
managedForm.getToolkit().adapt(txtFiltertext, true, true);
Button button = managedForm.getToolkit().createButton(grpGegenstand, "", SWT.PUSH);
button.setImage(ResourceManager.getPluginImage("de.urszeidler.shr5.ecp", "images/clear.gif"));
button.setToolTipText("Clear the filter");
button.addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent e) {
txtFiltertext.setText("");
}
});
createTreeTableWidget.getTreeViewer().addFilter(filter);
}
}