/******************************************************************************* * Copyright (c) 2005, 2008 AIRBUS FRANCE. * 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: * David Sciamma (Anyware Technologies) - initial API and implementation * Mathieu Garcia (Anyware Technologies) - initial API and implementation * Jacques Lescot (Anyware Technologies) - initial API and implementation * Thomas Friol (Anyware Technologies) - initial API and implementation *******************************************************************************/ package org.eclipse.papyrus.views.documentation.view; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.window.Window; import org.eclipse.papyrus.views.documentation.DocumentationUnsupportedException; import org.eclipse.papyrus.views.documentation.IDocumentationManager; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; 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.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorRegistry; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.ResourceSelectionDialog; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.model.WorkbenchLabelProvider; /** * A class defining a composite to edit the resources of a EModelElement as an EAnnotation. <br> * Creation : 10 oct. 2005 * * @author <a href="mailto:thomas.friol@anyware-tech.com">Thomas FRIOL</a> */ public class ResourcesComposite extends DocPageComposite { private TreeViewer resourcesList; private Button addResourcesButton; private Button removeResourcesButton; private Button editResourceButton; private ISelectionChangedListener selectionChangedListener; private SelectionListener buttonSelectionListener; private IDoubleClickListener listDoubleClickListener; private KeyListener listKeyListener; /** * Constructor. * * @param parent the parent composite * @param style the composite style * @param editingDomainProvider the provider of editing domain to execute commands */ public ResourcesComposite(Composite parent, int style) { super(parent, style); } /** * @see org.topcased.modeler.documentation.DocPageComposite#createContents(org.eclipse.swt.widgets.Composite) */ protected void createContents(Composite parent) { selectionChangedListener = new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { handleResourcesListSelectionChanged(); } }; buttonSelectionListener = new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (e.getSource() == addResourcesButton) { handleAddResources(); } else if (e.getSource() == removeResourcesButton) { handleRemoveResources(); } else if (e.getSource() == editResourceButton) { handleEditResource(); } } }; listDoubleClickListener = new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { handleOpenResource(); } }; listKeyListener = new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.DEL) { handleRemoveResources(); } } }; resourcesList = new TreeViewer(parent, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); resourcesList.getTree().setLayoutData(new GridData(GridData.FILL_BOTH)); resourcesList.setContentProvider(new ArrayTreeContentProvider()); resourcesList.setLabelProvider(new ResourcesLabelProvider()); resourcesList.addSelectionChangedListener(selectionChangedListener); resourcesList.addDoubleClickListener(listDoubleClickListener); resourcesList.getTree().addKeyListener(listKeyListener); Composite actionsComp = new Composite(parent, SWT.NONE); actionsComp.setLayout(new GridLayout(3, true)); actionsComp.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER)); addResourcesButton = new Button(actionsComp, SWT.PUSH); addResourcesButton.setText(Messages.ResourcesComposite_add); addResourcesButton.setLayoutData(new GridData(GridData.FILL_BOTH)); addResourcesButton.addSelectionListener(buttonSelectionListener); removeResourcesButton = new Button(actionsComp, SWT.PUSH); removeResourcesButton.setText(Messages.ResourcesComposite_remove); removeResourcesButton.setLayoutData(new GridData(GridData.FILL_BOTH)); removeResourcesButton.addSelectionListener(buttonSelectionListener); editResourceButton = new Button(actionsComp, SWT.PUSH); editResourceButton.setText(Messages.ResourcesComposite_edit); editResourceButton.setLayoutData(new GridData(GridData.FILL_BOTH)); editResourceButton.addSelectionListener(buttonSelectionListener); } /** * @see org.topcased.modeler.documentation.DocPageComposite#refresh() */ protected void refresh() { resourcesList.setInput(null); resourcesList.getTree().setEnabled(getDocumentedElement() != null); addResourcesButton.setEnabled(getDocumentedElement() != null); removeResourcesButton.setEnabled(false); editResourceButton.setEnabled(false); if (getDocumentedElement() != null) { IWorkbenchPart activePart = getActivePart(); IDocumentationPartHandler documentationPartHandler = DocumentionPartHandlerRegistry.getInstance().getDocumentationPartHandler(activePart); if (documentationPartHandler != null) { try { if (documentationPartHandler != null) { EObject associatedDiagram = documentationPartHandler.getAssociatedDiagram(activePart, getDocumentedElement()); EObject toDocument = associatedDiagram == null ? getDocumentedElement() : associatedDiagram; List<URI> resources = documentationPartHandler.getDocumentationManager().getAssociatedResources(toDocument); resourcesList.setInput(resources); } } catch (DocumentationUnsupportedException e) { } } } } protected IDocumentationPartHandler getDocumentationPartHandler(IWorkbenchPart part) { if (getDocumentedElement() != null) { return DocumentionPartHandlerRegistry.getInstance().getDocumentationPartHandler(part); } return null; } protected Command getAddAssociatedResourceCommand(URI uriResource) { IDocumentationPartHandler documentationPartHandler = getDocumentationPartHandler(getActivePart()); if (documentationPartHandler != null) { EObject associatedDiagram = documentationPartHandler.getAssociatedDiagram(getActivePart(), getDocumentedElement()); EObject toDocument = associatedDiagram == null ? getDocumentedElement() : associatedDiagram; IDocumentationManager documentationManager = documentationPartHandler.getDocumentationManager(); if (documentationManager != null) { return documentationManager.getAddAssociatedResourceCommand(toDocument, uriResource); } } return null; } protected Command getRemoveAssociatedResourceCommand(URI uriResource) { IDocumentationPartHandler documentationPartHandler = getDocumentationPartHandler(getActivePart()); if (documentationPartHandler != null) { EObject associatedDiagram = documentationPartHandler.getAssociatedDiagram(getActivePart(), getDocumentedElement()); EObject toDocument = associatedDiagram == null ? getDocumentedElement() : associatedDiagram; IDocumentationManager documentationManager = documentationPartHandler.getDocumentationManager(); if (documentationManager != null) { return documentationManager.getRemoveAssociatedResourceCommand(toDocument, uriResource); } } return null; } private void executeCommand(CompoundCommand compoundCmd) { IWorkbenchPart part = getActivePart(); if (getDocumentationPartHandler(part) != null) { getDocumentationPartHandler(part).executeCommand(part, compoundCmd); } } private void handleResourcesListSelectionChanged() { IStructuredSelection selection = (IStructuredSelection) resourcesList.getSelection(); removeResourcesButton.setEnabled(!selection.isEmpty()); editResourceButton.setEnabled(selection.size() == 1); } private void handleAddResources() { if (getDocumentedElement() != null) { // Get the map of resources to add Set<URI> resourcesToAdd = new HashSet<URI>(); TypedResourcesSelectionDialog dialog = new TypedResourcesSelectionDialog(getShell()); int result = dialog.open(); if (result == Window.OK) { switch (dialog.getType()) { case TypedResourcesSelectionDialog.REMOTE_RESOURCE: RemoteResourceDialog rrDialog = new RemoteResourceDialog(getShell(), "http://"); //$NON-NLS-1$ if (rrDialog.open() == Window.OK) { resourcesToAdd.add(URI.createURI(rrDialog.getValue())); } break; case TypedResourcesSelectionDialog.EXTERNAL_RESOURCE: FileDialog erDialog = new FileDialog(getShell(), SWT.MULTI); if (erDialog.open() != null) { String[] resources = erDialog.getFileNames(); for (int i = 0; i < resources.length; i++) { resourcesToAdd.add(URI.createFileURI(erDialog.getFilterPath() + File.separator + resources[i])); } } break; /* Default case : WORKSPACE_RESOURCE */ default: WorkspaceResourceDialog wrDialog = new WorkspaceResourceDialog(getShell()); result = wrDialog.open(); if (result == Window.OK) { Object[] resources = wrDialog.getResult(); for (int i = 0; i < resources.length; i++) { if (resources[i] instanceof IFile) { resourcesToAdd.add(URI.createPlatformResourceURI(((IFile) resources[i]).getFullPath().toString(), true)); } } } break; } // Execute the add resources command if there are some resources to add CompoundCommand compoundCmd = new CompoundCommand(); for (URI uriResource : resourcesToAdd) { compoundCmd.appendIfCanExecute(getAddAssociatedResourceCommand(uriResource)); } executeCommand(compoundCmd); } } } private void handleRemoveResources() { if (getDocumentedElement() != null) { IStructuredSelection selection = (IStructuredSelection) resourcesList.getSelection(); List<URI> resourcesToRemove = (List<URI>)selection.toList(); // Execute the remove resources command if there are some resources to remove if (!resourcesToRemove.isEmpty()) { if (MessageDialog.openQuestion(getShell(), Messages.ResourcesComposite_resourcesRemoving, Messages.ResourcesComposite_deleteResourcesConfirmation)) { CompoundCommand compoundCmd = new CompoundCommand(); for (URI uriResource : resourcesToRemove) { compoundCmd.appendIfCanExecute(getRemoveAssociatedResourceCommand(uriResource)); } executeCommand(compoundCmd); } } } } private void handleEditResource() { IStructuredSelection selection = (IStructuredSelection) resourcesList.getSelection(); if (selection.size() == 1) { URI uri = (URI)selection.getFirstElement(); URI newUri = null; if (uri != null) { if (uri.isPlatform()) { WorkspaceResourceDialog wrDialog = new WorkspaceResourceDialog(getShell()); wrDialog.setInitialSelections(new IFile[] {ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uri.toPlatformString(true))),}); if (wrDialog.open() == Window.OK) { newUri = URI.createPlatformResourceURI(((IFile) wrDialog.getResult()[0]).getFullPath().toString(), true); } } else if (uri.isFile()) { FileDialog erDialog = new FileDialog(getShell()); erDialog.setFileName(uri.toFileString()); newUri = URI.createFileURI(erDialog.open()); } else { RemoteResourceDialog rrDialog = new RemoteResourceDialog(getShell(), uri.toString()); if (rrDialog.open() == Window.OK) { newUri = URI.createURI(rrDialog.getValue()); } } if (newUri != null) { CompoundCommand compoundCmd = new CompoundCommand(); compoundCmd.appendIfCanExecute(getRemoveAssociatedResourceCommand(uri)); compoundCmd.appendIfCanExecute(getAddAssociatedResourceCommand(uri)); executeCommand(compoundCmd); } } } } private void handleOpenResource() { IStructuredSelection selection = (IStructuredSelection) resourcesList.getSelection(); if (selection.size() == 1) { URI uri = (URI)selection.getFirstElement(); if (uri.isPlatform()) { String platformString = uri.toPlatformString(true); IFile resource = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(platformString)); try { IDE.openEditor(DocViewPlugin.getActivePage(), resource); } catch (PartInitException pie) { displayErrorDialog("Invalid workspace resource", "The workspace resource '" + platformString + "' cannot be opened."); } } else if (uri.isFile()) { String fileString = uri.toFileString(); File resource = new File(fileString); ExternalResourceEditorInput input = new ExternalResourceEditorInput(resource); try { IDE.openEditor(DocViewPlugin.getActivePage(), input, getEditorId(resource)); } catch (PartInitException pie) { displayErrorDialog("Invalid external resource", "The external resource '" + fileString + "' cannot be opened."); } } else { String remoteString = uri.toString(); try { DocViewPlugin.openURL(new URL(remoteString)); } catch (MalformedURLException e) { displayErrorDialog("Invalid remote resource", "The remote resource '" + remoteString + "' cannot be opened."); } } } } private void displayErrorDialog(final String title, final String message) { Display.getDefault().asyncExec(new Runnable() { public void run() { MessageDialog.openError(getShell(), (title == null) ? "Error" : title, (message == null) ? "" : message); //$NON-NLS-1$ } }); } /** * Get the editor id to use to open an external resource.<br> * This method is copied from org.eclipse.ui.internal.editors.text.OpenExternalFileAction * * @param file the external resource file * @return an editor id */ private String getEditorId(File file) { IWorkbench workbench = DocViewPlugin.getDefault().getWorkbench(); IEditorRegistry editorRegistry = workbench.getEditorRegistry(); IEditorDescriptor descriptor = editorRegistry.getDefaultEditor(file.getName(), getContentType(file)); if (descriptor != null) { return descriptor.getId(); } return EditorsUI.DEFAULT_TEXT_EDITOR_ID; } @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); if (resourcesList != null && resourcesList.getControl() != null) { resourcesList.getControl().setEnabled(enabled); } if (this.editResourceButton != null) { this.editResourceButton.setEnabled(enabled); } if (this.removeResourcesButton != null) { this.removeResourcesButton.setEnabled(enabled); } if (this.addResourcesButton != null) { this.addResourcesButton.setEnabled(enabled); } } /** * Return the content type of the given file.<br/> * This method is copied from org.eclipse.ui.internal.editors.text.OpenExternalFileAction * * @param file a file * @return a content type */ private IContentType getContentType(File file) { if (file == null) { return null; } InputStream stream = null; try { stream = new FileInputStream(file); return Platform.getContentTypeManager().findContentTypeFor(stream, file.getName()); } catch (IOException x) { // ModelerPlugin.log(x); return null; } finally { try { if (stream != null) { stream.close(); } } catch (IOException x) { // ModelerPlugin.log(x); } } } /** * A label provider used for the resources list viewer. */ private class ResourcesLabelProvider extends LabelProvider { private WorkbenchLabelProvider wlp = new WorkbenchLabelProvider(); /** * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) */ public String getText(Object element) { if (element instanceof URI) { URI uri = (URI)element; if (uri.isPlatform()) { return uri.toPlatformString(true); } else if (uri.isFile()) { return uri.toFileString(); } else { return uri.toString(); } } return "Unknown resource"; } /** * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object) */ public Image getImage(Object element) { if (element instanceof URI) { URI uri = (URI)element; if (uri.isPlatform()) { IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uri.toPlatformString(true))); return wlp.getImage(iFile); } else if (uri.isFile()) { return DocViewPlugin.getDefault().getImageRegistry().get("EXTERNAL_RESOURCE"); } else { return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE); } } return null; } } /** * A class defining a dialog to add or edit a worksapce resource. */ private class WorkspaceResourceDialog extends ResourceSelectionDialog { /** * Constructor * * @param parentShell */ public WorkspaceResourceDialog(Shell parentShell) { super(parentShell, ResourcesPlugin.getWorkspace().getRoot(), "Please select the workspace resources to add to the documentation."); } } /** * A class defining a dialog to add or edit a remote resource. */ private class RemoteResourceDialog extends InputDialog { /** * Constructor * * @param parentShell * @param initialValue */ public RemoteResourceDialog(Shell parentShell, String initialValue) { super(parentShell, "Remote resource", "Please enter the URL of the remote resource.", initialValue, null); } } }