blob: 933c65740edae5a706976c2cf44e8c1636d22e47 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2012-2015 itemis and others.
* 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:
* itemis - Initial API and implementation
* itemis - [434230] ParseException when trying to sort BasicXViewerSection for columns displaying Date-typed EAttributes
* itemis - [436313] Enable BasicXViewerSection also to be used for EReference-based properties
* itemis - [436429] Enable custom layout data to be passed to BasicXViewerSection
* itemis - [460260] Expanded paths are collapsed on resource reload
*
* </copyright>
*/
package org.eclipse.sphinx.emf.editors.forms.nebula.sections;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.nebula.widgets.xviewer.XViewer;
import org.eclipse.nebula.widgets.xviewer.XViewerFactory;
import org.eclipse.nebula.widgets.xviewer.XViewerSorter;
import org.eclipse.nebula.widgets.xviewer.XViewerTextFilter;
import org.eclipse.nebula.widgets.xviewer.core.model.SortDataType;
import org.eclipse.nebula.widgets.xviewer.core.model.XViewerAlign;
import org.eclipse.nebula.widgets.xviewer.core.model.XViewerColumn;
import org.eclipse.nebula.widgets.xviewer.edit.XViewerEditAdapter;
import org.eclipse.sphinx.emf.editors.forms.BasicTransactionalFormEditor;
import org.eclipse.sphinx.emf.editors.forms.nebula.internal.Activator;
import org.eclipse.sphinx.emf.editors.forms.nebula.providers.BasicModelXViewerLabelProvider;
import org.eclipse.sphinx.emf.editors.forms.pages.AbstractFormPage;
import org.eclipse.sphinx.emf.editors.forms.sections.AbstractViewerFormSection;
import org.eclipse.sphinx.platform.ui.util.SelectionUtil;
import org.eclipse.sphinx.platform.util.PlatformLogUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.Section;
// TODO Provide this as a field rather than a section
public class BasicXViewerSection extends AbstractViewerFormSection {
protected EObject exampleValue;
protected XViewerFactory xViewerFactory;
protected GridData layoutData;
public BasicXViewerSection(AbstractFormPage formPage, Object sectionInput, EObject exampleValue) {
this(formPage, sectionInput, exampleValue, Section.DESCRIPTION | ExpandableComposite.TITLE_BAR);
}
public BasicXViewerSection(AbstractFormPage formPage, Object sectionInput, EObject exampleValue, int style) {
super(formPage, sectionInput, style);
Assert.isNotNull(exampleValue);
this.exampleValue = exampleValue;
}
public BasicXViewerSection(AbstractFormPage formPage, Object sectionInput, XViewerFactory xViewerFactory) {
this(formPage, sectionInput, xViewerFactory, Section.DESCRIPTION | ExpandableComposite.TITLE_BAR);
}
public BasicXViewerSection(AbstractFormPage formPage, Object sectionInput, XViewerFactory xViewerFactory, int style) {
super(formPage, sectionInput, style);
Assert.isNotNull(xViewerFactory);
this.xViewerFactory = xViewerFactory;
}
public GridData getLayoutData() {
if (layoutData == null) {
layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
}
return layoutData;
}
public void setLayoutData(GridData layoutData) {
this.layoutData = layoutData;
}
@Override
protected int getNumberOfColumns() {
return 1;
}
@Override
protected void createSectionClientContent(final IManagedForm managedForm, final SectionPart sectionPart, Composite sectionClient) {
Assert.isNotNull(managedForm);
Assert.isNotNull(sectionPart);
Assert.isNotNull(sectionClient);
// Create xViewer factory and define table columns if necessary
if (xViewerFactory == null) {
xViewerFactory = createXViewerFactory();
registerColumns(xViewerFactory);
}
// Create table viewer
XViewer xViewer = createXViewer(sectionClient, xViewerFactory);
xViewer.getTree().setLayoutData(getLayoutData());
// Make table viewer this section's viewer
/*
* !! Important Note !! This must be done before initializing the table viewer's content/label providers because
* the latter are likely to require the table viewer and may want to retrieve it by calling #getViewer() (see
* #createLabelProvider() for details).
*/
setViewer(xViewer);
// Provide table content
xViewer.setContentProvider(createContentProvider());
xViewer.setLabelProvider(createLabelProvider());
// Set table input
xViewer.setInput(sectionInput);
}
protected XViewerFactory createXViewerFactory() {
XViewerFactory xViewerFactory = new XViewerFactory(exampleValue.eClass().getName()) {
@Override
public boolean isAdmin() {
return true;
}
@Override
public XViewerSorter createNewXSorter(XViewer xViewer) {
return new XViewerSorter(xViewer) {
@Override
public int getCompareForDate(String date1, Object obj1, String date2, Object obj2) {
if (date1 != null && obj1 == null && date2 != null && obj2 == null) {
Date date1Date = null;
try {
date1Date = getDateFormat().parse(date1);
} catch (ParseException ex) {
PlatformLogUtil.logAsError(Activator.getPlugin(), ex);
return 0;
}
Date date2Date = null;
try {
date2Date = getDateFormat().parse(date2);
} catch (ParseException ex) {
PlatformLogUtil.logAsError(Activator.getPlugin(), ex);
return 0;
}
return getCompareForDate(date1Date, date2Date);
} else {
return super.getCompareForDate(date1, obj1, date2, obj2);
}
}
};
}
};
return xViewerFactory;
}
/**
* Returns the {@link DateFormat date format} to be used by this viewer's {@link XViewerSorter sorter} to sort
* {@link Date}-typed values. Must be the same date format as that being used by this viewer's
* {@link #createLabelProvider() label provider} to render Date-typed values.
* <p>
* This implementation returns an <code>new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US)</code>
* instance by default. It matches the format used by EMF Edit to render Date-typed {@link EAttribute attribute}
* values (see {@link PropertyValueWrapper#getText(Object), AdapterFactoryItemDelegator#getText(Object) and
* Date#toString() for details}. Clients may override and return {@link DateFormat} .getXxxInstance() or new
* {@link SimpleDateFormat} ("xxx") as appropriate.
* </p>
*
* @return The date format to be used for sorting Date-typed values displayed by this viewer.
* @see DateFormat
* @see SimpleDateFormat
*/
protected DateFormat getDateFormat() {
return new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US); //$NON-NLS-1$
}
protected XViewer createXViewer(Composite sectionClient, XViewerFactory xViewerFactory) {
final BasicTransactionalFormEditor formEditor = formPage.getTransactionalFormEditor();
XViewer xViewer = new XViewer(sectionClient, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER, xViewerFactory) {
@Override
public void setSelection(ISelection selection) {
selection = !SelectionUtil.getStructuredSelection(selection).isEmpty() ? selection : formEditor.getDefaultSelection();
super.setSelection(selection);
}
@Override
public XViewerTextFilter getXViewerTextFilter() {
return createXViewerTextFilter(this);
}
};
// Add editing support
XViewerEditAdapter xViewerEditAdapter = createXViewerEditAdapter();
if (xViewerEditAdapter != null) {
xViewer.setXViewerEditAdapter(xViewerEditAdapter);
}
return xViewer;
}
/**
* Override to provide extended filter capabilities.
*/
protected XViewerTextFilter createXViewerTextFilter(XViewer xViewer) {
return new XViewerTextFilter(xViewer);
}
/**
* Returns null by default. Sub classes can provide a concrete implementation to handle editing support.
*/
protected XViewerEditAdapter createXViewerEditAdapter() {
return null;
}
protected void registerColumns(XViewerFactory xViewerFactory) {
List<IItemPropertyDescriptor> propertyDescriptors = formPage.getItemDelegator().getPropertyDescriptors(exampleValue);
for (IItemPropertyDescriptor propertyDescriptor : propertyDescriptors) {
xViewerFactory.registerColumns(new XViewerColumn(propertyDescriptor.getId(exampleValue).toString(),
propertyDescriptor.getDisplayName(exampleValue), 100, XViewerAlign.Left, true, getSortDataType(propertyDescriptor, exampleValue),
false, propertyDescriptor.getDescription(exampleValue)));
}
}
protected SortDataType getSortDataType(IItemPropertyDescriptor propertyDescriptor, Object object) {
Assert.isNotNull(propertyDescriptor);
Assert.isNotNull(object);
EClassifier propertyType = ((EStructuralFeature) propertyDescriptor.getFeature(object)).getEType();
if (propertyType == EcorePackage.eINSTANCE.getEDate()) {
return SortDataType.Date;
} else if (propertyType == EcorePackage.eINSTANCE.getEFloat() || propertyType == EcorePackage.eINSTANCE.getEDouble()) {
return SortDataType.Float;
} else if (propertyType == EcorePackage.eINSTANCE.getEBoolean()) {
return SortDataType.Check;
} else if (propertyType == EcorePackage.eINSTANCE.getEInt()) {
return SortDataType.Integer;
} else if (propertyDescriptor.isMultiLine(object)) {
return SortDataType.String_MultiLine;
}
return SortDataType.String;
}
@Override
protected IBaseLabelProvider createLabelProvider() {
return new BasicModelXViewerLabelProvider((XViewer) getViewer(), formPage.getItemDelegator());
}
}