| /******************************************************************************* |
| * Copyright (c) 2010, 2022 BestSolution.at and others. |
| * |
| * 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: |
| * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation |
| * Dirk Fauth <dirk.fauth@googlemail.com> - Bug 426986 |
| * Steven Spungin <steven@spungin.tv> - Bug 430660, 430664, Bug 430809, 430717 |
| * Steven Spungin <steven@spungin.tv> - Ongoing maintenance |
| * Olivier Prouvost <olivier.prouvost@opcoach.com> - Bug 412567 |
| ******************************************************************************/ |
| package org.eclipse.e4.tools.emf.ui.internal.common.component; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Map.Entry; |
| |
| import org.eclipse.core.databinding.Binding; |
| import org.eclipse.core.databinding.UpdateValueStrategy; |
| import org.eclipse.core.databinding.observable.list.IObservableList; |
| import org.eclipse.core.databinding.observable.map.IObservableMap; |
| import org.eclipse.core.databinding.observable.value.IObservableValue; |
| import org.eclipse.core.databinding.property.list.IListProperty; |
| import org.eclipse.core.databinding.property.value.IValueProperty; |
| import org.eclipse.core.databinding.validation.IValidator; |
| import org.eclipse.core.databinding.validation.ValidationStatus; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.e4.core.contexts.IEclipseContext; |
| import org.eclipse.e4.tools.emf.ui.common.ContributionURIValidator; |
| import org.eclipse.e4.tools.emf.ui.common.IContributionClassCreator; |
| import org.eclipse.e4.tools.emf.ui.common.Util; |
| import org.eclipse.e4.tools.emf.ui.common.component.AbstractComponentEditor; |
| import org.eclipse.e4.tools.emf.ui.internal.E4Properties; |
| import org.eclipse.e4.tools.emf.ui.internal.Messages; |
| import org.eclipse.e4.tools.emf.ui.internal.ResourceProvider; |
| import org.eclipse.e4.tools.emf.ui.internal.common.AbstractPickList.PickListFeatures; |
| import org.eclipse.e4.tools.emf.ui.internal.common.E4PickList; |
| import org.eclipse.e4.tools.emf.ui.internal.common.E4StringPickList; |
| import org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs.BindingContextSelectionDialog; |
| import org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs.ContributionClassDialog; |
| import org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs.FindImportElementDialog; |
| import org.eclipse.e4.tools.emf.ui.internal.common.properties.ProjectOSGiTranslationProvider; |
| import org.eclipse.e4.tools.services.IClipboardService.Handler; |
| import org.eclipse.e4.tools.services.IResourcePool; |
| import org.eclipse.e4.ui.dialogs.filteredtree.PatternFilter; |
| import org.eclipse.e4.ui.internal.workbench.E4XMIResource; |
| import org.eclipse.e4.ui.model.application.MApplicationElement; |
| import org.eclipse.e4.ui.model.application.MContribution; |
| import org.eclipse.e4.ui.model.application.commands.MBindings; |
| import org.eclipse.e4.ui.model.application.commands.impl.CommandsPackageImpl; |
| import org.eclipse.e4.ui.model.application.impl.ApplicationFactoryImpl; |
| import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl; |
| import org.eclipse.e4.ui.model.application.ui.MElementContainer; |
| import org.eclipse.e4.ui.model.application.ui.MUIElement; |
| import org.eclipse.e4.ui.model.application.ui.MUILabel; |
| import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl; |
| import org.eclipse.emf.common.command.Command; |
| import org.eclipse.emf.common.util.BasicEMap; |
| import org.eclipse.emf.databinding.EMFDataBindingContext; |
| import org.eclipse.emf.databinding.EMFProperties; |
| import org.eclipse.emf.databinding.edit.EMFEditProperties; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.edit.command.AddCommand; |
| import org.eclipse.emf.edit.command.RemoveCommand; |
| import org.eclipse.emf.edit.command.SetCommand; |
| import org.eclipse.jface.databinding.swt.IWidgetValueProperty; |
| import org.eclipse.jface.databinding.swt.typed.WidgetProperties; |
| import org.eclipse.jface.databinding.viewers.IViewerValueProperty; |
| import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; |
| import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider; |
| import org.eclipse.jface.databinding.viewers.typed.ViewerProperties; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.fieldassist.ControlDecoration; |
| import org.eclipse.jface.fieldassist.FieldDecoration; |
| import org.eclipse.jface.fieldassist.FieldDecorationRegistry; |
| import org.eclipse.jface.viewers.CellEditor; |
| import org.eclipse.jface.viewers.ColumnLabelProvider; |
| import org.eclipse.jface.viewers.ComboViewer; |
| import org.eclipse.jface.viewers.EditingSupport; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.LabelProvider; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.TableViewer; |
| import org.eclipse.jface.viewers.TableViewerColumn; |
| import org.eclipse.jface.viewers.TextCellEditor; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.dnd.Clipboard; |
| import org.eclipse.swt.dnd.TextTransfer; |
| import org.eclipse.swt.events.KeyAdapter; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| 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.Link; |
| import org.eclipse.swt.widgets.Text; |
| |
| /** |
| * This class creates different widgets in editors... |
| * |
| * As all these widgets are common to a lot of editors. So this class could be |
| * moved in AbstractComponentEditor and the code would be really simplified |
| * because all parameters in static functions are already defined in |
| * AbstractComponentEditor |
| * |
| */ |
| public class ControlFactory { |
| public static final String COPY_HANDLER = ControlFactory.class.getName() + ".COPY_HANDLER"; //$NON-NLS-1$ |
| |
| public static class TextPasteHandler implements Handler { |
| private final Text t; |
| |
| public TextPasteHandler(Text t) { |
| this.t = t; |
| } |
| |
| public static void createFor(Text t) { |
| t.setData(COPY_HANDLER, new TextPasteHandler(t)); |
| } |
| |
| @Override |
| public void paste() { |
| final Clipboard cp = new Clipboard(t.getDisplay()); |
| final Object o = cp.getContents(TextTransfer.getInstance()); |
| cp.dispose(); |
| if (o == null) { |
| return; |
| } |
| |
| if (validate(o.toString())) { |
| t.paste(); |
| } |
| } |
| |
| @Override |
| public void cut() { |
| t.cut(); |
| } |
| |
| @Override |
| public void copy() { |
| t.copy(); |
| } |
| |
| public boolean validate(String text) { |
| return true; |
| } |
| } |
| |
| public static <M> void createXMIId(Composite parent, AbstractComponentEditor<M> editor) { |
| final Label l = new Label(parent, SWT.NONE); |
| l.setText("XMI:ID"); //$NON-NLS-1$ |
| l.setLayoutData(new GridData()); |
| |
| final Text t = new Text(parent, SWT.BORDER); |
| t.setEditable(false); |
| final GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| gd.horizontalSpan = 2; |
| t.setLayoutData(gd); |
| |
| TextPasteHandler.createFor(t); |
| |
| editor.getMaster().addValueChangeListener(event -> { |
| final M val = event.diff.getNewValue(); |
| if (val != null && val instanceof EObject && !t.isDisposed()) { |
| final Resource res = ((EObject) val).eResource(); |
| if (res instanceof E4XMIResource) { |
| final String v = ((E4XMIResource) res).getID((EObject) val); |
| if (v != null && v.trim().length() > 0) { |
| t.setText(v); |
| } |
| } |
| } |
| }); |
| } |
| |
| public static Composite createMapProperties(Composite parent, final Messages Messages, |
| final AbstractComponentEditor<?> editor, String label, final EStructuralFeature feature, int vIndent) { |
| return createMapProperties(parent, Messages, editor, label, null, feature, vIndent); |
| } |
| |
| public static Composite createMapProperties(Composite parent, final Messages messages, |
| final AbstractComponentEditor<?> editor, String label, String tooltip, final EStructuralFeature feature, |
| int vIndent) { |
| |
| final E4PickList pickList = new E4PickList(parent, SWT.NONE, Arrays.asList(PickListFeatures.NO_PICKER), |
| editor, feature) { |
| @Override |
| protected List<?> getContainerChildren(Object master) { |
| return null; |
| } |
| |
| @Override |
| protected void addPressed() { |
| final Dialog dialog = new Dialog(getShell()) { |
| private Text key; |
| private Text value; |
| |
| @Override |
| protected Control createDialogArea(Composite parent) { |
| getShell().setText(messages.ControlFactory_KeyValueShellTitle); |
| final Composite comp = (Composite) super.createDialogArea(parent); |
| final Composite container = new Composite(comp, SWT.NONE); |
| container.setLayout(new GridLayout(2, false)); |
| container.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| |
| Label l = new Label(container, SWT.NONE); |
| l.setText(messages.ControlFactory_Key); |
| |
| key = new Text(container, SWT.BORDER); |
| key.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| |
| l = new Label(container, SWT.NONE); |
| l.setText(messages.ControlFactory_Value); |
| |
| value = new Text(container, SWT.BORDER); |
| value.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| |
| return comp; |
| } |
| |
| @Override |
| protected void okPressed() { |
| if (key.getText().trim().length() > 0) { |
| final BasicEMap.Entry<String, String> entry = (org.eclipse.emf.common.util.BasicEMap.Entry<String, String>) ApplicationFactoryImpl.eINSTANCE |
| .createStringToStringMap(); |
| entry.setHash(key.hashCode()); |
| entry.setKey(key.getText()); |
| entry.setValue(value.getText().trim().length() > 0 ? value.getText() : null); |
| final Command cmd = AddCommand.create(editor.getEditingDomain(), editor.getMaster() |
| .getValue(), feature, entry); |
| if (cmd.canExecute()) { |
| editor.getEditingDomain().getCommandStack().execute(cmd); |
| super.okPressed(); |
| } |
| } |
| } |
| }; |
| dialog.open(); |
| } |
| }; |
| pickList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); |
| pickList.setText(label); |
| if (tooltip != null) { |
| pickList.setToolTipText(tooltip); |
| } |
| |
| final TableViewer tableviewer = pickList.getList(); |
| tableviewer.getTable().setHeaderVisible(true); |
| tableviewer.setContentProvider(new ObservableListContentProvider<>()); |
| |
| final GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); |
| gd.verticalIndent = vIndent; |
| tableviewer.getControl().setLayoutData(gd); |
| |
| TableViewerColumn column = new TableViewerColumn(tableviewer, SWT.NONE); |
| column.getColumn().setText(Messages.ControlFactory_KeyColumn); |
| column.getColumn().setWidth(200); |
| column.setLabelProvider(new ColumnLabelProvider() { |
| @SuppressWarnings("unchecked") |
| @Override |
| public String getText(Object element) { |
| final Entry<String, String> entry = (Entry<String, String>) element; |
| return entry.getKey(); |
| } |
| }); |
| |
| final TextCellEditor keyEditor = new TextCellEditor(tableviewer.getTable()); |
| column.setEditingSupport(new EditingSupport(tableviewer) { |
| |
| @Override |
| protected void setValue(Object element, Object value) { |
| final Command cmd = SetCommand.create(editor.getEditingDomain(), element, |
| ApplicationPackageImpl.Literals.STRING_TO_STRING_MAP__KEY, |
| value.toString().trim().length() == 0 ? null : value.toString()); |
| if (cmd.canExecute()) { |
| editor.getEditingDomain().getCommandStack().execute(cmd); |
| tableviewer.refresh(); |
| tableviewer.getTable().getColumn(0).pack(); |
| } |
| } |
| |
| @Override |
| protected Object getValue(Object element) { |
| @SuppressWarnings("unchecked") |
| final Entry<String, String> entry = (Entry<String, String>) element; |
| return entry.getKey(); |
| } |
| |
| @Override |
| protected CellEditor getCellEditor(Object element) { |
| return keyEditor; |
| } |
| |
| @Override |
| protected boolean canEdit(Object element) { |
| return true; |
| } |
| }); |
| |
| // FIXME How can we react upon changes in the Map-Value? |
| column = new TableViewerColumn(tableviewer, SWT.NONE); |
| column.getColumn().setText(Messages.ControlFactory_ValueColumn); |
| column.getColumn().setWidth(200); |
| column.setLabelProvider(new ColumnLabelProvider() { |
| @Override |
| public String getText(Object element) { |
| @SuppressWarnings("unchecked") |
| final Entry<String, String> entry = (Entry<String, String>) element; |
| return entry.getValue(); |
| } |
| }); |
| |
| final TextCellEditor cellEditor = new TextCellEditor(tableviewer.getTable()); |
| column.setEditingSupport(new EditingSupport(tableviewer) { |
| |
| @Override |
| protected void setValue(Object element, Object value) { |
| final Command cmd = SetCommand.create(editor.getEditingDomain(), element, |
| ApplicationPackageImpl.Literals.STRING_TO_STRING_MAP__VALUE, |
| value.toString().trim().length() == 0 ? null : value.toString()); |
| if (cmd.canExecute()) { |
| editor.getEditingDomain().getCommandStack().execute(cmd); |
| tableviewer.refresh(); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| protected Object getValue(Object element) { |
| final Entry<String, String> entry = (Entry<String, String>) element; |
| return entry.getValue() == null ? "" : entry.getValue(); //$NON-NLS-1$ |
| } |
| |
| @Override |
| protected CellEditor getCellEditor(Object element) { |
| return cellEditor; |
| } |
| |
| @Override |
| protected boolean canEdit(Object element) { |
| return true; |
| } |
| }); |
| |
| @SuppressWarnings("unchecked") |
| final IListProperty<Object, Object> prop = EMFEditProperties.list(editor.getEditingDomain(), feature); |
| final IObservableList<Object> observableList = prop.observeDetail(editor.getMaster()); |
| tableviewer.setInput(observableList); |
| observableList.addListChangeListener(event -> tableviewer.getTable().getColumn(0).pack()); |
| |
| return pickList; |
| } |
| |
| public static <M> void createTextField(Composite parent, String label, IObservableValue<M> master, |
| EMFDataBindingContext context, IWidgetValueProperty<Text, String> textProp, |
| IValueProperty<? super M, String> modelProp) { |
| createTextField(parent, label, null, master, context, textProp, modelProp, null); |
| } |
| |
| public static <M> void createTextField(Composite parent, String label, String tooltip, IObservableValue<M> master, |
| EMFDataBindingContext context, IWidgetValueProperty<Text, String> textProp, |
| IValueProperty<? super M, String> modelProp) { |
| createTextField(parent, label, tooltip, master, context, textProp, modelProp, null); |
| } |
| |
| public static <M> void createTextField(Composite parent, String label, IObservableValue<M> master, |
| EMFDataBindingContext context, IWidgetValueProperty<Text, String> textProp, |
| IValueProperty<? super M, String> modelProp, |
| final String warningText) { |
| createTextField(parent, label, null, master, context, textProp, modelProp, warningText); |
| } |
| |
| /** |
| * |
| * @param parent |
| * @param label |
| * @param master |
| * @param context |
| * @param textProp |
| * @param modelProp |
| * @param warningText |
| * Non null warningText means that a warning with this non-null text |
| * will be shown when the field is left empty |
| */ |
| public static <M> void createTextField(Composite parent, String label, String tooltip, IObservableValue<M> master, |
| EMFDataBindingContext context, IWidgetValueProperty<Text, String> textProp, |
| IValueProperty<? super M, String> modelProp, |
| final String warningText) { |
| createTextField(parent, label, tooltip, master, context, textProp, modelProp, warningText, |
| FieldDecorationRegistry.DEC_WARNING); |
| } |
| |
| /** |
| * |
| * @param parent |
| * @param label |
| * @param master |
| * @param context |
| * @param textProp |
| * @param modelProp |
| * @param decorationText |
| * Non null decorationText means that a message with this non-null |
| * text will be shown when the field is left empty |
| * @param decorationType |
| * Non null decorationType describes the type of the decoration. |
| * Supported types: FieldDecorationRegistry.DEC_ERROR, |
| * FieldDecorationRegistry.DEC_WARNING, |
| * FieldDecorationRegistry.DEC_INFORMATION |
| * |
| */ |
| public static <M> void createTextField(Composite parent, String label, String tooltip, IObservableValue<M> master, |
| EMFDataBindingContext context, IWidgetValueProperty<Text, String> textProp, |
| IValueProperty<? super M, String> modelProp, |
| final String decorationText, final String decorationType) { |
| final Label l = new Label(parent, SWT.NONE); |
| l.setText(label); |
| if (tooltip != null) { |
| l.setToolTipText(tooltip); |
| } |
| l.setLayoutData(new GridData()); |
| |
| final Text t = new Text(parent, SWT.BORDER); |
| final GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| gd.horizontalSpan = 2; |
| t.setLayoutData(gd); |
| TextPasteHandler.createFor(t); |
| if (decorationText != null) { |
| final ControlDecoration controlDecoration = new ControlDecoration(t, SWT.LEFT | SWT.TOP); |
| controlDecoration.setDescriptionText(decorationText); |
| final FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault().getFieldDecoration( |
| decorationType); |
| controlDecoration.setImage(fieldDecoration.getImage()); |
| final IValidator<Object> iv = value -> { |
| if (value == null) { |
| controlDecoration.show(); |
| return ValidationStatus.warning(decorationText); |
| } |
| if (value instanceof String) { |
| final String text = (String) value; |
| if (text.trim().length() == 0) { |
| controlDecoration.show(); |
| return getValidationStatus(decorationType, decorationText); |
| } |
| |
| controlDecoration.hide(); |
| return Status.OK_STATUS; |
| } |
| |
| controlDecoration.hide(); |
| return Status.OK_STATUS; |
| }; |
| final UpdateValueStrategy<String, String> acv = new UpdateValueStrategy<String, String>().setAfterConvertValidator(iv); |
| context.bindValue(textProp.observeDelayed(200, t), modelProp.observeDetail(master), acv, acv); |
| } else { |
| context.bindValue(textProp.observeDelayed(200, t), modelProp.observeDetail(master)); |
| } |
| } |
| |
| public static <M> void createTranslatedTextField(Composite parent, String label, IObservableValue<M> master, |
| EMFDataBindingContext context, IWidgetValueProperty<? super Text, String> textProp, |
| IValueProperty<? super M, String> modelProp, |
| IResourcePool resourcePool, IProject project) { |
| createTranslatedTextField(parent, label, null, master, context, textProp, modelProp, resourcePool, project); |
| } |
| |
| public static <M> void createTranslatedTextField(Composite parent, String label, String tooltip, |
| IObservableValue<M> master, EMFDataBindingContext context, |
| IWidgetValueProperty<? super Text, String> textProp, |
| IValueProperty<? super M, String> modelProp, IResourcePool resourcePool, IProject project) { |
| final Label l = new Label(parent, SWT.NONE); |
| l.setText(label); |
| if (tooltip != null) { |
| l.setToolTipText(tooltip); |
| } |
| l.setLayoutData(new GridData()); |
| |
| final Text t = new Text(parent, SWT.BORDER); |
| final GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| if (project == null) { |
| gd.horizontalSpan = 2; |
| } else { |
| gd.horizontalSpan = 2; |
| } |
| |
| t.setLayoutData(gd); |
| |
| TextPasteHandler.createFor(t); |
| context.bindValue(textProp.observeDelayed(200, t), modelProp.observeDetail(master)); |
| |
| // if (project != null) { |
| // Button b = new Button(parent, SWT.PUSH | SWT.FLAT); |
| // b.setImage(resourcePool.getImageUnchecked(ResourceProvider.IMG_Obj16_world_edit)); |
| // } |
| } |
| |
| private static IStatus getValidationStatus(String decorationType, String decorationText) { |
| switch (decorationType) { |
| case FieldDecorationRegistry.DEC_ERROR: |
| return ValidationStatus.error(decorationText); |
| case FieldDecorationRegistry.DEC_WARNING: |
| return ValidationStatus.warning(decorationText); |
| case FieldDecorationRegistry.DEC_INFORMATION: |
| return ValidationStatus.info(decorationText); |
| |
| default: |
| break; |
| } |
| |
| return ValidationStatus.warning(decorationText); |
| } |
| |
| |
| public static void createFindImport(Composite parent, final Messages Messages, |
| final AbstractComponentEditor<? extends MApplicationElement> editor, EMFDataBindingContext context) { |
| final IWidgetValueProperty<Text, String> textProp = WidgetProperties.text(SWT.Modify); |
| |
| final Label l = new Label(parent, SWT.NONE); |
| l.setText(Messages.ModelTooling_Common_RefId); |
| l.setLayoutData(new GridData()); |
| |
| final Text t = new Text(parent, SWT.BORDER); |
| final GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| t.setLayoutData(gd); |
| |
| TextPasteHandler.createFor(t); |
| |
| context.bindValue( |
| textProp.observeDelayed(200, t), |
| E4Properties.elementId(editor.getEditingDomain()).observeDetail(editor.getMaster())); |
| |
| Button b = ControlFactory.createFindButton(parent, editor.resourcePool); |
| b.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| final FindImportElementDialog dialog = new FindImportElementDialog(b.getShell(), editor, |
| (EObject) editor.getMaster().getValue(), Messages); |
| dialog.open(); |
| } |
| }); |
| } |
| |
| public static <E extends MUIElement, M extends MElementContainer<E>> void createSelectedElement( |
| Composite parent, final AbstractComponentEditor<M> editor, final EMFDataBindingContext context, |
| String label) { |
| final Label l = new Label(parent, SWT.NONE); |
| l.setText(label); |
| l.setLayoutData(new GridData()); |
| |
| final ComboViewer viewer = new ComboViewer(parent); |
| final GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| gd.horizontalSpan = 2; |
| viewer.getControl().setLayoutData(gd); |
| final IViewerValueProperty<ComboViewer, E> vProp = ViewerProperties.singleSelection(); |
| |
| final Binding[] binding = new Binding[1]; |
| final IObservableValue<E> uiObs = vProp.observe(viewer); |
| final IObservableValue<E> mObs = E4Properties.<E>selectedElement(editor.getEditingDomain()) |
| .observeDetail(editor.getMaster()); |
| editor.getMaster().addValueChangeListener(event -> { |
| if (binding[0] != null) { |
| binding[0].dispose(); |
| } |
| }); |
| |
| final IObservableList<E> list = E4Properties.<E>children(editor.getEditingDomain()) |
| .observeDetail(editor.getMaster()); |
| final ObservableListContentProvider<E> cp = new ObservableListContentProvider<>(); |
| viewer.setContentProvider(cp); |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| final IObservableMap<?, ?>[] attributeMaps = { |
| // Cast, because MUILabel is not part of E's type |
| ((IValueProperty) E4Properties.label(editor.getEditingDomain())).observeDetail(cp.getKnownElements()), |
| E4Properties.elementId(editor.getEditingDomain()).observeDetail(cp.getKnownElements()) }; |
| viewer.setLabelProvider(new ObservableMapLabelProvider(attributeMaps) { |
| @Override |
| public String getText(Object element) { |
| final EObject o = (EObject) element; |
| final String rv = o.eClass().getName(); |
| |
| if (element instanceof MUILabel) { |
| final MUILabel label = (MUILabel) element; |
| if (!Util.isNullOrEmpty(label.getLabel())) { |
| return rv + " - " + label.getLabel().trim(); //$NON-NLS-1$ |
| } |
| |
| } |
| |
| if (element instanceof MApplicationElement) { |
| final MApplicationElement appEl = (MApplicationElement) element; |
| if (!Util.isNullOrEmpty(appEl.getElementId())) { |
| return rv + " - " + appEl.getElementId(); //$NON-NLS-1$ |
| } |
| } |
| |
| return rv + "[" + list.indexOf(element) + "]"; //$NON-NLS-1$//$NON-NLS-2$ |
| } |
| }); |
| viewer.setInput(list); |
| |
| editor.getMaster().addValueChangeListener(event -> binding[0] = context.bindValue(uiObs, mObs)); |
| } |
| |
| public static void createBindingContextWiget(Composite parent, final Messages Messages, |
| final AbstractComponentEditor<? extends MBindings> editor, String label) { |
| createBindingContextWiget(parent, Messages, editor, label, null); |
| } |
| |
| public static void createBindingContextWiget(Composite parent, final Messages Messages, |
| final AbstractComponentEditor<? extends MBindings> editor, String label, String tooltip) { |
| { |
| final E4PickList pickList = new E4PickList(parent, SWT.NONE, Arrays.asList(PickListFeatures.NO_ORDER, |
| PickListFeatures.NO_PICKER), editor, CommandsPackageImpl.Literals.BINDINGS__BINDING_CONTEXTS) { |
| @Override |
| protected void addPressed() { |
| final BindingContextSelectionDialog dialog = new BindingContextSelectionDialog(getShell(), editor |
| .getEditor().getModelProvider(), Messages); |
| if (dialog.open() == IDialogConstants.OK_ID) { |
| final Command cmd = AddCommand.create(editor.getEditingDomain(), editor.getMaster().getValue(), |
| CommandsPackageImpl.Literals.BINDINGS__BINDING_CONTEXTS, dialog.getSelectedContext()); |
| if (cmd.canExecute()) { |
| editor.getEditingDomain().getCommandStack().execute(cmd); |
| } |
| } |
| } |
| }; |
| pickList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); |
| |
| pickList.setText(label); |
| pickList.getList().setInput(E4Properties.contexts().observeDetail(editor.getMaster())); |
| } |
| } |
| |
| public static Composite createStringListWidget(Composite parent, Messages Messages, |
| final AbstractComponentEditor<? extends MApplicationElement> editor, String label, |
| final EStructuralFeature feature, int vIndent) { |
| return createStringListWidget(parent, Messages, editor, label, null, feature, vIndent); |
| } |
| |
| public static Composite createStringListWidget(Composite parent, Messages Messages, |
| final AbstractComponentEditor<? extends MApplicationElement> editor, String label, String tooltip, |
| final EStructuralFeature feature, |
| int vIndent) { |
| |
| final E4StringPickList pickList = new E4StringPickList(parent, SWT.NONE, null, editor, feature) { |
| @Override |
| protected void addPressed() { |
| handleAddText(editor, feature, getTextWidget()); |
| } |
| }; |
| |
| pickList.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1)); |
| pickList.setText(label); |
| if (tooltip != null) { |
| pickList.setToolTipText(tooltip); |
| } |
| |
| final Text t = pickList.getTextWidget(); |
| t.addKeyListener(new KeyAdapter() { |
| @Override |
| public void keyPressed(KeyEvent e) { |
| if (e.keyCode == SWT.CR || e.keyCode == SWT.LF) { |
| handleAddText(editor, feature, t); |
| } |
| } |
| }); |
| |
| TextPasteHandler.createFor(t); |
| |
| final TableViewer viewer = pickList.getList(); |
| viewer.setLabelProvider(new LabelProvider()); |
| final GridData gd = (GridData) viewer.getTable().getLayoutData(); |
| gd.heightHint = 150; |
| |
| @SuppressWarnings("unchecked") |
| final IListProperty<Object, Object> prop = EMFProperties.list(feature); |
| viewer.setInput(prop.observeDetail(editor.getMaster())); |
| |
| viewer.addSelectionChangedListener(event -> { |
| final String strSelected = (String) ((StructuredSelection) event.getSelection()).getFirstElement(); |
| t.setText(strSelected != null ? strSelected : ""); //$NON-NLS-1$ |
| }); |
| |
| |
| return pickList; |
| } |
| |
| private static void handleAddText(AbstractComponentEditor<? extends MApplicationElement> editor, |
| EStructuralFeature feature, Text tagText) { |
| if (tagText.getText().trim().length() > 0) { |
| final String[] tags = tagText.getText().split(";"); //$NON-NLS-1$ |
| for (int i = 0; i < tags.length; i++) { |
| tags[i] = tags[i].trim(); |
| } |
| |
| final MApplicationElement appEl = editor.getMaster().getValue(); |
| final Command cmd = AddCommand.create(editor.getEditingDomain(), appEl, feature, Arrays.asList(tags)); |
| if (cmd.canExecute()) { |
| editor.getEditingDomain().getCommandStack().execute(cmd); |
| } |
| tagText.setText(""); //$NON-NLS-1$ |
| } |
| } |
| |
| // This method is left in for reference purposes |
| @SuppressWarnings("unused") |
| private static void handleReplaceText(AbstractComponentEditor<? extends MApplicationElement> editor, |
| EStructuralFeature feature, Text tagText, TableViewer viewer) { |
| if (tagText.getText().trim().length() > 0) { |
| if (!viewer.getSelection().isEmpty()) { |
| final String[] tags = tagText.getText().split(";"); //$NON-NLS-1$ |
| for (int i = 0; i < tags.length; i++) { |
| tags[i] = tags[i].trim(); |
| } |
| |
| final MApplicationElement appEl = editor.getMaster().getValue(); |
| final EObject el = (EObject) editor.getMaster().getValue(); |
| final List<?> ids = ((IStructuredSelection) viewer.getSelection()).toList(); |
| final Object curVal = ((IStructuredSelection) viewer.getSelection()).getFirstElement(); |
| final EObject container = (EObject) editor.getMaster().getValue(); |
| final List<?> l = (List<?>) container.eGet(feature); |
| final int idx = l.indexOf(curVal); |
| if (idx >= 0) { |
| final Command cmdRemove = RemoveCommand.create(editor.getEditingDomain(), el, feature, ids); |
| final Command cmdInsert = AddCommand.create(editor.getEditingDomain(), appEl, feature, |
| Arrays.asList(tags), idx); |
| if (cmdRemove.canExecute() && cmdInsert.canExecute()) { |
| editor.getEditingDomain().getCommandStack().execute(cmdRemove); |
| editor.getEditingDomain().getCommandStack().execute(cmdInsert); |
| } |
| tagText.setText(""); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| |
| public static <M> void createCheckBox(Composite parent, String label, IObservableValue<M> master, |
| EMFDataBindingContext context, IWidgetValueProperty<Button, Boolean> selectionProp, |
| IValueProperty<? super M, Boolean> modelProp) { |
| createCheckBox(parent, label, null, master, context, selectionProp, modelProp); |
| } |
| |
| public static <M> void createCheckBox(Composite parent, String label, String tooltip, IObservableValue<M> master, |
| EMFDataBindingContext context, IWidgetValueProperty<Button, Boolean> selectionProp, |
| IValueProperty<? super M, Boolean> modelProp) { |
| final Button checkBox = new Button(parent, SWT.CHECK); |
| checkBox.setText(label); |
| if (tooltip != null) { |
| checkBox.setToolTipText(tooltip); |
| } |
| checkBox.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 3, 1)); |
| context.bindValue(selectionProp.observe(checkBox), modelProp.observeDetail(master)); |
| } |
| |
| public static String getLocalizedLabel(ProjectOSGiTranslationProvider translationProvider, MUILabel element) { |
| return getLocalizedValue(translationProvider, (MApplicationElement) element, |
| UiPackageImpl.Literals.UI_LABEL__LABEL, UiPackageImpl.Literals.UI_LABEL__LOCALIZED_LABEL); |
| } |
| |
| public static String getLocalizedValue(ProjectOSGiTranslationProvider translationProvider, |
| MApplicationElement element, EStructuralFeature feature, EStructuralFeature localizedFeature) { |
| final EObject eo = (EObject) element; |
| if (translationProvider == null) { |
| final String value = (String) eo.eGet(localizedFeature); |
| if (value != null && value.trim().length() > 0) { |
| return value; |
| } |
| } |
| |
| final String value = (String) eo.eGet(feature); |
| if (value != null && value.trim().length() > 0) { |
| return tr(translationProvider, value); |
| } |
| return null; |
| |
| } |
| |
| public static String tr(ProjectOSGiTranslationProvider translationProvider, String label) { |
| if (label.startsWith("%") && translationProvider != null) { //$NON-NLS-1$ |
| final String key = label.substring(1); |
| final String translation = translationProvider.translate(key); |
| return translation == key ? label : translation; |
| } |
| return label; |
| } |
| |
| public static void attachFiltering(Text searchText, final TableViewer viewer, final PatternFilter filter) { |
| searchText.addModifyListener(e -> { |
| filter.setPattern(((Text) e.widget).getText()); |
| viewer.refresh(); |
| if (viewer.getTable().getItemCount() > 0) { |
| final Object data = viewer.getTable().getItem(0).getData(); |
| viewer.setSelection(new StructuredSelection(data)); |
| } |
| }); |
| searchText.addTraverseListener(e -> { |
| if (e.keyCode == SWT.ARROW_DOWN && viewer.getTable().getItemCount() > 0) { |
| viewer.getControl().setFocus(); |
| } |
| }); |
| } |
| |
| /** |
| * This method create a ClassURI field containing : a link to the class, a text |
| * field (to set the value bundleclass://....) and a button find to find the |
| * object. It must be called by all editors that need to get a class URI It adds |
| * a validator to check if the value exists (OK), or if it is null or empty |
| * (WARNING), or if the class does not exists (ERROR) |
| * |
| * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id= 412567">Bug |
| * 412567 </a> * |
| * @param parent |
| * the parent composite |
| * @param Messages |
| * The messages container class |
| * @param editor |
| * the current abstractComponentEditor containing a classURI field |
| * @param title |
| * the title of the field |
| * @param feature |
| * the associated Feature in the model |
| * @param c |
| * the Contribution Class creator to use to create the URI class |
| * @param project |
| * current project where application model stands |
| * @param context |
| * the EMFBinding context |
| * @param eclipseContext |
| * the Eclipse context |
| * @param adapter |
| * the selection adapter to use. For objects extending MContribution |
| * there is a default adapter. But for MPartDescriptors, which is not |
| * a MContribution, a specific adapter must be set (@see |
| * MPartDescriptorEditor) |
| */ |
| public static void createClassURIField(Composite parent, final Messages Messages, |
| final AbstractComponentEditor<?> editor, String title, final EAttribute feature, |
| IContributionClassCreator c, |
| IProject project, |
| EMFDataBindingContext context, IEclipseContext eclipseContext, SelectionAdapter adapter) { |
| final Link lnk; |
| final IWidgetValueProperty<Text, String> textProp = WidgetProperties.text(SWT.Modify); |
| |
| if (project != null && c != null) { |
| lnk = new Link(parent, SWT.NONE); |
| lnk.setText("<A>" + title + "</A>"); //$NON-NLS-1$//$NON-NLS-2$ |
| lnk.setLayoutData(new GridData()); |
| lnk.addSelectionListener(adapter); |
| } else { |
| lnk = null; |
| final Label l = new Label(parent, SWT.NONE); |
| l.setText(title); |
| l.setLayoutData(new GridData()); |
| } |
| |
| final Text t = new Text(parent, SWT.BORDER); |
| TextPasteHandler.createFor(t); |
| t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| t.addModifyListener(e -> { |
| if (lnk != null) { |
| lnk.setToolTipText(((Text) e.getSource()).getText()); |
| } |
| }); |
| @SuppressWarnings("unchecked") |
| final Binding binding = context.bindValue(textProp.observeDelayed(200, t), |
| ((IValueProperty<Object, Object>) EMFEditProperties.value(editor.getEditingDomain(), feature)) |
| .observeDetail(editor.getMaster()), |
| new UpdateValueStrategy<>().setAfterConvertValidator(new ContributionURIValidator()), |
| new UpdateValueStrategy<>()); |
| Util.addDecoration(t, binding); |
| |
| Button b = ControlFactory.createFindButton(parent, editor.resourcePool); |
| b.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| final ContributionClassDialog dialog = new ContributionClassDialog(b.getShell(), eclipseContext, |
| editor.getEditingDomain(), (MApplicationElement) editor.getMaster().getValue(), |
| feature, Messages); |
| dialog.open(); |
| } |
| }); |
| } |
| |
| public static void createClassURIField(Composite parent, final Messages Messages, |
| final AbstractComponentEditor<?> editor, String title, final EAttribute feature, |
| IContributionClassCreator c, IProject project, EMFDataBindingContext context, |
| IEclipseContext eclipseContext) { |
| createClassURIField(parent, Messages, editor, title, feature, c, project, context, eclipseContext, |
| new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| c.createOpen((MContribution) editor.getMaster().getValue(), editor.getEditingDomain(), project, |
| parent.getShell()); |
| } |
| }); |
| |
| } |
| |
| public static Button createFindButton(Composite parent, IResourcePool resourcePool) { |
| Button b = new Button(parent, SWT.PUSH | SWT.FLAT); |
| b.setText(Messages.ModelTooling_Common_FindEllipsis); |
| b.setImage(resourcePool.getImageUnchecked(ResourceProvider.IMG_Obj16_zoom)); |
| b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false)); |
| return b; |
| } |
| |
| } |