blob: 4920e5c106ad2efc1cefe82f045dcb92e316a83d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2017 BestSolution.at 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:
* Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
* Steven Spungin <steven@spungin.tv> - Bug 437469
* Patrik Suzzi <psuzzi@gmail.com> - Bug 467262
* Olivier Prouvost <olivier.prouvost@opcoach.com> - Bug 509488, 509551
******************************************************************************/
package org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.e4.tools.emf.ui.common.IModelElementProvider.Filter;
import org.eclipse.e4.tools.emf.ui.common.Util;
import org.eclipse.e4.tools.emf.ui.common.Util.InternalPackage;
import org.eclipse.e4.tools.emf.ui.common.component.AbstractComponentEditor;
import org.eclipse.e4.tools.emf.ui.internal.Messages;
import org.eclipse.e4.tools.emf.ui.internal.common.ClassContributionCollector;
import org.eclipse.e4.ui.model.application.MApplicationElement;
import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
import org.eclipse.e4.ui.model.fragment.MStringModelFragment;
import org.eclipse.e4.ui.model.fragment.impl.FragmentPackageImpl;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.fieldassist.AutoCompleteField;
import org.eclipse.jface.fieldassist.ComboContentAdapter;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
public class FindParentReferenceElementDialog extends TitleAreaDialog {
private final MStringModelFragment fragment;
private final AbstractComponentEditor editor;
private TableViewer viewer;
private final Messages Messages;
private ModelResultHandlerImpl currentResultHandler;
private WritableList list;
private ComboViewer eClassViewer;
private Text searchText;
private EClass selectedContainer;
private ClassContributionCollector collector;
/** Remember of classes that can be used for a fragment definition. */
private static List<EClass> extendableClasses = null;
public FindParentReferenceElementDialog(Shell parentShell, AbstractComponentEditor editor,
MStringModelFragment fragment, Messages Messages, EClass previousSelection) {
super(parentShell);
this.fragment = fragment;
this.editor = editor;
this.Messages = Messages;
this.collector = getCollector();
this.selectedContainer = previousSelection;
}
private ClassContributionCollector getCollector() {
final Bundle bundle = FrameworkUtil.getBundle(FindParentReferenceElementDialog.class);
final BundleContext context = bundle.getBundleContext();
final ServiceReference<?> ref = context.getServiceReference(ClassContributionCollector.class.getName());
if (ref != null) {
return (ClassContributionCollector) context.getService(ref);
}
return null;
}
@Override
protected boolean isResizable() {
return true;
}
@Override
protected Control createDialogArea(Composite parent) {
final Composite comp = (Composite) super.createDialogArea(parent);
final Image titleImage = new Image(parent.getDisplay(),
getClass().getClassLoader().getResourceAsStream("/icons/full/wizban/import_wiz.png")); //$NON-NLS-1$
setTitleImage(titleImage);
getShell().addDisposeListener(e -> titleImage.dispose());
getShell().setText(Messages.FindParentReferenceElementDialog_ShellTitle);
setTitle(Messages.FindParentReferenceElementDialog_Title);
setMessage(Messages.FindParentReferenceElementDialog_Message);
final Composite container = new Composite(comp, SWT.NONE);
container.setLayoutData(new GridData(GridData.FILL_BOTH));
container.setLayout(new GridLayout(2, false));
Label l = new Label(container, SWT.NONE);
l.setText(Messages.FindParentReferenceElementDialog_ContainerType);
Composite parentForCombo = new Composite(container, SWT.NONE);
parentForCombo.setLayout(new GridLayout(2, false));
parentForCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
final Combo combo = new Combo(parentForCombo, SWT.NONE);
eClassViewer = new ComboViewer(combo);
combo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
eClassViewer.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
return ((EClass) element).getName();
}
});
eClassViewer.setContentProvider(new ArrayContentProvider());
final List<EClass> eClassList = getExtendableClasses();
eClassViewer.setComparator(new ViewerComparator() {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
final EClass ec1 = (EClass) e1;
final EClass ec2 = (EClass) e2;
return ec1.getName().compareTo(ec2.getName());
}
});
eClassViewer.setInput(eClassList);
eClassViewer.getControl().setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
eClassViewer.addSelectionChangedListener(event -> updateSearch());
final ArrayList<String> vals = new ArrayList<>();
for (final EClass item : eClassList) {
vals.add(item.getName());
}
final String[] values = vals.toArray(new String[0]);
final ComboContentAdapter textContentAdapter = new ComboContentAdapter() {
@Override
public void setControlContents(Control control, String text1, int cursorPosition) {
super.setControlContents(control, text1, cursorPosition);
final int index = Arrays.asList(values).indexOf(text1);
final EClass eClass = eClassList.get(index);
eClassViewer.setSelection(new StructuredSelection(eClass));
}
};
new AutoCompleteField(combo, textContentAdapter, values);
Label help = new Label(parentForCombo, SWT.NONE);
final Image helpImage = new Image(parent.getDisplay(),
getClass().getClassLoader().getResourceAsStream("/icons/full/obj16/missing_image_placeholder.png")); //$NON-NLS-1$
help.setImage(helpImage);
help.setToolTipText(Messages.FindParentReferenceElementDialog_HelpTooltip);
l = new Label(container, SWT.NONE);
l.setText(Messages.FindParentReferenceElementDialog_Search);
searchText = new Text(container, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
searchText.setLayoutData(gd);
l = new Label(container, SWT.PUSH);
viewer = new TableViewer(container);
gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 200;
viewer.getControl().setLayoutData(gd);
viewer.setLabelProvider(new StyledCellLabelProvider() {
@Override
public void update(ViewerCell cell) {
final EObject o = (EObject) cell.getElement();
final AbstractComponentEditor editor = FindParentReferenceElementDialog.this.editor.getEditor()
.getEditor(o.eClass());
cell.setImage(editor.getImage(o));
final MApplicationElement appEl = (MApplicationElement) o;
final StyledString styledString = new StyledString(editor.getLabel(o) + " (" //$NON-NLS-1$
+ (appEl.getElementId() == null
? "<" + Messages.FindParentReferenceElementDialog_NoId + ">" : appEl.getElementId()) //$NON-NLS-1$ //$NON-NLS-2$
+ ")", null); //$NON-NLS-1$
final String detailLabel = editor.getDetailLabel(o);
if (detailLabel != null && !detailLabel.equals(appEl.getElementId())) {
styledString.append(" - " + detailLabel, StyledString.DECORATIONS_STYLER); //$NON-NLS-1$
}
styledString.append(" - " + o.eResource().getURI(), StyledString.COUNTER_STYLER); //$NON-NLS-1$
cell.setStyleRanges(styledString.getStyleRanges());
cell.setText(styledString.getString());
}
});
viewer.setContentProvider(new ObservableListContentProvider());
viewer.addDoubleClickListener(event -> okPressed());
list = new WritableList();
viewer.setInput(list);
searchText.addModifyListener(e -> updateSearch());
final Button button = new Button(container, SWT.PUSH);
button.setText(Messages.FindParentReferenceElementDialog_ClearCache);
button.setLayoutData(new GridData(GridData.END, GridData.CENTER, true, false, 2, 1));
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
collector.clearModelCache();
}
});
// Manage the current selection on comboviewer (previous or first one).
if (selectedContainer != null) {
eClassViewer.setSelection(new StructuredSelection(selectedContainer));
} else {
// Select addon by default (not necessary in the first position in
// the eclasslist...)
eClassViewer.setSelection(new StructuredSelection(ApplicationPackageImpl.Literals.APPLICATION));
}
return comp;
}
/**
* This method returns classes that have extensible fields It rejects
* eClasses having only transientData and persistedState for instance Result
* is cached in a singleton for each dialog instances...
*
* @return
*/
private List<EClass> getExtendableClasses() {
if (extendableClasses == null) {
extendableClasses = new ArrayList<>();
for (final InternalPackage p : Util.loadPackages()) {
for (EClass c : p.getAllClasses()) {
if (Util.canBeExtendedInAFragment(c)) {
extendableClasses.add(c);
}
}
}
}
return extendableClasses;
}
protected void updateSearch() {
if (currentResultHandler != null) {
currentResultHandler.cancel();
}
list.clear();
final Filter filter = new Filter(
(EClass) ((IStructuredSelection) eClassViewer.getSelection()).getFirstElement(), searchText.getText());
currentResultHandler = new ModelResultHandlerImpl(list, filter, editor, ((EObject) fragment).eResource());
collector.findModelElements(filter, currentResultHandler);
}
@Override
protected void okPressed() {
final IStructuredSelection s = (IStructuredSelection) viewer.getSelection();
if (!s.isEmpty()) {
final MApplicationElement el = (MApplicationElement) s.getFirstElement();
if (el.getElementId() != null && el.getElementId().trim().length() > 0) {
final Command cmd = SetCommand.create(editor.getEditingDomain(), fragment,
FragmentPackageImpl.Literals.STRING_MODEL_FRAGMENT__PARENT_ELEMENT_ID, el.getElementId());
if (cmd.canExecute()) {
selectedContainer = (EClass) ((IStructuredSelection) eClassViewer.getSelection()).getFirstElement();
editor.getEditingDomain().getCommandStack().execute(cmd);
super.okPressed();
}
} else {
setErrorMessage(Messages.FindParentReferenceElementDialog_NoReferenceId);
}
}
}
/**
* Gets the selected EClass container after a successeful selection of the
* parent
*
* @return the selectedContainer
*/
public EClass getSelectedContainer() {
return selectedContainer;
}
}