Java tutorial
/******************************************************************************* * Copyright (c) 2016 Obeo. * 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: * Obeo - initial API and implementation * *******************************************************************************/ package org.obeonetwork.m2doc.ui.dialog; import com.google.common.base.Predicates; import com.google.common.collect.Collections2; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.presentation.EcoreActionBarContributor.ExtendedLoadResourceAction.RegisteredPackageDialog; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; 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.Combo; 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.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.FilteredTree; import org.eclipse.ui.dialogs.PatternFilter; import org.obeonetwork.m2doc.tplconf.EPackageMapping; import org.obeonetwork.m2doc.tplconf.ScalarType; import org.obeonetwork.m2doc.tplconf.StructuredType; import org.obeonetwork.m2doc.tplconf.TemplateConfig; import org.obeonetwork.m2doc.tplconf.TemplateConfigUtil; import org.obeonetwork.m2doc.tplconf.TemplateType; import org.obeonetwork.m2doc.tplconf.TemplateVariable; import org.obeonetwork.m2doc.tplconf.TplconfFactory; import org.obeonetwork.m2doc.tplconf.impl.TplconfFactoryImpl; import static com.google.common.base.Preconditions.checkNotNull; /** * Dialog to configure one template variable. * * @author ldelaigue */ public class VariableEditDialog extends TitleAreaDialog { private final TemplateConfig config; private final TemplateVariable variable; private final AdapterFactory adapterFactory; private Text txtName; private ComboViewer mmComboViewer; private Text txtTypeName; private TreeViewer classifierTreeViewer; private FilteredTree filteredTree; private Map<String, EPackageMapping> mappingsByUri = new LinkedHashMap<>(); /** * Create the dialog. * * @param parentShell * The parent shell * @param var * The variable to edit, must NOT be attached to the {@link TemplateConfig} * @param config * The target {@link TemplateConfig} * @param adapterFactory * The {@link AdapterFactory} */ public VariableEditDialog(Shell parentShell, TemplateVariable var, TemplateConfig config, AdapterFactory adapterFactory) { super(parentShell); setShellStyle(SWT.CLOSE | SWT.RESIZE | SWT.TITLE | SWT.APPLICATION_MODAL); this.variable = checkNotNull(var); this.config = checkNotNull(config); this.adapterFactory = checkNotNull(adapterFactory); } /** * Create contents of the dialog. * * @param parent */ @Override protected Control createDialogArea(Composite parent) { setTitle("Configure Variable"); setMessage("Configure the variable name and type."); Composite area = (Composite) super.createDialogArea(parent); Composite container = new Composite(area, SWT.NONE); container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); container.setLayout(new GridLayout(2, false)); Label lblVariableName = new Label(container, SWT.NONE); lblVariableName.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); lblVariableName.setText("TemplateVariable Name:"); txtName = new Text(container, SWT.BORDER); txtName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); Label lblMetamodel = new Label(container, SWT.NONE); lblMetamodel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); lblMetamodel.setText("Meta-Model:"); Composite composite = new Composite(container, SWT.NONE); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1)); GridLayout gl_composite = new GridLayout(2, false); gl_composite.verticalSpacing = 0; gl_composite.marginHeight = 0; gl_composite.marginWidth = 0; gl_composite.horizontalSpacing = 0; composite.setLayout(gl_composite); Combo combo = new Combo(composite, SWT.NONE); combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1)); mmComboViewer = new ComboViewer(combo); mmComboViewer.setContentProvider(new IStructuredContentProvider() { @Override public Object[] getElements(Object inputElement) { @SuppressWarnings("unchecked") Map<String, EPackageMapping> map = (Map<String, EPackageMapping>) inputElement; List<Object> result = new ArrayList<>(); result.add(config); result.addAll(map.values()); return result.toArray(new Object[result.size()]); } @Override public void dispose() { // Nothing } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // Nothing } }); mmComboViewer.setLabelProvider(new AdapterFactoryLabelProvider(adapterFactory)); for (EPackageMapping mapping : config.getMappings()) { if (mapping.getUri() != null && mapping.getName() != null) { mappingsByUri.put(mapping.getUri(), mapping); } } mmComboViewer.setInput(mappingsByUri); Button btnAddMetamodel = new Button(composite, SWT.NONE); btnAddMetamodel.setText("..."); btnAddMetamodel.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { RegisteredPackageDialog dialog = new RegisteredPackageDialog(Display.getCurrent().getActiveShell()); dialog.setMultipleSelection(false); dialog.open(); if (dialog.getReturnCode() == Dialog.OK) { Object firstResult = dialog.getFirstResult(); if (firstResult instanceof String) { String uri = (String) firstResult; if (mappingsByUri.containsKey(uri)) { // Reuse the one that's already registered mmComboViewer.setSelection(new StructuredSelection(mappingsByUri.get(uri)), true); } else { final EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(uri); if (ePackage != null) { EPackageMapping newMapping = TplconfFactory.eINSTANCE.createEPackageMapping(); newMapping.setName(ePackage.getName()); newMapping.setUri(ePackage.getNsURI()); newMapping.setEPackage(ePackage); mappingsByUri.put(uri, newMapping); mmComboViewer.refresh(); mmComboViewer.setSelection(new StructuredSelection(newMapping), true); } } } } } }); Label lblType = new Label(container, SWT.NONE); lblType.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); lblType.setText("TemplateType:"); PatternFilter filter = new PatternFilter(); filteredTree = new FilteredTree(container, SWT.BORDER | SWT.SINGLE, filter, true); classifierTreeViewer = filteredTree.getViewer(); Label lblTypeName = new Label(container, SWT.NONE); lblTypeName.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); lblTypeName.setText("TemplateType Name:"); txtTypeName = new Text(container, SWT.BORDER); txtTypeName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); classifierTreeViewer.setContentProvider(new ITreeContentProvider() { @Override public boolean hasChildren(Object element) { return false; } @Override public Object getParent(Object element) { return null; } @Override public Object[] getElements(Object inputElement) { if (inputElement instanceof EPackageMapping) { EPackageMapping mm = ((EPackageMapping) inputElement); if (mm.getEPackage() instanceof EPackage) { EList<EClassifier> eClassifiers = ((EPackage) mm.getEPackage()).getEClassifiers(); return eClassifiers.toArray(new Object[eClassifiers.size()]); } } else if (inputElement instanceof TemplateConfig) { Collection<TemplateType> allTypes = ((TemplateConfig) inputElement).getTypesByName().values(); return Collections2.filter(allTypes, Predicates.instanceOf(ScalarType.class)).toArray(); } return new Object[0]; } @Override public Object[] getChildren(Object parentElement) { return null; } @Override public void dispose() { // Nothing } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // Nothing } }); classifierTreeViewer.setLabelProvider(new AdapterFactoryLabelProvider(adapterFactory)); // Set initial values txtName.setText(variable.getName()); if (variable.getTypeName() != null) { txtTypeName.setText(variable.getTypeName()); } TemplateType type = variable.getType(); if (type instanceof ScalarType) { mmComboViewer.setSelection(new StructuredSelection(config), true); classifierTreeViewer.setSelection(new StructuredSelection(variable.getType()), true); } else if (type instanceof StructuredType) { if (((StructuredType) variable.getType()).getMapping() != null) { mmComboViewer.setSelection( new StructuredSelection(((StructuredType) variable.getType()).getMapping()), true); } if (((StructuredType) variable.getType()).getEClassifier() != null) { classifierTreeViewer.setSelection( new StructuredSelection(((StructuredType) variable.getType()).getEClassifier()), true); } } hookListeners(); return container; } protected void hookListeners() { txtName.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { variable.setName(txtName.getText()); validate(); } }); txtTypeName.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { final String typeName = txtTypeName.getText(); variable.setTypeName(typeName); if (typeName == null || typeName.length() == 0) { mmComboViewer.setSelection(new StructuredSelection()); classifierTreeViewer.setSelection(new StructuredSelection()); } else if (typeName.indexOf(TemplateConfigUtil.METAMODEL_TYPE_SEPARATOR) > 0) { int index = typeName.indexOf(TemplateConfigUtil.METAMODEL_TYPE_SEPARATOR); String mmName = typeName.substring(0, index); EPackageMapping mapping = findMappingByName(mmName); if (mapping != null) { mmComboViewer.setSelection(new StructuredSelection(mapping), true); } if (config.getTypesByName().containsKey(typeName)) { TemplateType type = config.getTypesByName().get(typeName); if (type instanceof ScalarType) { classifierTreeViewer.setSelection(new StructuredSelection(type), true); } else if (type instanceof StructuredType) { if (((StructuredType) type).getEClassifier() != null) { classifierTreeViewer.setSelection( new StructuredSelection(((StructuredType) type).getEClassifier()), true); } else { classifierTreeViewer.setSelection(new StructuredSelection(), true); } } } else { String classifierName = typeName.substring(index + 2); filteredTree.getFilterControl().setText(classifierName); if (mmName != null && mapping != null) { if (mapping.getEPackage() != null) { EClassifier eClassifier = ((EPackage) mapping.getEPackage()) .getEClassifier(classifierName); if (eClassifier != null) { final StructuredType mmType = TplconfFactory.eINSTANCE.createStructuredType(); mmType.setEClassifier(eClassifier); mmType.setMapping(mapping); mmType.setMappingName(mmName); mmType.setName(classifierName); classifierTreeViewer.setSelection(new StructuredSelection(eClassifier), true); } else { classifierTreeViewer.setSelection(new StructuredSelection(), true); } } else { classifierTreeViewer.setSelection(new StructuredSelection(), true); } } else { classifierTreeViewer.setSelection(new StructuredSelection(), true); } } } else { // scalar type? mmComboViewer.setSelection(new StructuredSelection(config)); TemplateType type = config.getTypesByName().get(typeName); if (type instanceof ScalarType) { classifierTreeViewer.setSelection(new StructuredSelection(type), true); } else { classifierTreeViewer.setSelection(new StructuredSelection(), true); } } validate(); } }); classifierTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { Object firstElement = ((IStructuredSelection) event.getSelection()).getFirstElement(); final TemplateType type; if (firstElement instanceof EClassifier) { EClassifier eClassifier = (EClassifier) firstElement; final String typeName = TemplateConfigUtil.typeName(eClassifier); if (config.getTypesByName().containsKey(typeName)) { type = config.getTypesByName().get(typeName); } else { type = TplconfFactoryImpl.eINSTANCE.createStructuredType(); final StructuredType newType = (StructuredType) type; newType.setName(eClassifier.getName()); newType.setEClassifier(eClassifier); newType.setMappingName(eClassifier.getEPackage().getName()); newType.setMapping(mappingsByUri.get(eClassifier.getEPackage().getName())); } } else if (firstElement instanceof ScalarType) { type = (ScalarType) firstElement; } else { type = null; } variable.setType(type); if (type != null) { setTypeName(type); } validate(); } }); mmComboViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { if (event.getSelection().isEmpty()) { classifierTreeViewer.setInput(config); } else { Object firstElement = ((IStructuredSelection) event.getSelection()).getFirstElement(); if (firstElement != null) { classifierTreeViewer.setInput(firstElement); } } classifierTreeViewer.refresh(); validate(); } }); } private EPackageMapping findMappingByName(String name) { if (name != null) { for (EPackageMapping mapping : mappingsByUri.values()) { if (name.equals(mapping.getName())) { return mapping; } } } return null; } protected void setTypeName(final TemplateType type) { if (type == null) { if (txtTypeName.getText() != null && txtTypeName.getText().length() > 0) { txtTypeName.setText(""); } } else if (type instanceof ScalarType) { if (txtTypeName.getText() == null || !txtTypeName.getText().equals(type.getName())) { txtTypeName.setText(type.getName()); } } else if (type instanceof StructuredType) { String typeName = TemplateConfigUtil.typeName(((StructuredType) type).getMappingName(), type.getName()); if (txtTypeName.getText() == null || !txtTypeName.getText().equals(typeName)) { txtTypeName.setText(typeName); } } } protected void validate() { if (!TemplateConfigUtil.isValidVariableName(variable.getName())) { blockWithMessage( "The variable name must be valid (start with a letter or underscore, contain only letters, digits, or underscores)"); return; } if (variable.getTypeName() == null || variable.getTypeName().length() == 0) { blockWithMessage("The variable type name must be set"); return; } if (variable.getType() == null && variable.getTypeName().indexOf(TemplateConfigUtil.METAMODEL_TYPE_SEPARATOR) <= 0) { blockWithMessage("The scalar type of the variable is not supported"); return; } if (!TemplateConfigUtil.isValidTypeName(variable.getTypeName())) { blockWithMessage("The variable type is not valid"); return; } getButton(IDialogConstants.OK_ID).setEnabled(true); setErrorMessage(null); } private void blockWithMessage(String message) { setErrorMessage(message); getButton(IDialogConstants.OK_ID).setEnabled(false); } /** * Create contents of the button bar. * * @param parent */ @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); } }