Skip to content

Content of file SWTControl.java

/*******************************************************************************
 * Copyright (c) 2011-2013 EclipseSource Muenchen GmbH and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 * Eugen Neufeld - initial API and implementation
 *
 *******************************************************************************/
package org.eclipse.emf.ecp.edit.internal.swt.util;

import java.util.Collections;
import java.util.List;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.databinding.edit.EMFEditObservables;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecp.edit.internal.swt.Activator;
import org.eclipse.emf.ecp.edit.spi.ECPAbstractControl;
import org.eclipse.emf.ecp.view.spi.model.VDiagnostic;
import org.eclipse.emf.ecp.view.spi.renderer.RenderingResultRow;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emfforms.spi.swt.core.ui.SWTValidationHelper;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
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.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;

/**
 * This class defines a SWTCOntrol which is an abstract class defining an {@link ECPAbstractControl} for SWT.
 *
 * @author Eugen Neufeld
 *
 */
@Deprecated
public abstract class SWTControl extends ECPAbstractControl implements ECPControlSWT {

	/**
	 * RAP theming variable to set.
	 */
	protected static final String CUSTOM_VARIANT = "org.eclipse.rap.rwt.customVariant";//$NON-NLS-1$
	/**
	 * The icon for a validation error.
	 */
	protected static final String VALIDATION_ERROR_ICON = "icons/validation_error.png";//$NON-NLS-1$

	private static final String ICONS_UNSET_FEATURE = "icons/unset_feature.png"; //$NON-NLS-1$

	/**
	 * The label for the validation icon.
	 */
	protected Label validationLabel;

