/*****************************************************************************
* Copyright (c) 2008 CEA LIST.
*
*
* 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:
* Remi Schnekenburger (CEA LIST) remi.schnekenburger@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.extensionpoints.editors.ui;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.commands.Command;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.papyrus.extensionpoints.editors.configuration.IDirectEditorConfiguration;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.editors.text.TextEditor;
/**
* Main class for embedded editors.
*/
public class EmbeddedTextEditor extends TextEditor {
/** Close listener for this embedded editor */
protected CloseListener closeListener;
/** save site selection provider( bug with multi-page editor...) */
private ISelectionProvider provider;
/** editor configuration */
private final IDirectEditorConfiguration directEditorConfiguration;
/** nested editor command stack */
private final DiagramCommandStack diagramCommandStack;
/** transactional editing domain from the backbone */
private final TransactionalEditingDomain transactionalEditingDomain;
/**
* Creates a new EmbeddedTextEditor.
*/
public EmbeddedTextEditor(IDirectEditorConfiguration directEditorConfiguration, DiagramCommandStack diagramCommandStack, TransactionalEditingDomain transactionalEditingDomain) {
super();
this.directEditorConfiguration = directEditorConfiguration;
this.diagramCommandStack = diagramCommandStack;
this.transactionalEditingDomain = transactionalEditingDomain;
initialiseSourceViewerConfiguration();
initialiseDocumentProvider();
}
/**
* Returns the configuration for this editor
*
* @return the configuration for this editor
*/
public IDirectEditorConfiguration getDirectEditorConfiguration() {
return directEditorConfiguration;
}
private void initialiseCompletionListener(SourceViewer sourceViewer) {
sourceViewer.prependVerifyKeyListener(new LabelKeyListener(sourceViewer));
sourceViewer.getControl().addTraverseListener(new ControlListener(sourceViewer));
}
/**
* Sets the source viewer configuration for this editor
*/
protected void initialiseSourceViewerConfiguration() {
setSourceViewerConfiguration(directEditorConfiguration.getSourceViewerConfiguration());
}
/**
* Sets the document provider for this editor
*/
protected void initialiseDocumentProvider() {
setDocumentProvider(new EmbeddedEditorDocumentProvider(this));
}
/**
* Adds a close listener to the editor, i.e. when the editor should be closed
*/
// @unused
public void setCloseListener(CloseListener closeListener) {
this.closeListener = closeListener;
}
/**
* {@inheritDoc}
*/
@Override
public void close(boolean save) {
// restore saved previous provider
getSite().setSelectionProvider(provider);
closeListener.close();
if(save) {
// get command stack of the 'parent' editor
Command command = new ICommandProxy(new AbstractTransactionalCommand(transactionalEditingDomain, "Edit property", null) {
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
return CommandResult.newOKCommandResult(((EmbeddedEditorDocumentProvider)getDocumentProvider()).applyChanges(getEditorInput()));
}
});
diagramCommandStack.execute(command, new NullProgressMonitor());
}
super.close(false);
}
/**
* {@inheritDoc}
*/
@Override
protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
// overrides styles
fAnnotationAccess = getAnnotationAccess();
fOverviewRuler = createOverviewRuler(getSharedColors());
SourceViewer viewer = new SourceViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), SWT.FULL_SELECTION | SWT.BORDER);
// ensure decoration support has been created and configured.
getSourceViewerDecorationSupport(viewer);
initialiseCompletionListener(viewer);
return viewer;
}
/**
* {@inheritDoc}
*/
@Override
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
provider = site.getSelectionProvider();
super.init(site, input);
}
/**
* Listener to process completion
*/
private class LabelKeyListener implements VerifyKeyListener {
/**
* the viewer to listen
*/
SourceViewer viewer;
/**
* Default constructor.
*
* @param viewer
* the viewer to listen
*/
public LabelKeyListener(SourceViewer viewer) {
this.viewer = viewer;
}
/**
* {@inheritDoc}
*/
public void verifyKey(VerifyEvent event) {
if(event.stateMask == SWT.CTRL) {
switch(event.character) {
case ' ':
callOperation(event, ISourceViewer.CONTENTASSIST_PROPOSALS);
break;
case '1':
callOperation(event, ISourceViewer.QUICK_ASSIST);
break;
// case 'c':
// callOperation(event, SourceViewer.COPY);
// break;
// case 'x':
// callOperation(event, SourceViewer.CUT);
// break;
// case 'v':
// callOperation(event, SourceViewer.PASTE);
// break;
// case 'y':
// callOperation(event, SourceViewer.REDO);
// break;
default:
// no success using key event 'z' or 'y' : using keycode
// instead...
switch(event.keyCode) {
case 122: // z
callOperation(event, ITextOperationTarget.UNDO);
break;
case 121: // y
callOperation(event, ITextOperationTarget.REDO);
break;
default:
break;
}
}
} else if(event.character == SWT.CR) {
EmbeddedTextEditor.this.close(true);
event.doit = false;
} else if(event.character == SWT.DEL) {
if(viewer.canDoOperation(ITextOperationTarget.DELETE)) {
viewer.doOperation(ITextOperationTarget.DELETE);
}
}
}
/**
* Try to call the specified operation on the viewer
*
* @param event
* the event to check
* @param code
* the code of the operation to call
*/
private void callOperation(VerifyEvent event, int code) {
if(viewer.canDoOperation(code)) {
viewer.doOperation(code);
}
event.doit = false;
}
}
/**
* Listener to process completion
*/
private class ControlListener implements TraverseListener {
/**
* the viewer to listen
*/
SourceViewer viewer;
/**
* Default constructor.
*
* @param viewer
* the viewer to listen
*/
public ControlListener(SourceViewer viewer) {
this.viewer = viewer;
}
/**
* {@inheritDoc}
*/
public void keyTraversed(TraverseEvent e) {
EmbeddedTextEditor.this.closeListener.keyTraversed(e);
}
}
}