| /******************************************************************************* |
| * 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()); |
| } |
| |
| } |