/**
* Copyright (c) 2009 Bestsolution.at and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Tom Schindl<tom.schindl@bestsolution.at> - Initial API and implementation
*/
package org.eclipse.emf.example.databinding.project.ui.rcp.views;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.databinding.AggregateValidationStatus;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.ObservablesManager;
import org.eclipse.core.databinding.ValidationStatusProvider;
import org.eclipse.core.databinding.observable.value.ComputedValue;
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.runtime.IStatus;
import org.eclipse.jface.databinding.swt.IWidgetValueProperty;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
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.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.IMessage;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.emf.databinding.IEMFListProperty;
import org.eclipse.emf.databinding.IEMFValueProperty;
import org.eclipse.emf.databinding.edit.EMFEditProperties;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.example.databinding.project.ui.rcp.Activator;
import org.eclipse.emf.example.databinding.project.ui.rcp.NLSMessages;
import org.eclipse.emf.example.databinding.project.ui.rcp.databinding.FormTextProperty;
import org.eclipse.emf.example.databinding.project.ui.rcp.databinding.UpdateStrategyFactory;
import org.eclipse.emf.example.databinding.project.ui.rcp.databinding.Util;
import org.eclipse.emf.example.databinding.project.ui.rcp.dialogs.PersonFilterDialog;
import org.eclipse.emf.examples.databinding.project.core.IModelResource;
import org.eclipse.emf.examples.databinding.project.core.model.project.Person;
import org.eclipse.emf.examples.databinding.project.core.model.project.ProjectPackage;
/**
* Part creating the form area
*/
public class ProjectFormAreaPart
{
private DataBindingContext ctx;
private Form form;
private ProjectCommittersPart committerPart;
private Image projectImage;
/**
* Create a new part instance
* @param site the site
* @param parent the parent composite
* @param toolkit the form toolkit to use
* @param resource the resource
* @param manager manager for observables to avoid leaks
* @param master the master observable
*/
public ProjectFormAreaPart(
IViewSite site,
Composite parent,
FormToolkit toolkit,
IModelResource resource,
ObservablesManager manager,
IObservableValue master)
{
ImageDescriptor desc = Activator.imageDescriptorFromPlugin("org.eclipse.ui", "icons/full/obj16/generic_elements.gif");
if (desc != null)
{
projectImage = desc.createImage();
}
else
{
projectImage = null;
}
createFormArea(site, parent, toolkit, resource, manager, master);
}
private void createFormArea(
IViewSite site,
final Composite parent,
FormToolkit toolkit,
final IModelResource resource,
ObservablesManager manager,
final IObservableValue master)
{
final EditingDomain editingDomain = resource.getEditingDomain();
ctx = new EMFDataBindingContext();
// Fix for bug 278301
Util.masterDetailFixup(ctx, master);
addStatusSupport(manager, ctx);
form = toolkit.createForm(parent);
toolkit.decorateFormHeading(form);
form.setText(" ");
form.setImage(projectImage);
Composite body = form.getBody();
body.setLayout(new GridLayout(3, false));
IWidgetValueProperty prop = WidgetProperties.text(SWT.Modify);
{
final IEMFValueProperty shortProp = EMFEditProperties.value(editingDomain, ProjectPackage.Literals.PROJECT__SHORTNAME);
toolkit.createLabel(body, "&Short name");
Text t = toolkit.createText(body, "");
t.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
ctx.bindValue(prop.observeDelayed(400, t), shortProp.observeDetail(master));
final IEMFValueProperty longProp = EMFEditProperties.value(editingDomain, ProjectPackage.Literals.PROJECT__LONGNAME);
toolkit.createLabel(body, "&Long name");
t = toolkit.createText(body, "");
t.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
ctx.bindValue(prop.observeDelayed(400, t), longProp.observeDetail(master));
ComputedValue cVal = new ComputedValue()
{
private IObservableValue shortname = shortProp.observeDetail(master);
private IObservableValue longname = longProp.observeDetail(master);
@Override
protected Object calculate()
{
return shortname.getValue() + " - " + longname.getValue();
}
};
manager.addObservable(cVal);
ctx.bindValue(FormTextProperty.create().observe(form), cVal);
}
{
IEMFValueProperty mProp = EMFEditProperties.value(editingDomain, ProjectPackage.Literals.PROJECT__START);
toolkit.createLabel(body, "Start Date");
Text t = toolkit.createText(body, "");
t.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
ctx.bindValue(prop.observeDelayed(400, t), mProp.observeDetail(master), UpdateStrategyFactory.stringToDateNotNull(
NLSMessages.ProjectAdminViewPart_StartDateNotParseable,
"Start date must not be null"), UpdateStrategyFactory.dateToString());
}
{
IEMFValueProperty mProp = EMFEditProperties.value(editingDomain, ProjectPackage.Literals.PROJECT__END);
toolkit.createLabel(body, "End Date");
Text t = toolkit.createText(body, "");
t.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
ctx.bindValue(
prop.observeDelayed(400, t),
mProp.observeDetail(master),
UpdateStrategyFactory.stringToDate(NLSMessages.ProjectAdminViewPart_EndDateNotParseable),
UpdateStrategyFactory.dateToString());
}
{
IEMFValueProperty mProp = EMFEditProperties.value(editingDomain, ProjectPackage.Literals.PROJECT__HOMEPAGE);
toolkit.createLabel(body, "Homepage");
Text t = toolkit.createText(body, "");
t.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
ctx.bindValue(prop.observeDelayed(400, t), mProp.observeDetail(master));
}
{
IEMFValueProperty mProp = EMFEditProperties.value(editingDomain, ProjectPackage.Literals.PROJECT__DEVMAIL);
toolkit.createLabel(body, "Dev-Mail");
Text t = toolkit.createText(body, "");
t.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
ctx.bindValue(prop.observeDelayed(400, t), mProp.observeDetail(master));
}
{
IEMFListProperty mProp = EMFEditProperties.list(editingDomain, ProjectPackage.Literals.PROJECT__PROJECTLEADS);
toolkit.createLabel(body, "Project Leads").setLayoutData(new GridData(SWT.TOP, SWT.DEFAULT, false, false));
Table c = toolkit.createTable(body, SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
final TableViewer tv = new TableViewer(c);
tv.setLabelProvider(new ColumnLabelProvider()
{
@Override
public String getText(Object element)
{
Person p = (Person)element;
return p.getLastname() + ", " + p.getFirstname();
}
});
tv.setContentProvider(new ObservableListContentProvider());
tv.setInput(mProp.observeDetail(master));
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.heightHint = 100;
c.setLayoutData(gd);
Composite buttonContainer = toolkit.createComposite(body);
buttonContainer.setLayoutData(new GridData(SWT.DEFAULT, SWT.BOTTOM, false, false));
buttonContainer.setLayout(new GridLayout());
Button b = toolkit.createButton(buttonContainer, "Add ...", SWT.FLAT);
gd = new GridData(SWT.DEFAULT, SWT.DEFAULT);
gd.horizontalAlignment = SWT.FILL;
b.setLayoutData(gd);
b.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
PersonFilterDialog dialog = new PersonFilterDialog(parent.getShell(), resource);
if (dialog.open() == IDialogConstants.OK_ID)
{
Command cmd = AddCommand.create(
editingDomain,
master.getValue(),
ProjectPackage.Literals.PROJECT__PROJECTLEADS,
dialog.getFirstResult());
if (cmd.canExecute())
{
resource.executeCmd(cmd);
}
}
}
});
b = toolkit.createButton(buttonContainer, "Remove", SWT.FLAT);
gd = new GridData(SWT.DEFAULT, SWT.DEFAULT);
gd.horizontalAlignment = SWT.FILL;
b.setLayoutData(gd);
b.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
IStructuredSelection s = (IStructuredSelection)tv.getSelection();
if (!s.isEmpty())
{
Command cmd = RemoveCommand.create(
editingDomain,
master.getValue(),
ProjectPackage.Literals.PROJECT__PROJECTLEADS,
s.toList());
if (cmd.canExecute())
{
resource.executeCmd(cmd);
}
}
}
});
}
addTabArea(site, body, toolkit, ctx, editingDomain, manager, master);
body.setBackgroundMode(SWT.INHERIT_DEFAULT);
}
private void addTabArea(
IViewSite site,
Composite parent,
FormToolkit toolkit,
DataBindingContext ctx,
EditingDomain editingDomain,
ObservablesManager manager,
IObservableValue master)
{
CTabFolder folder = new CTabFolder(parent, SWT.BORDER);
folder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
folder.setSelectionBackground(new Color []{
toolkit.getColors().getColor(IFormColors.H_GRADIENT_END),
toolkit.getColors().getColor(IFormColors.H_GRADIENT_START) }, new int []{ 25 }, true);
folder.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
folder.setSelectionForeground(toolkit.getColors().getColor(IFormColors.TITLE));
folder.setSimple(false);
committerPart = new ProjectCommittersPart(site, folder, ctx, editingDomain, manager, master);
}
private void addStatusSupport(ObservablesManager mgr, final DataBindingContext ctx)
{
AggregateValidationStatus aggregateStatus = new AggregateValidationStatus(
ctx.getValidationStatusProviders(),
AggregateValidationStatus.MAX_SEVERITY);
aggregateStatus.addValueChangeListener(new IValueChangeListener()
{
public void handleValueChange(ValueChangeEvent event)
{
handleStateChange((IStatus)event.diff.getNewValue(), ctx);
}
});
}
private void handleStateChange(IStatus currentStatus, DataBindingContext ctx)
{
if (form.isDisposed() || form.getHead().isDisposed())
{
return;
}
if (currentStatus != null && currentStatus.getSeverity() != IStatus.OK)
{
int type = convertType(currentStatus.getSeverity());
List<IMessage> list = new ArrayList<IMessage>();
for (Iterator< ? > it = ctx.getValidationStatusProviders().iterator(); it.hasNext();)
{
ValidationStatusProvider validationStatusProvider = (ValidationStatusProvider)it.next();
final IStatus status = (IStatus)validationStatusProvider.getValidationStatus().getValue();
if (!status.isOK())
{
list.add(new IMessage()
{
public Control getControl()
{
return null;
}
public Object getData()
{
return null;
}
public Object getKey()
{
return null;
}
public String getPrefix()
{
return null;
}
public String getMessage()
{
return status.getMessage();
}
public int getMessageType()
{
return convertType(status.getSeverity());
}
});
}
}
form.setMessage("Data invalid", type, list.toArray(new IMessage [0]));
}
else
{
form.setMessage(null);
}
}
private int convertType(int severity)
{
switch (severity)
{
case IStatus.OK:
return IMessageProvider.NONE;
case IStatus.CANCEL:
return IMessageProvider.NONE;
case IStatus.INFO:
return IMessageProvider.INFORMATION;
case IStatus.WARNING:
return IMessageProvider.WARNING;
case IStatus.ERROR:
return IMessageProvider.ERROR;
default:
return IMessageProvider.NONE;
}
}
/**
* release all sources allocated
*/
public void dispose()
{
if (projectImage != null)
{
projectImage.dispose();
}
committerPart.dispose();
if (ctx != null)
{
ctx.dispose();
}
}
}