/******************************************************************************* * Copyright (c) 2009, 2015 Siemens AG 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: * Kai Tödter - initial implementation * Stephan Hackstedt <stephan.hackstedt@googlemail.com> - Bug 465449 ******************************************************************************/ package org.eclipse.e4.demo.contacts.views; import java.net.URL; import javax.inject.Inject; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.beans.PojoProperties; import org.eclipse.core.databinding.observable.value.ComputedValue; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.observable.value.WritableValue; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.e4.core.di.annotations.Creatable; import org.eclipse.e4.demo.contacts.databinding.AggregateNameObservableValue; import org.eclipse.e4.demo.contacts.model.Contact; import org.eclipse.e4.ui.css.swt.dom.WidgetElement; import org.eclipse.e4.ui.model.application.ui.MDirtyable; import org.eclipse.jface.databinding.swt.WidgetProperties; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; @Creatable public class DetailComposite extends Composite { private final MDirtyable dirtyable; private Contact originalContact; private Contact clonedContact; private boolean commitChanges = false; private Label imageLabel; private ImageData dummyPortrait; private boolean generalGroup; private final DataBindingContext dbc; private final WritableValue contactValue = new WritableValue(); private final IObservableValue scaledImage; @Inject public DetailComposite(MDirtyable dirtyable, final Composite parent) { super(parent, SWT.NONE); this.dirtyable = dirtyable; parent.getShell().setBackgroundMode(SWT.INHERIT_DEFAULT); dbc = new DataBindingContext(); URL url = FileLocator.find(Platform.getBundle("org.eclipse.e4.demo.contacts"), new Path("images/dummy.png"), null); ImageDescriptor imageDescriptor = ImageDescriptor.createFromURL(url); if (imageDescriptor != null) { dummyPortrait = imageDescriptor.getImageData(); } final GridLayout layout = new GridLayout(1, false); layout.verticalSpacing = 5; setLayout(layout); // General final Composite composite = createComposite(this); createSeparator(composite, "General"); createText(composite, "Title:", "title"); createText(composite, "Name:", "name"); // Leads to Aggregate // "firstName" "middleName" // "lastName" createText(composite, "Company:", "company"); createText(composite, "Job Title:", "jobTitle"); createText(composite, "Note:", "note"); createVerticalSpace(composite); // Business Address createSeparator(composite, "Business Address "); createText(composite, "Street:", "street"); createText(composite, "City:", "city"); createText(composite, "ZIP:", "zip"); createText(composite, "State/Prov:", "state"); createText(composite, "Country:", "country"); createVerticalSpace(composite); // Business Phone createSeparator(composite, "Business Phones "); createText(composite, "Phone:", "phone"); createText(composite, "Mobile:", "mobile"); createVerticalSpace(composite); // Business Internet createSeparator(composite, "Business Internet"); createText(composite, "Email:", "email"); createText(composite, "Web Page:", "webPage"); createVerticalSpace(composite); // Bind the image final IObservableValue imageObservableValue = PojoProperties .value((Class<?>) contactValue.getValue(), "image", ImageData.class).observeDetail(contactValue); this.scaledImage = new ComputedValue() { private Image currentImage; @Override protected Object calculate() { ImageData imageData = (ImageData) imageObservableValue.getValue(); if (imageData == null) { imageData = dummyPortrait; } double ratio = imageData.height / 85.0; int width = (int) (imageData.width / ratio); int height = (int) (imageData.height / ratio); ImageData scaledImageData = imageData.scaledTo(width, height); if (currentImage != null) { currentImage.dispose(); currentImage = null; } currentImage = new Image(Display.getCurrent(), scaledImageData); return currentImage; } @Override public void dispose() { if (currentImage != null) { currentImage.dispose(); currentImage = null; } super.dispose(); } }; dbc.bindValue(WidgetProperties.image().observe(imageLabel), scaledImage, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), null); addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { scaledImage.dispose(); } }); commitChanges = true; } private void setDirty(boolean dirty) { dirtyable.setDirty(dirty); } public boolean checkEmptyString(Object testString) { if (testString == null || !(testString instanceof String) || ((String) testString).trim().length() == 0) { return false; } return true; } private void createSeparator(Composite parent, String text) { generalGroup = text.equals("General"); final Label label = new Label(parent, SWT.NONE); label.setText(text + " "); WidgetElement.setID(label, "SeparatorLabel"); GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false); gridData.horizontalSpan = 3; label.setLayoutData(gridData); // final Label separator = new Label(parent, SWT.SEPARATOR // | SWT.HORIZONTAL); // GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false); // gridData.horizontalIndent = -100; // gridData.verticalIndent = 5; // gridData.horizontalSpan = 2; // separator.setLayoutData(gridData); } private void createVerticalSpace(Composite parent) { final Label label2 = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); label2.setVisible(false); GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false); gridData.horizontalSpan = 3; label2.setLayoutData(gridData); } private static Composite createComposite(final Composite parent) { final Composite composite = new Composite(parent, SWT.NONE); composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); composite.setLayout(new GridLayout(3, false)); return composite; } private Text createText(final Composite parent, final String labelText, final String property) { final Label label = new Label(parent, SWT.NONE); label.setText(labelText + " "); // the extra space is due to a bug in // font formatting when using css // styling GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalIndent = 20; label.setLayoutData(gridData); final Text text = new Text(parent, SWT.NONE); GridData gridData2 = new GridData(GridData.FILL_HORIZONTAL); gridData2.horizontalIndent = 0; if (!generalGroup) { gridData2.horizontalSpan = 2; } else { gridData2.horizontalSpan = 1; if (labelText.equals("Title:")) { // The label image is set with data binding imageLabel = new Label(parent, SWT.NONE); GridData gridData3 = new GridData(); gridData3.verticalSpan = 5; imageLabel.setLayoutData(gridData3); } } text.setLayoutData(gridData2); if (property != null) { if (property.equals("name")) { dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(text), new AggregateNameObservableValue(contactValue)); } else { dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(text), PojoProperties.value((Class<?>) contactValue.getValueType(), property, String.class) .observeDetail(contactValue)); } } text.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { if (commitChanges) { setDirty(true); } } }); return text; } public Contact getOriginalContact() { return originalContact; } public Contact getModifiedContact() { return clonedContact; } private void setTextEnabled(Composite composite, boolean enabled) { for (Control control : composite.getChildren()) { if (control instanceof Composite) { setTextEnabled((Composite) control, enabled); } else if (control instanceof Text) { control.setEnabled(enabled); } } } public void update(final Contact contact) { if (contact == null) { commitChanges = false; setTextEnabled(this, false); contactValue.setValue(null); } else { setTextEnabled(this, true); commitChanges = false; try { clonedContact = (Contact) contact.clone(); originalContact = contact; contactValue.setValue(clonedContact); commitChanges = true; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } } }