Java tutorial
/******************************************************************************* * Copyright (c) 2008, 2015 THALES GLOBAL SERVICES. * 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.eclipse.sirius.ui.tools.internal.wizards.pages; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.edit.provider.ComposedAdapterFactory; import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.sirius.business.api.dialect.DialectManager; import org.eclipse.sirius.business.api.session.Session; import org.eclipse.sirius.ecore.extender.business.api.permission.IPermissionAuthority; import org.eclipse.sirius.ecore.extender.business.api.permission.PermissionAuthorityRegistry; import org.eclipse.sirius.ui.tools.api.views.ViewHelper; import org.eclipse.sirius.viewpoint.DRepresentation; import org.eclipse.sirius.viewpoint.DRepresentationContainer; import org.eclipse.sirius.viewpoint.DSemanticDecorator; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Item; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer; /** * Wizard to select representations from an Aird. * * @author cbrun */ public class RepresentationsSelectionWizardPage extends WizardPage { private static final String SELECT_REPRESENTATIONS_TO_EXPORT = "Select Representations to export"; private static final String READ_ONLY_REPRESENTATION_CONTAINER = "The representation container is read only.\r\n Please select another representation."; /** The title of the page. */ private static final String PAGE_TITLE = "Selection of representations to export"; /** The page is completed. */ private static final int CODE_OK = 0; /** The user has not selected one or more diagrams. */ private static final int CODE_NO_SEL = 1; /** A representation cannot be extracted because the container is read only */ private static final int CODE_ERROR_READONLY = 2; /** The composite control of the page. */ private Composite pageComposite; /** The table viewer. */ private CheckboxTreeViewer treeViewer; /** The filter. */ private final Session root; private final Collection<DRepresentation> preselection; /** * Create a new <code>DescDiagramSelectionWizardPage</code>. * * @param root * the root object * @param representations * the preselection. */ public RepresentationsSelectionWizardPage(final Session root, final Collection<DRepresentation> representations) { super(PAGE_TITLE); this.setTitle(PAGE_TITLE); this.root = root; this.preselection = representations; if (preselection.size() > 0) { setPageComplete(true); } setMessage(SELECT_REPRESENTATIONS_TO_EXPORT, IMessageProvider.INFORMATION); } @Override public void createControl(final Composite parent) { initializeDialogUnits(parent); pageComposite = new Composite(parent, SWT.NONE); pageComposite.setLayout(new GridLayout()); pageComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); this.treeViewer = createTreeViewer(pageComposite); treeViewer.setInput(root); // treeViewer.addFilter(this.representationSelectionFilter); treeViewer.expandAll(); treeViewer.collapseAll(); setControl(pageComposite); for (final DRepresentation preselected : preselection) { this.treeViewer.setChecked(preselected, true); } } /** * Create the table viewer. * * @param parent * the parent composite. * @return the table viewer. */ private CheckboxTreeViewer createTreeViewer(final Composite parent) { final ContainerCheckedTreeViewer viewer = new DescDiagramSelectionTreeViewer(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); viewer.getControl().setLayoutData(gridData); viewer.getTree().setHeaderVisible(false); viewer.getTree().setLinesVisible(false); viewer.addCheckStateListener(new SiriusDiagramSelectionCheckStateListener()); viewer.setContentProvider(new SessionContentProvider(this.root)); viewer.setLabelProvider(new AdapterFactoryLabelProvider(ViewHelper.INSTANCE.createAdapterFactory())); return viewer; } /** * Change the page according to the new state of the selection. * * @author cbrun */ private class SiriusDiagramSelectionCheckStateListener implements ICheckStateListener { @Override public void checkStateChanged(final CheckStateChangedEvent event) { final int result = checkSelection(getSelectedElements()); switch (result) { case CODE_OK: case CODE_NO_SEL: setMessage(SELECT_REPRESENTATIONS_TO_EXPORT, IMessageProvider.INFORMATION); setPageComplete(true); break; case CODE_ERROR_READONLY: setMessage(READ_ONLY_REPRESENTATION_CONTAINER, IMessageProvider.ERROR); setPageComplete(false); break; default: setMessage("Unknown code result", IMessageProvider.ERROR); setPageComplete(false); break; } } } private int checkSelection(final Collection<DRepresentation> selectedRepresentations) { int result = CODE_OK; if (selectedRepresentations.isEmpty()) { result = CODE_NO_SEL; } else { for (DRepresentation item : selectedRepresentations) { // check permission authority EObject container = item.eContainer(); if (container instanceof DRepresentationContainer) { IPermissionAuthority permissionAuthority = PermissionAuthorityRegistry.getDefault() .getPermissionAuthority(container); if (permissionAuthority != null && !permissionAuthority.canDeleteInstance(item)) { // Cannot remove representation from the container result = CODE_ERROR_READONLY; break; // quit the while } } } // while } return result; } /** * Selects only diagrams. * * @author cbrun */ private class DescDiagramSelectionTreeViewer extends ContainerCheckedTreeViewer { /** * Create a new <code>DescDiagramSelectionTreeViewer</code>. * * @param parent * the parent composite. */ public DescDiagramSelectionTreeViewer(final Composite parent) { super(parent); } /** * Create a new <code>DescDiagramSelectionTreeViewer</code>. * * @param parent * the parent composite. * @param style * the style. */ public DescDiagramSelectionTreeViewer(final Composite parent, final int style) { super(parent, style); } /** * Create a new <code>DescDiagramSelectionTreeViewer</code>. * * @param tree * the tree. */ public DescDiagramSelectionTreeViewer(final Tree tree) { super(tree); } @Override protected void doCheckStateChanged(final Object element) { // // Check all diagrams that are under this element. final Widget item = findItem(element); if (item instanceof TreeItem) { final TreeItem treeItem = (TreeItem) item; if (!(element instanceof DRepresentation)) { final boolean result = updateChildrenItems(treeItem, treeItem.getChecked()); if (result) { treeItem.setGrayed(true); } else { treeItem.setGrayed(false); } treeItem.setChecked(result); } updateParentItems(treeItem); } } /** * Updates the check / gray state of all parent items */ private void updateParentItems(final TreeItem item) { if (item != null && !(item.getData() instanceof DRepresentation)) { final Item[] children = getChildren(item); boolean containsChecked = false; for (Item element : children) { final TreeItem curr = (TreeItem) element; containsChecked = containsChecked || curr.getChecked(); } item.setChecked(containsChecked); item.setGrayed(containsChecked); } if (item != null) { updateParentItems(item.getParentItem()); } } /** * Updates the check state of all created children * * @return <code>true</code> if an element as been checked. */ private boolean updateChildrenItems(final TreeItem parent, final boolean state) { boolean result = false; final Item[] children = getChildren(parent); for (Item element : children) { final TreeItem curr = (TreeItem) element; if (curr.getData() instanceof DRepresentation && ((curr.getChecked() != state) || curr.getGrayed())) { curr.setChecked(state); curr.setGrayed(false); result = result || state; result = result || updateChildrenItems(curr, state); } else if (curr.getData() != null && ((curr.getChecked() != state) || curr.getGrayed())) { final boolean childrenResult = updateChildrenItems(curr, state); if (childrenResult) { curr.setChecked(true); curr.setGrayed(true); } else { curr.setChecked(false); curr.setGrayed(false); } result = result || childrenResult; } } return result; } } /** * Return all selected elements. * * @return all selected elements. */ @SuppressWarnings("unchecked") public Collection<DRepresentation> getSelectedElements() { final Collection<DRepresentation> result = new HashSet<DRepresentation>(); result.addAll((Collection<? extends DRepresentation>) Arrays.asList(treeViewer.getCheckedElements())); result.removeAll(Arrays.asList(treeViewer.getGrayedElements())); return result; } /** * Session content provider. */ private static final class SessionContentProvider implements ITreeContentProvider { private static Object[] empty = new Object[0]; /** The semantic EMF content provider. */ private final AdapterFactoryContentProvider semanticProvider; private final Session session; /** * Create a new <code>SemanticDViewContentProvider</code> with the * specified analysis. * * @param functionnalAnalysis * the analysis to browse. */ public SessionContentProvider(final Session session) { this.session = session; final AdapterFactory adapterFactory = new ComposedAdapterFactory( ComposedAdapterFactory.Descriptor.Registry.INSTANCE); this.semanticProvider = new AdapterFactoryContentProvider(adapterFactory); } @Override public Object[] getChildren(final Object parentElement) { Object[] children = empty; if (parentElement instanceof Session) { children = ((Session) parentElement).getSemanticResources().toArray(); } else if (parentElement instanceof Resource) { // Test Resource before EObject because with CDO a CDOResource // is a EObject children = ((Resource) parentElement).getContents().toArray(); } else if (parentElement instanceof EObject && !(parentElement instanceof DRepresentation)) { final EObject parent = (EObject) parentElement; final Collection<DRepresentation> representations = this.findRepresentations(parent); Object[] semantic = this.semanticProvider.getChildren(parentElement); semantic = filtersSemanticFromAnotherResource(parent.eResource(), semantic); final Object[] result = new Object[representations.size() + semantic.length]; int i = 0; final Iterator<DRepresentation> iterRepresentation = representations.iterator(); while (iterRepresentation.hasNext()) { result[i++] = iterRepresentation.next(); } System.arraycopy(semantic, 0, result, representations.size(), semantic.length); children = result; } return children; } private Object[] filtersSemanticFromAnotherResource(final Resource resource, final Object[] semantic) { final Collection<Object> filtered = new ArrayList<Object>(); for (final Object object : semantic) { filtered.add(object); } for (final Object object : semantic) { if (object instanceof EObject) { Resource r = ((EObject) object).eResource(); if (r != null && resource != r && session.getSemanticResources().contains(r)) { filtered.remove(object); } } } return filtered.toArray(); } @Override public Object getParent(final Object element) { if (element instanceof EObject) { final EObject current = (EObject) element; final EObject parent = current instanceof DRepresentation ? ((DSemanticDecorator) current).getTarget() : current.eContainer(); return parent; } return null; } @Override public boolean hasChildren(final Object element) { return getChildren(element).length > 0; } @Override public Object[] getElements(final Object inputElement) { return getChildren(inputElement); } @Override public void dispose() { this.semanticProvider.dispose(); } @Override public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) { // empty } /** * Return all the diagrams for the specified viewpoint. * * @param semanticElement * the parent semantic element. * @return all the diagrams for the specified viewpoint. */ private Collection<DRepresentation> findRepresentations(final EObject semanticElement) { if (semanticElement == null) { return Collections.emptySet(); } return DialectManager.INSTANCE.getRepresentations(semanticElement, session); } } }