/*********************************************************************** * Copyright (c) 2009 Anyware Technologies 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: * Jacques Lescot (Anyware Technologies) - initial API and implementation **********************************************************************/ package org.eclipse.papyrus.views.documentation.view; import java.net.MalformedURLException; import java.net.URL; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.window.Window; import org.eclipse.papyrus.views.documentation.DocumentationUnsupportedException; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FillLayout; 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.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; /** * A class defining an composite used to edit the documentation related to a semantic element.<br> * <br> * Created : 11 August 2009<br> * * @author <a href="mailto:jacques.lescot@anyware-tech.com">Jacques LESCOT</a> */ public class CommentsComposite extends DocPageComposite { /** A composite used to edit the documentation using a Rich Text editor */ private RichTextComposite richTextComposite; /** A composite used to edit the documentation using a Plain Text editor */ private PlainTextComposite plainTextComposite; private Button useRichTextEditorButton; private Button editButton; private Composite editorContainer; private FocusListener focusListener; private Text infoText; private static String typeLabel = Messages.CommentsComposite_docCurrent; private static boolean isRichTextEnabled = true; /** * Constructor. * * @param parent the parent composite * @param style the composite style * @param editingDomainProvider the provider of editing domain to execute commands */ public CommentsComposite(Composite parent, int style) { super(parent, style); } /** * @see org.topcased.modeler.documentation.DocPageComposite#createContents(org.eclipse.swt.widgets.Composite) */ protected void createContents(Composite parent) { boolean labelForTypeInformation = (getStyle() & DocPage.STYLE_TEXT_TYPE) != 0; if (labelForTypeInformation) { infoText = new Text(parent, SWT.READ_ONLY); } parent.setLayout(new GridLayout(3, false)); editorContainer = new Composite(parent, SWT.NONE); GridData gData = new GridData(GridData.FILL_BOTH); gData.horizontalSpan = 3; editorContainer.setLayoutData(gData); editorContainer.setLayout(new FillLayout()); if (isRichTextEnabled) { try { Browser browser = new Browser(editorContainer, SWT.NONE); browser.dispose(); } catch (SWTError swtError) { // TODO log // ModelerPlugin.log("None XULRunner installed. You can not use Rich Text Edition.", IStatus.WARNING); isRichTextEnabled = false; } } // Initialize Simple Text Editor by default plainTextComposite = createPlainCommentsComposite(); useRichTextEditorButton = new Button(parent, SWT.CHECK | SWT.RIGHT); useRichTextEditorButton.setText("Use HTML Editor"); useRichTextEditorButton.setImage(DocViewPlugin.getDefault().getImageRegistry().get("HTML_EDITOR")); useRichTextEditorButton.setSelection(false); useRichTextEditorButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { changeEditor(); } }); Label emptyLbl = new Label(parent, SWT.NONE); emptyLbl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); editButton = new Button(parent, SWT.PUSH); editButton.setImage(DocViewPlugin.getDefault().getImageRegistry().get("EDIT")); editButton.setText("Edit"); editButton.setEnabled(useRichTextEditorButton.getSelection()); editButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { RichTextEditorDialog dialog = new RichTextEditorDialog(getShell(), getDocumentationValueFromElement()); if (dialog.open() == Window.OK) { richTextComposite.setDocumentationValue(dialog.getDocumentationValue()); handleDocChanged(); } } }); if (infoText != null) { infoText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); } } /** * @see org.topcased.modeler.documentation.DocPageComposite#refresh() */ protected void refresh() { EObject docElement = getDocumentedElement(); useRichTextEditorButton.setEnabled(docElement != null); if (useRichTextEditorButton.getSelection()) { richTextComposite.setDocumentationValue(""); if (docElement != null) { richTextComposite.setDocumentationValue(getDocumentationValueFromElement()); } } else { plainTextComposite.setDocumentationValue(""); plainTextComposite.getControl().setEnabled(docElement != null); if (docElement != null) { plainTextComposite.setDocumentationValue(getDocumentationValueFromElement()); } } if (infoText != null) { if (docElement != null) { infoText.setText(typeLabel + docElement.eClass().getName()); } else { infoText.setText(""); } } } /** * @return the richTextComposite */ protected RichTextComposite getRichTextComposite() { return richTextComposite; } /** * @return the plainTextComposite */ public PlainTextComposite getPlainTextComposite() { return plainTextComposite; } /** * Change comments editor between simple Text Editor to HTML Text Editor and */ public void changeEditor() { if (!useRichTextEditorButton.getSelection()) { String comment = richTextComposite.getDocumentationValue(); richTextComposite.dispose(); plainTextComposite = createPlainCommentsComposite(); plainTextComposite.setFocus(); plainTextComposite.setDocumentationValue(comment); useRichTextEditorButton.setToolTipText("Use HTML Editor to edit documentation"); useRichTextEditorButton.setSelection(false); editButton.setEnabled(false); } else { if (isRichTextEnabled) { String comment = plainTextComposite.getDocumentationValue(); plainTextComposite.getControl().removeFocusListener(focusListener); plainTextComposite.dispose(); richTextComposite = createRichCommentsComposite(); richTextComposite.setDocumentationValue(comment); useRichTextEditorButton.setToolTipText("Use Text Editor to edit documentation"); useRichTextEditorButton.setSelection(true); editButton.setEnabled(true); editButton.setFocus(); } else { showMessageDialog(); useRichTextEditorButton.setSelection(false); } } editorContainer.layout(); } private void showMessageDialog() { MessageDialog dialog = new MessageDialog(getShell(), "Rich Text Edition unavailable", null, "Your operating system does not support the SWT Browser component, thus you are not able to edit documentation using rich text capabilities.\n" + "You should try installing XULRunner in your environment so that you can enable Rich Text Edition, and then restart your application.\n" + "To install XulRunner, have a look at : <a>http://www.eclipse.org/atf/downloads/base_files/manualXulrunner_section.php</a>.", MessageDialog.WARNING, new String[] {IDialogConstants.OK_LABEL}, 0) { @Override protected Control createMessageArea(Composite composite) { Image image = getImage(); if (image != null) { imageLabel = new Label(composite, SWT.NULL); image.setBackground(imageLabel.getBackground()); imageLabel.setImage(image); GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.BEGINNING).applyTo(imageLabel); } // create message if (message != null) { Link messageLink = new Link(composite, getMessageLabelStyle()); messageLink.setText(message); messageLink.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { try { PlatformUI.getWorkbench().getBrowserSupport().createBrowser(null).openURL(new URL(event.text)); okPressed(); } catch (PartInitException e) { // TODO log } catch (MalformedURLException e) { // TODO log } } }); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).hint(convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH), SWT.DEFAULT).applyTo( messageLink); } return composite; } }; dialog.open(); } /** * Create the Composite used to render the Rich Text Editor * * @return RichTextCommentsComposite */ protected RichTextComposite createRichCommentsComposite() { richTextComposite = new RichTextComposite(editorContainer, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; richTextComposite.setLayout(layout); return richTextComposite; } /** * Create the Composite used to render the Plain text editor * * @return PlainTextComposite */ protected PlainTextComposite createPlainCommentsComposite() { plainTextComposite = new PlainTextComposite(editorContainer, SWT.NONE); focusListener = new FocusAdapter() { private String previousComment; public void focusGained(FocusEvent e) { previousComment = plainTextComposite.getDocumentationValue(); } public void focusLost(FocusEvent e) { if (!plainTextComposite.getDocumentationValue().equals(previousComment)) { handleDocChanged(); } } }; plainTextComposite.getTextControl().addFocusListener(focusListener); return plainTextComposite; } /** * @see org.eclipse.swt.widgets.Composite#setFocus() */ public boolean setFocus() { if (useRichTextEditorButton == null) { return false; } if (useRichTextEditorButton.getSelection()) { return editButton.setFocus(); } if (plainTextComposite == null) { return false; } return plainTextComposite.setFocus(); } /** * Gets the checkbox allowing to use rich text edition * * @return the useRichTextEditorButton */ protected Button getUseRichTextEditorButton() { return useRichTextEditorButton; } /** * Gets the edit button * * @return the edit button */ protected Button getEditButton() { return editButton; } /** * Get the String value of the element to be edited.<br/> * * @return String the documentation text */ protected String getDocumentationValueFromElement() { try { IDocumentationPartHandler documentationPartHandler = DocumentionPartHandlerRegistry.getInstance().getDocumentationPartHandler(getActivePart()); if (documentationPartHandler != null) { EObject associatedDiagram = documentationPartHandler.getAssociatedDiagram(getActivePart(), getDocumentedElement()); EObject toDocument = associatedDiagram == null ? getDocumentedElement() : associatedDiagram; return documentationPartHandler.getDocumentationManager().getDocumentation(toDocument); } } catch (DocumentationUnsupportedException e) { } return ""; //$NON-NLS-1$ } /** * Update documentation text using a Command. */ public void handleDocChanged() { IDocumentationPartHandler documentationPartHandler = DocumentionPartHandlerRegistry.getInstance().getDocumentationPartHandler(getActivePart()); if (documentationPartHandler != null) { String docValue = getUseRichTextEditorButton().getSelection() ? getRichTextComposite().getDocumentationValue() : getPlainTextComposite().getDocumentationValue(); Command cmd = documentationPartHandler.getDocumentationManager().getChangeDocumentationCommand(getDocumentedElement(), docValue); documentationPartHandler.executeCommand(getActivePart(), cmd); } } @Override public void setEnabled(boolean enabled) { if (plainTextComposite != null) { plainTextComposite.setEnabled(enabled); } if (richTextComposite != null) { richTextComposite.setEnabled(enabled); } if (useRichTextEditorButton != null) { useRichTextEditorButton.setEnabled(enabled); } } @Override public void setForeground(Color color) { super.setForeground(color); if (plainTextComposite != null) { plainTextComposite.setForeground(color); } if (richTextComposite != null) { richTextComposite.setForeground(color); } } }