	private IObservableValue modelValue;
private Binding binding; private Composite controlComposite; private Composite parentComposite; private StackLayout sl; private Label unsetLabel; /** * * {@inheritDoc} * * @see org.eclipse.emf.ecp.edit.internal.swt.util.ECPControlSWT#createControls(org.eclipse.swt.widgets.Composite) */ @Override public List<RenderingResultRow<Control>> createControls(final Composite parent) { final IItemPropertyDescriptor itemPropertyDescriptor = getItemPropertyDescriptor(getFirstSetting()); if (itemPropertyDescriptor == null) { return null; } parent.addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { dispose(); } }); createValidationIcon(parent); final List<RenderingResultRow<Control>> list = Collections.singletonList(SWTRenderingHelper.INSTANCE .getResultRowFactory().createRenderingResultRow( validationLabel, createControl(parent))); applyValidation(getControl().getDiagnostic()); // TODO remove asap backwardCompatibleHandleValidation(); return list; } /** * This method is called to render the control on a parent. * * @param parent the {@link Composite} which is the parent * @return the created {@link Composite} */ public Composite createControl(final Composite parent) { final Composite dataControl = createDataControl(parent); setHelpTooltips(); // init setEditable(isEditable()); binding = bindValue(); // write initial values to model (if they differ from the default value of the model-element) if (!getFirstStructuralFeature().isUnsettable() && !getFirstSetting().isSet()) { if (binding != null) { binding.updateTargetToModel(); } } return dataControl; } private void createValidationIcon(Composite composite) { if (!isEmbedded()) { validationLabel = new Label(composite, SWT.NONE); validationLabel.setBackground(composite.getBackground()); // set the size of the label to the size of the image // GridDataFactory.fillDefaults().hint(16, 17).applyTo(validationLabel); } } private Composite createDataControl(Composite composite) { final Composite innerComposite = new Composite(composite, SWT.NONE); innerComposite.setBackground(composite.getBackground()); // GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(innerComposite); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(innerComposite); createContentControl(innerComposite); return innerComposite; } private void setHelpTooltips() { final Control[] controls = getControlsForTooltip(); if (controls != null) { for (final Control control : controls) { control.setToolTipText(getHelpText()); } } } /** * Method for retrieving all controls which should have the help text as their tooltip. * * @return the array of the controls to set a tooltip to */ protected abstract Control[] getControlsForTooltip(); /** * Helper for creating the unset stacklayout and creating the control's composite. * * @param composite the parent {@link Composite} to create the control onto */ protected void createContentControl(Composite composite) { parentComposite = new Composite(composite, SWT.NONE); parentComposite.setBackground(composite.getBackground()); GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(parentComposite); sl = new StackLayout(); parentComposite.setLayout(sl); controlComposite = new Composite(parentComposite, SWT.NONE); controlComposite.setBackground(parentComposite.getBackground()); // 1 column for control, 1 for default unset button GridLayoutFactory.fillDefaults().numColumns(1).spacing(2, 0) .applyTo(controlComposite); unsetLabel = new Label(parentComposite, SWT.NONE); unsetLabel.setBackground(composite.getBackground()); unsetLabel.setForeground(composite.getShell().getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); unsetLabel.setAlignment(SWT.CENTER); unsetLabel.setText(getUnsetLabelText()); unsetLabel.addMouseListener(new MouseListener() { @Override public void mouseUp(MouseEvent e) { sl.topControl = controlComposite; parentComposite.layout(true); if (binding != null) { binding.updateTargetToModel(); } else { // TODO editingdomain is missing final Setting firstSetting = getFirstSetting(); final Object currentUnsetValue = firstSetting.get(true); firstSetting.set(currentUnsetValue); } } @Override public void mouseDown(MouseEvent e) { // nothing to do } @Override public void mouseDoubleClick(MouseEvent e) { // nothing to do } }); int numControls = 1; fillControlComposite(controlComposite); if (!isEmbedded() && getFirstStructuralFeature().isUnsettable()) { Button unsetButton = getCustomUnsetButton(); if (unsetButton == null) { numControls++; unsetButton = new Button(controlComposite, SWT.PUSH); unsetButton.setToolTipText(getUnsetButtonTooltip()); unsetButton.setImage(Activator.getImage(ICONS_UNSET_FEATURE)); } unsetButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { final Setting firstSetting = getFirstSetting(); final EditingDomain editingDomain = getEditingDomain(firstSetting); editingDomain.getCommandStack() .execute( new SetCommand(editingDomain, firstSetting.getEObject(), firstSetting .getEStructuralFeature(), SetCommand.UNSET_VALUE)); showUnsetLabel(); } }); unsetButton.setData(CUSTOM_VARIANT, "org_eclipse_emf_ecp_control_unset"); //$NON-NLS-1$ } if (numControls != 1) { // 1 column for control, 1 for default unset button ((GridLayout) controlComposite.getLayout()).numColumns = numControls; } // INFO margin needed for controlDecorator // .extendedMargins(10, 0, 0, 0) if (!getFirstStructuralFeature().isUnsettable() || getFirstSetting().isSet()) { sl.topControl = controlComposite; } else { sl.topControl = unsetLabel; } parentComposite.layout(); } /** * */ protected void showUnsetLabel() { sl.topControl = unsetLabel; parentComposite.layout(); } /** * This method must be overridden by concrete classes. Here the widget displaying the data is added to the * composite. * * @param controlComposite the {@link Composite} to add the widget to */ protected abstract void fillControlComposite(Composite controlComposite); /** * The default unset button will be displayed to the right of the control's composite. Concrete classes may override * this method to include an own unset button in their composite rather than using the default positioning. * * @return The custom unset button of the concrete class */ protected Button getCustomUnsetButton() { return null; } /** * The model value used for databinding. It is either the set one or the calculated. * * @return the {@link IObservableValue} */ protected IObservableValue getModelValue() { if (modelValue != null) { return modelValue; } final Setting setting = getFirstSetting(); modelValue = EMFEditObservables.observeValue(getEditingDomain(setting), setting.getEObject(), setting.getEStructuralFeature()); return modelValue; } /** * Allows the user to set the {@link IObservableValue} to use in the control during databinding. * * @param modelValue the set {@link IObservableValue} */ public void setObservableValue(IObservableValue modelValue) { this.modelValue = modelValue; } /** * A helper method which creates a button for an action on a composite. * * @param action the action to create a button for * @param composite the composite to create the button onto * @return the created button */ protected Button createButtonForAction(final Action action, final Composite composite) { final Button selectButton = new Button(composite, SWT.PUSH); selectButton.setImage(Activator.getImage(action)); selectButton.setEnabled(!getControl().isReadonly()); selectButton.setToolTipText(action.getToolTipText()); selectButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { action.run(); composite.layout(); } }); return selectButton; } /** * Triggers the control to perform the databinding. * * @return The {@link Binding} */ protected abstract Binding bindValue(); /** * Returns the help information. * * @return The help text */ protected String getHelpText() { return getItemPropertyDescriptor(getFirstSetting()).getDescription(null); } /** * Returns the validation icon matching the given severity. * * @param severity the severity of the {@link org.eclipse.emf.common.util.Diagnostic} * @return the icon to be displayed, or <code>null</code> when no icon is to be displayed */ protected Image getValidationIcon(int severity) { return SWTValidationHelper.INSTANCE.getValidationIcon(severity); } /** * Returns the background color for a control with the given validation severity. * * @param severity severity the severity of the {@link org.eclipse.emf.common.util.Diagnostic} * @return the color to be used as a background color */ protected Color getValidationBackgroundColor(int severity) { return SWTValidationHelper.INSTANCE.getValidationBackgroundColor(severity); } /** * Returns the string for the unset label. * * @return The unset label text */ protected abstract String getUnsetLabelText(); /** * Returns the string for the unset button tooltip. * * @return The unset button tooltip */ protected abstract String getUnsetButtonTooltip(); /** * Method for retrieving a {@link Color} based on the predefined SWT id. * * @param color the SWT id of the color * @return the Color or black if the id was incorrect */ protected final Color getSystemColor(int color) { if (parentComposite == null) { return Display.getDefault().getSystemColor(color); } return parentComposite.getShell().getDisplay().getSystemColor(color); } /** * Whether this control should be editable. * * @return true if the {@link IItemPropertyDescriptor#canSetProperty(Object)} returns true, false otherwise */ @Deprecated protected boolean isEditable() { final Setting firstSetting = getFirstSetting(); return getItemPropertyDescriptor(firstSetting).canSetProperty(firstSetting.getEObject()); } @Override public void dispose() { validationLabel = null; if (modelValue != null) { modelValue.dispose(); modelValue = null; } if (binding != null) { binding.dispose(); binding = null; } if (controlComposite != null) { controlComposite.dispose(); controlComposite = null; } if (parentComposite != null) { parentComposite.dispose(); parentComposite = null; } sl = null; if (unsetLabel != null) { unsetLabel.dispose(); unsetLabel = null; } super.dispose(); } /** * Helper method to keep the old validation. * * @since 1.2 */ @Override protected void backwardCompatibleHandleValidation() { final VDiagnostic diagnostic = getControl().getDiagnostic(); if (diagnostic == null) { return; } Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (getControl() == null) { return; } resetValidation(); for (final Object object : diagnostic.getDiagnostics()) { handleValidation((Diagnostic) object); } } }); } }