/*******************************************************************************
* Copyright (c) 2012 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.widgets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.emf.eef.runtime.EEFRuntimePlugin;
import org.eclipse.emf.eef.runtime.api.component.IPropertiesEditionComponent;
import org.eclipse.emf.eef.runtime.api.notify.IPropertiesEditionEvent;
import org.eclipse.emf.eef.runtime.api.notify.IPropertiesEditionListener;
import org.eclipse.emf.eef.runtime.context.impl.DomainPropertiesEditionContext;
import org.eclipse.emf.eef.runtime.context.impl.EObjectPropertiesEditionContext;
import org.eclipse.emf.eef.runtime.impl.utils.EEFUtils;
import org.eclipse.emf.eef.runtime.ui.utils.EditingUtils;
import org.eclipse.emf.eef.runtime.ui.viewers.PropertiesEditionContentProvider;
import org.eclipse.emf.eef.runtime.ui.viewers.PropertiesEditionViewer;
import org.eclipse.emf.eef.runtime.ui.widgets.ReferencesTable.ReferencesTableListener;
import org.eclipse.emf.eef.runtime.ui.widgets.referencestable.ReferencesTableContentProvider;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.forms.FormColors;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
/**
* @author <a href="mailto:goulwen.lefur@obeo.fr">Goulwen Le Fur</a>
*
*/
public class ContainmentPropertiesEditingViewer extends StructuredViewer {
/**
* Image for the add element button.
*/
final protected static Image NEW_ELEMENT_IMG = EEFRuntimePlugin.getImage(EEFRuntimePlugin.ICONS_16x16
+ "Add_16x16.gif"); //$NON-NLS-1$
/**
* Image for the delete element button.
*/
final protected static Image DELETE_ELEMENT_IMG = EEFRuntimePlugin.getImage(EEFRuntimePlugin.ICONS_16x16
+ "Delete_16x16.gif"); //$NON-NLS-1$
/**
* Image for the up button.
*/
final protected static Image UP_ELEMENT_IMG = EEFRuntimePlugin.getImage(EEFRuntimePlugin.ICONS_16x16
+ "ArrowUp_16x16.gif"); //$NON-NLS-1$
/**
* Image for the down button.
*/
final protected static Image DOWN_ELEMENT_IMG = EEFRuntimePlugin.getImage(EEFRuntimePlugin.ICONS_16x16
+ "ArrowDown_16x16.gif"); //$NON-NLS-1$
private Composite control;
private int kind;
private String mode;
private FormToolkit toolkit;
private IPropertiesEditionComponent component;
private Object viewerInput;
private List<ReferencesTableListener> listeners;
private boolean scrolledFormSearched;
private ScrolledForm scrolledForm;
private boolean refreshState;
private CLabel title;
private Button addButton;
private Label helpButton;
private FormColors colors;
/**
* Default container for SWT mode.
* @param parent parent composite
* @param kind kind of view
*/
public ContainmentPropertiesEditingViewer(Composite parent, int kind) {
super();
this.kind = kind;
this.listeners = new ArrayList<ReferencesTable.ReferencesTableListener>();
this.scrolledFormSearched = false;
control = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginLeft = -4;
((Composite) control).setLayout(layout);
title = new CLabel((Composite) control, SWT.NONE);
title.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
addButton = new Button((Composite) control, SWT.PUSH);
addButton.setImage(NEW_ELEMENT_IMG);
addButton.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
for (ReferencesTableListener listener : listeners) {
listener.handleAdd();
}
}
});
}
/**
* Constructor with toolkit for Form mode.
* @param parent parent composite
* @param kind kind of view
* @param toolkit toolkit to use
*/
public ContainmentPropertiesEditingViewer(Composite parent, int kind, FormToolkit toolkit) {
super();
this.kind = kind;
this.toolkit = toolkit;
this.listeners = new ArrayList<ReferencesTable.ReferencesTableListener>();
this.scrolledFormSearched = false;
control = toolkit.createComposite(parent, SWT.NONE);
GridLayout layout = new GridLayout(3, false);
layout.marginLeft = -4;
((Composite) control).setLayout(layout);
title = new CLabel((Composite) control, SWT.NONE);
title.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
EditingUtils.setEEFtype(title, "eef::ContainmentPropertiesEditingViewer::title");
addButton = toolkit.createButton((Composite) control, "", SWT.PUSH);
addButton.setImage(NEW_ELEMENT_IMG);
addButton.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
for (ReferencesTableListener listener : listeners) {
listener.handleAdd();
}
}
});
EditingUtils.setEEFtype(addButton, "eef::ContainmentPropertiesEditingViewer::addbutton");
Control createHelpButton = FormUtils.createHelpButton(toolkit, control, "", "");
if (createHelpButton instanceof Label) {
helpButton = (Label)createHelpButton;
GridData layoutData = new GridData();
layoutData.widthHint = 0;
createHelpButton.setLayoutData(layoutData);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object)
*/
@Override
protected Widget doFindInputItem(Object element) {
// TODO Auto-generated method stub
return null;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
*/
@Override
protected Widget doFindItem(Object element) {
// TODO Auto-generated method stub
return null;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt.widgets.Widget,
* java.lang.Object, boolean)
*/
@Override
protected void doUpdateItem(Widget item, Object element, boolean fullMap) {
// TODO Auto-generated method stub
}
/**
* @param listener to add.
*/
public void addListener(ReferencesTableListener listener) {
listeners.add(listener);
}
/**
* @param listener to remove.
*/
public void removeListener(ReferencesTableListener listener) {
listeners.remove(listener);
}
/**
* @param mode the mode to set
*/
public void setMode(String mode) {
this.mode = mode;
}
/**
* @return the component
*/
public IPropertiesEditionComponent getPropertiesEditingComponent() {
return component;
}
/**
* @param component the component to set
*/
public void setPropertiesEditingComponent(IPropertiesEditionComponent component) {
this.component = component;
}
/**
* @param text title of the widget.
*/
public void setText(String text) {
if (text != null) {
title.setText(text);
}
}
/**
* @param text help of the widget
*/
public void setHelpText(String text) {
if (text != null && !"".equals(text)) {
((GridData)helpButton.getLayoutData()).widthHint = 25;
helpButton.setToolTipText(text);
} else {
((GridData)helpButton.getLayoutData()).widthHint = 0;
}
}
/**
* @param id
*/
public void setID(Object id) {
EditingUtils.setID(control, id);
EditingUtils.setID(title, id);
EditingUtils.setID(addButton, id);
}
/**
* @param required whether the feature is required or not.
*/
public void setRequired(boolean required) {
if (required) {
title.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT));
} else {
title.setFont(JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT));
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object)
*/
@Override
protected void internalRefresh(Object element) {
clear();
this.viewerInput = element;
if (getContentProvider() != null) {
refreshState = true;
Object[] elements = getChildrenViewer(element);
for (Object object : elements) {
if (object instanceof EObject) {
Composite controlAsComposite = (Composite) control;
createChild((EObject) object, controlAsComposite);
}
}
refreshState = false;
}
if (control.getLayoutData() instanceof GridData) {
Composite parent = control.getParent();
while (parent != null) {
parent.layout(true);
if (parent instanceof ScrolledComposite){
parent = null;
} else {
parent = parent.getParent();
}
}
control.layout(true);
}
ScrolledForm owningScrolledForm = owningScrolledForm(control);
if (owningScrolledForm != null) {
owningScrolledForm.reflow(true);
}
}
/**
* @param element to process
* @return the children of the element.
*/
private Object[] getChildrenViewer(Object element) {
ReferencesTableContentProvider propertiesEditionProvider = (ReferencesTableContentProvider)getContentProvider();
Object[] elements = propertiesEditionProvider.getElements(element);
return elements;
}
/**
* @param elements
* @param searched
* @return
*/
private int indexOf(Object searched) {
Object[] elements = getChildrenViewer(viewerInput);
for (int i = 0; i < elements.length; i++) {
if (searched.equals(elements[i])) {
return i;
}
}
return -1;
}
/**
* Remove all the children elements of the viewer.
*/
protected void clear() {
for (Control child : control.getChildren()) {
if (child instanceof ChildComposite) {
child.dispose();
}
}
}
/**
* @param composite
* @return the ScrolledForm owning the current viewer <code>null</code> otherwise.
*/
private ScrolledForm gettingOwningScrolledForm(Composite composite) {
if (composite instanceof ScrolledForm) {
return (ScrolledForm) composite;
} else if (composite != null) {
return owningScrolledForm(composite.getParent());
} else {
return null;
}
}
/**
* Search the ScrolledForm owning the current viewer.
* @param composite current viewer.
* @return the ScrolledForm owning the current viewer <code>null</code> otherwise.
*/
private ScrolledForm owningScrolledForm(Composite composite) {
if (!scrolledFormSearched) {
scrolledForm = gettingOwningScrolledForm(composite);
scrolledFormSearched = true;
}
return scrolledForm;
}
/**
* Creates a ChildComposite for the given EObject.
* @param object EObject to display.
* @param parent the viewer control.
*/
private void createChild(EObject object, Composite parent) {
ChildComposite child = new ChildComposite(parent, SWT.NONE);
child.setInput(object);
}
private String labelTitle(Object object) {
IItemLabelProvider labelProvider = (IItemLabelProvider) adapterFactory().adapt(object, IItemLabelProvider.class);
String text = null;
if (labelProvider != null)
text = labelProvider.getText(object);
else
text = object.toString();
return text;
}
private Image labelImage(Object object) {
return new AdapterFactoryLabelProvider(adapterFactory()).getImage(object);
}
private AdapterFactory adapterFactory() {
return component.getEditingContext().getAdapterFactory();
}
protected IContentProvider getInternContentProvider() {
if (component != null && component.getEditingContext() != null) {
if (mode == IPropertiesEditionComponent.LIVE_MODE) {
return new PropertiesEditionContentProvider(adapterFactory(), mode, EEFUtils.getEditingDomain(component.getEditingContext()));
} else {
try {
return new PropertiesEditionContentProvider(adapterFactory(), mode);
} catch (InstantiationException e) {
throw new IllegalStateException("An EditingDomain must be defined for live mode.");
}
}
} else {
throw new IllegalStateException("A PropertiesEditingComponent must be defined for this widget.");
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object)
*/
@Override
public void reveal(Object element) {}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget()
*/
@Override
protected List<?> getSelectionFromWidget() {
return Collections.EMPTY_LIST;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List,
* boolean)
*/
@Override
protected void setSelectionToWidget(List l, boolean reveal) {}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.Viewer#getControl()
*/
@Override
public Control getControl() {
return control;
}
private Color getColor(String key) {
if (colors == null) {
colors = new FormColors(control.getDisplay());
}
return colors.getColor(key);
}
private class ChildComposite extends Composite {
private CLabel objectTitle;
private PropertiesEditionViewer viewer;
private EObject input;
private IPropertiesEditionListener listener;
public ChildComposite(Composite parent, int style) {
super(parent, style);
GridData compositeData = new GridData(GridData.FILL_BOTH);
compositeData.horizontalSpan= 3;
setLayoutData(compositeData);
GridLayout layout = new GridLayout(4, false);
layout.marginWidth = 5;
layout.verticalSpacing = 5;
setLayout(layout);
Button removeButton;
Button upButton;
Button downButton;
if (kind == 1) {
setBackground(getColor(IFormColors.TB_BG));
objectTitle = new CLabel(this, SWT.NONE);
removeButton = toolkit.createButton(this, "", SWT.PUSH);
upButton = toolkit.createButton(this, "", SWT.PUSH);
downButton = toolkit.createButton(this, "", SWT.PUSH);
} else {
setBackground(JFaceColors.getBannerBackground(getDisplay()));
objectTitle = new CLabel(this, SWT.NONE);
objectTitle.setBackground(JFaceColors.getBannerBackground(getDisplay()));
removeButton = new Button(this, SWT.PUSH);
upButton = new Button(this, SWT.PUSH);
downButton = new Button(this, SWT.PUSH);
}
EditingUtils.setEEFtype(objectTitle, "eef::ContainmentPropertiesEditingViewer::childtitle");
EditingUtils.setEEFtype(removeButton, "eef::ContainmentPropertiesEditingViewer::removechildbutton");
EditingUtils.setEEFtype(upButton, "eef::ContainmentPropertiesEditingViewer::upchildbutton");
EditingUtils.setEEFtype(downButton, "eef::ContainmentPropertiesEditingViewer::downchildbutton");
GridData labelData = new GridData(GridData.FILL_HORIZONTAL);
objectTitle.setLayoutData(labelData);
removeButton.setImage(DELETE_ELEMENT_IMG);
removeButton.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected(SelectionEvent e) {
for (ReferencesTableListener listener : listeners) {
listener.handleRemove(input);
}
}
});
upButton.setImage(UP_ELEMENT_IMG);
upButton.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected(SelectionEvent e) {
for (ReferencesTableListener listener : listeners) {
int indexOf = indexOf(input);
if (indexOf > 0) {
listener.handleMove(input, indexOf, indexOf - 1);
}
}
}
});
downButton.setImage(DOWN_ELEMENT_IMG);
downButton.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected(SelectionEvent e) {
for (ReferencesTableListener listener : listeners) {
int indexOf = indexOf(input);
if (indexOf > -1 && indexOf < (getChildrenViewer(viewerInput).length - 1)) {
listener.handleMove(input, indexOf, indexOf + 1);
}
}
}
});
viewer = new PropertiesEditionViewer(this, null, SWT.NONE, kind);
if (toolkit != null) {
viewer.setToolkit(toolkit);
}
viewer.setContentProvider(getInternContentProvider());
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.horizontalSpan = 4;
viewer.getControl().setLayoutData(data);
}
/**
* Defines input of the viewer.
* @param object the viewer input
*/
public void setInput(EObject object) {
this.input = object;
if (component != null && component.getEditingContext() != null) {
if (mode == IPropertiesEditionComponent.LIVE_MODE) {
viewer.setInput(new DomainPropertiesEditionContext(component.getEditingContext(), component, EEFUtils.getEditingDomain(component.getEditingContext()), adapterFactory(), (EObject) object));
} else {
viewer.setInput(new EObjectPropertiesEditionContext(component.getEditingContext(), component, (EObject) object, adapterFactory()));
}
} else {
viewer.setInput(object);
}
listener = new IPropertiesEditionListener() {
public void firePropertiesChanged(IPropertiesEditionEvent event) {
refreshTitle(input);
}
};
((PropertiesEditionContentProvider)viewer.getContentProvider()).addPropertiesListener(listener);
refreshTitle(object);
}
/**
* {@inheritDoc}
* @see org.eclipse.swt.widgets.Widget#dispose()
*/
@Override
public void dispose() {
if (listener != null) {
((PropertiesEditionContentProvider)viewer.getContentProvider()).removePropertiesListener(listener);
}
super.dispose();
}
/**
* @return input of the viewer.
*/
public EObject getInput() {
return input;
}
public void refreshTitle(Object object) {
objectTitle.setText(labelTitle(object));
Image labelImage = labelImage(object);
if (labelImage != null) {
objectTitle.setImage(labelImage);
}
}
}
}