blob: faf83b67f2f01978a6629d8ca3a2c2aead87948f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 IBM Corporation 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
*
*******************************************************************************/
package org.eclipse.dltk.ruby.internal.ui.editor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.internal.ui.actions.FoldingActionGroup;
import org.eclipse.dltk.internal.ui.editor.DLTKEditorMessages;
import org.eclipse.dltk.internal.ui.editor.ScriptEditor;
import org.eclipse.dltk.internal.ui.editor.ScriptOutlinePage;
import org.eclipse.dltk.internal.ui.editor.ToggleCommentAction;
import org.eclipse.dltk.ruby.core.RubyLanguageToolkit;
import org.eclipse.dltk.ruby.internal.ui.RubyUI;
import org.eclipse.dltk.ruby.internal.ui.text.IRubyPartitions;
import org.eclipse.dltk.ruby.internal.ui.text.RubyPairMatcher;
import org.eclipse.dltk.ruby.internal.ui.text.folding.RubyFoldingStructureProvider;
import org.eclipse.dltk.ui.actions.IScriptEditorActionDefinitionIds;
import org.eclipse.dltk.ui.text.ScriptTextTools;
import org.eclipse.dltk.ui.text.folding.IFoldingStructureProvider;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.source.ICharacterPairMatcher;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import org.eclipse.ui.texteditor.TextOperationAction;
public class RubyEditor extends ScriptEditor {
public static final String EDITOR_ID = "org.eclipse.dltk.ruby.ui.editor.RubyEditor"; //$NON-NLS-1$
public static final String EDITOR_CONTEXT = "#RubyEditorContext"; //$NON-NLS-1$
public static final String RULER_CONTEXT = "#RubyRulerContext"; //$NON-NLS-1$
private org.eclipse.dltk.internal.ui.editor.BracketInserter fBracketInserter = new RubyBracketInserter(
this);
private RubyPairMatcher bracketMatcher = new RubyPairMatcher();
protected void initializeEditor() {
super.initializeEditor();
setEditorContextMenuId(EDITOR_CONTEXT);
setRulerContextMenuId(RULER_CONTEXT);
}
protected IPreferenceStore getScriptPreferenceStore() {
return RubyUI.getDefault().getPreferenceStore();
}
public ScriptTextTools getTextTools() {
return RubyUI.getDefault().getTextTools();
}
protected ScriptOutlinePage doCreateOutlinePage() {
return new RubyOutlinePage(this, RubyUI.getDefault()
.getPreferenceStore());
}
protected void connectPartitioningToElement(IEditorInput input,
IDocument document) {
if (document instanceof IDocumentExtension3) {
IDocumentExtension3 extension = (IDocumentExtension3) document;
if (extension
.getDocumentPartitioner(IRubyPartitions.RUBY_PARTITIONING) == null) {
RubyDocumentSetupParticipant participant = new RubyDocumentSetupParticipant();
participant.setup(document);
}
}
}
private IFoldingStructureProvider fFoldingProvider = null;
protected IFoldingStructureProvider getFoldingStructureProvider() {
if (fFoldingProvider == null) {
fFoldingProvider = new RubyFoldingStructureProvider();
}
return fFoldingProvider;
}
protected FoldingActionGroup createFoldingActionGroup() {
return new FoldingActionGroup(this, getViewer(), RubyUI.getDefault()
.getPreferenceStore());
}
public String getEditorId() {
return EDITOR_ID;
}
public IDLTKLanguageToolkit getLanguageToolkit() {
return RubyLanguageToolkit.getDefault();
}
public String getCallHierarchyID() {
return "org.eclipse.dltk.callhierarchy.view"; //$NON-NLS-1$
}
protected void initializeKeyBindingScopes() {
setKeyBindingScopes(new String[] { "org.eclipse.dltk.ui.rubyEditorScope" }); //$NON-NLS-1$
}
protected void createActions() {
super.createActions();
Action action = new TextOperationAction(DLTKEditorMessages
.getBundleForConstructedKeys(),
"Comment.", this, ITextOperationTarget.PREFIX); //$NON-NLS-1$
action.setActionDefinitionId(IScriptEditorActionDefinitionIds.COMMENT);
setAction("Comment", action); //$NON-NLS-1$
markAsStateDependentAction("Comment", true); //$NON-NLS-1$
action = new TextOperationAction(DLTKEditorMessages
.getBundleForConstructedKeys(),
"Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); //$NON-NLS-1$
action
.setActionDefinitionId(IScriptEditorActionDefinitionIds.UNCOMMENT);
setAction("Uncomment", action); //$NON-NLS-1$
markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$
action = new ToggleCommentAction(DLTKEditorMessages
.getBundleForConstructedKeys(), "ToggleComment.", this); //$NON-NLS-1$
action
.setActionDefinitionId(IScriptEditorActionDefinitionIds.TOGGLE_COMMENT);
setAction("ToggleComment", action); //$NON-NLS-1$
markAsStateDependentAction("ToggleComment", true); //$NON-NLS-1$
ISourceViewer sourceViewer = getSourceViewer();
SourceViewerConfiguration configuration = getSourceViewerConfiguration();
((ToggleCommentAction) action).configure(sourceViewer, configuration);
}
public void createPartControl(Composite parent) {
super.createPartControl(parent);
boolean closeBrackets = true;
boolean closeStrings = true;
boolean closeAngularBrackets = false;
fBracketInserter.setCloseBracketsEnabled(closeBrackets);
fBracketInserter.setCloseStringsEnabled(closeStrings);
fBracketInserter.setCloseAngularBracketsEnabled(closeAngularBrackets);
ISourceViewer sourceViewer = getSourceViewer();
if (sourceViewer instanceof ITextViewerExtension)
((ITextViewerExtension) sourceViewer)
.prependVerifyKeyListener(fBracketInserter);
}
private static ListenerList doSetInputListeners = new ListenerList();
public static void addListener(IRubyEditorListener listener) {
doSetInputListeners.add(listener);
}
public static void removeListener(IRubyEditorListener listener) {
doSetInputListeners.remove(listener);
}
protected void notifyDoSetInput(IModelElement element) {
Object[] listeners2 = doSetInputListeners.getListeners();
for (int i = 0; i < listeners2.length; i++) {
IRubyEditorListener listener = (IRubyEditorListener) listeners2[i];
if (listener != null) {
listener.notifyDoSetInput(element);
}
}
}
protected void doSetInput(IEditorInput input) throws CoreException {
super.doSetInput(input);
IModelElement element = getInputModelElement();
if (element != null) {
notifyDoSetInput(element);
}
}
public void dispose() {
ISourceViewer sourceViewer = getSourceViewer();
if (sourceViewer instanceof ITextViewerExtension)
((ITextViewerExtension) sourceViewer)
.removeVerifyKeyListener(fBracketInserter);
super.dispose();
}
protected void configureSourceViewerDecorationSupport(
SourceViewerDecorationSupport support) {
support.setCharacterPairMatcher(bracketMatcher);
support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS,
MATCHING_BRACKETS_COLOR);
super.configureSourceViewerDecorationSupport(support);
}
/**
* Jumps to the matching bracket.
*/
public void gotoMatchingBracket() {
ISourceViewer sourceViewer = getSourceViewer();
IDocument document = sourceViewer.getDocument();
if (document == null)
return;
IRegion selection = getSignedSelection(sourceViewer);
int selectionLength = Math.abs(selection.getLength());
if (selectionLength > 1) {
setStatusLineErrorMessage(Messages.RubyEditor_nobracketSelected);
sourceViewer.getTextWidget().getDisplay().beep();
return;
}
// #26314
int sourceCaretOffset = selection.getOffset() + selection.getLength();
if (isSurroundedByBrackets(document, sourceCaretOffset))
sourceCaretOffset -= selection.getLength();
IRegion region = bracketMatcher.match(document, sourceCaretOffset);
if (region == null) {
setStatusLineErrorMessage(Messages.RubyEditor_noMatchingBracketFound);
sourceViewer.getTextWidget().getDisplay().beep();
return;
}
int offset = region.getOffset();
int length = region.getLength();
if (length < 1)
return;
int anchor = bracketMatcher.getAnchor();
// http://dev.eclipse.org/bugs/show_bug.cgi?id=34195
int targetOffset = (ICharacterPairMatcher.RIGHT == anchor) ? offset + 1
: offset + length;
boolean visible = false;
if (sourceViewer instanceof ITextViewerExtension5) {
ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
} else {
IRegion visibleRegion = sourceViewer.getVisibleRegion();
// http://dev.eclipse.org/bugs/show_bug.cgi?id=34195
visible = (targetOffset >= visibleRegion.getOffset() && targetOffset <= visibleRegion
.getOffset()
+ visibleRegion.getLength());
}
if (!visible) {
setStatusLineErrorMessage(Messages.RubyEditor_matchingBracketIsOutsideSelectedElement);
sourceViewer.getTextWidget().getDisplay().beep();
return;
}
if (selection.getLength() < 0)
targetOffset -= selection.getLength();
sourceViewer.setSelectedRange(targetOffset, selection.getLength());
sourceViewer.revealRange(targetOffset, selection.getLength());
}
}