blob: 8cd5ef5ea313ac29a8d46842a6f84da1869d62ab [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.text;
import org.eclipse.core.runtime.Assert;
import org.eclipse.dltk.internal.ui.editor.EditorUtility;
import org.eclipse.dltk.internal.ui.editor.ScriptSourceViewer;
import org.eclipse.dltk.internal.ui.text.HTMLTextPresenter;
import org.eclipse.dltk.internal.ui.text.ScriptElementProvider;
import org.eclipse.dltk.ruby.internal.ui.text.completion.RubyCompletionProcessor;
import org.eclipse.dltk.ruby.internal.ui.text.completion.RubyContentAssistPreference;
import org.eclipse.dltk.ruby.internal.ui.typehierarchy.RubyHierarchyInformationControl;
import org.eclipse.dltk.ui.CodeFormatterConstants;
import org.eclipse.dltk.ui.text.AbstractScriptScanner;
import org.eclipse.dltk.ui.text.IColorManager;
import org.eclipse.dltk.ui.text.ScriptPresentationReconciler;
import org.eclipse.dltk.ui.text.ScriptSourceViewerConfiguration;
import org.eclipse.dltk.ui.text.SingleTokenScriptScanner;
import org.eclipse.dltk.ui.text.util.AutoEditUtils;
import org.eclipse.dltk.ui.text.util.TabStyle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IAutoEditStrategy;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.information.IInformationPresenter;
import org.eclipse.jface.text.information.IInformationProvider;
import org.eclipse.jface.text.information.InformationPresenter;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.presentation.PresentationReconciler;
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
import org.eclipse.jface.text.rules.ITokenScanner;
import org.eclipse.jface.text.rules.RuleBasedScanner;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.texteditor.ITextEditor;
public class RubySourceViewerConfiguration extends
ScriptSourceViewerConfiguration {
private RubyTextTools fTextTools;
private RubyCodeScanner fCodeScanner;
private AbstractScriptScanner fStringScanner;
private AbstractScriptScanner fCommentScanner;
private AbstractScriptScanner fDocScanner;
public RubySourceViewerConfiguration(IColorManager colorManager,
IPreferenceStore preferenceStore, ITextEditor editor,
String partitioning) {
super(colorManager, preferenceStore, editor, partitioning);
}
public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
return RubyPartitions.RUBY_PARTITION_TYPES;
}
public String[] getIndentPrefixes(ISourceViewer sourceViewer,
String contentType) {
RubyPreferenceInterpreter prefs = new RubyPreferenceInterpreter(this.fPreferenceStore);
if (prefs.getTabStyle() == TabStyle.SPACES)
return new String[] {AutoEditUtils.getNSpaces(prefs.getIndentSize())};
else
return new String[] {"\t"};
// return new String[] { "\t", AutoEditUtils.getNSpaces(prefs.getIndentSize()) };
}
public int getTabWidth(ISourceViewer sourceViewer) {
if (fPreferenceStore == null)
return super.getTabWidth(sourceViewer);
return fPreferenceStore
.getInt(CodeFormatterConstants.FORMATTER_TAB_SIZE);
}
protected void initializeScanners() {
Assert.isTrue(isNewSetup());
fCodeScanner = new RubyCodeScanner(getColorManager(), fPreferenceStore);
fStringScanner = new RubyStringScanner(getColorManager(),
fPreferenceStore);
fCommentScanner = new SingleTokenScriptScanner(getColorManager(),
fPreferenceStore, RubyColorConstants.RUBY_SINGLE_LINE_COMMENT);
fDocScanner = new RubyDocScanner(getColorManager(), fPreferenceStore);
}
/**
* @return <code>true</code> iff the new setup without text tools is in
* use.
*/
private boolean isNewSetup() {
return fTextTools == null;
}
protected RuleBasedScanner getStringScanner() {
return fStringScanner;
}
protected RuleBasedScanner getCommentScanner() {
return fCommentScanner;
}
public IPresentationReconciler getPresentationReconciler(
ISourceViewer sourceViewer) {
PresentationReconciler reconciler = new ScriptPresentationReconciler();
reconciler
.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
DefaultDamagerRepairer dr = new DefaultDamagerRepairer(
this.fCodeScanner);
reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
dr = new DefaultDamagerRepairer(getStringScanner());
reconciler.setDamager(dr, RubyPartitions.RUBY_STRING);
reconciler.setRepairer(dr, RubyPartitions.RUBY_STRING);
dr = new DefaultDamagerRepairer(getDocScanner());
reconciler.setDamager(dr, RubyPartitions.RUBY_DOC);
reconciler.setRepairer(dr, RubyPartitions.RUBY_DOC);
dr = new DefaultDamagerRepairer(getCommentScanner());
reconciler.setDamager(dr, RubyPartitions.RUBY_COMMENT);
reconciler.setRepairer(dr, RubyPartitions.RUBY_COMMENT);
return reconciler;
}
private ITokenScanner getDocScanner() {
return fDocScanner;
}
/**
* Adapts the behavior of the contained components to the change encoded in
* the given event.
* <p>
* Clients are not allowed to call this method if the old setup with text
* tools is in use.
* </p>
*
* @param event
* the event to which to adapt
* @see RubySourceViewerConfiguration#ScriptSourceViewerConfiguration(IColorManager,
* IPreferenceStore, ITextEditor, String)
*/
public void handlePropertyChangeEvent(PropertyChangeEvent event) {
Assert.isTrue(isNewSetup());
if (fCodeScanner.affectsBehavior(event))
fCodeScanner.adaptToPreferenceChange(event);
if (fStringScanner.affectsBehavior(event))
fStringScanner.adaptToPreferenceChange(event);
if (fDocScanner.affectsBehavior(event))
fDocScanner.adaptToPreferenceChange(event);
}
/**
* Determines whether the preference change encoded by the given event
* changes the behavior of one of its contained components.
*
* @param event
* the event to be investigated
* @return <code>true</code> if event causes a behavioral change
*
*/
public boolean affectsTextPresentation(PropertyChangeEvent event) {
return fCodeScanner.affectsBehavior(event)
|| fStringScanner.affectsBehavior(event)
|| fDocScanner.affectsBehavior(event);
}
private IInformationControlCreator getHierarchyPresenterControlCreator(
ISourceViewer sourceViewer) {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
int shellStyle = SWT.RESIZE;
int treeStyle = SWT.V_SCROLL | SWT.H_SCROLL;
return new RubyHierarchyInformationControl(parent, shellStyle,
treeStyle);
}
};
}
public IInformationPresenter getHierarchyPresenter(
ScriptSourceViewer sourceViewer, boolean doCodeResolve) {
// Do not create hierarchy presenter if there's no CU.
if (getEditor() != null
&& getEditor().getEditorInput() != null
&& EditorUtility.getEditorInputModelElement(getEditor(), true) == null)
return null;
InformationPresenter presenter = new InformationPresenter(
getHierarchyPresenterControlCreator(sourceViewer));
presenter
.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
IInformationProvider provider = new ScriptElementProvider(getEditor(),
doCodeResolve);
presenter.setInformationProvider(provider,
IDocument.DEFAULT_CONTENT_TYPE);
presenter.setSizeConstraints(50, 20, true, false);
return presenter;
}
protected boolean isNewLine(IDocument doc, String text) {
String[] delims = doc.getLegalLineDelimiters();
for(int i = 0; i < delims.length; ++i) {
if (delims[i].equals(text)) {
return true;
}
}
return false;
}
public IAutoEditStrategy[] getAutoEditStrategies(
ISourceViewer sourceViewer, String contentType) {
// // TODO: check contentType. think, do we really need it? :)
String partitioning = getConfiguredDocumentPartitioning(sourceViewer);
return new IAutoEditStrategy[] { new RubyAutoEditStrategy(
fPreferenceStore, partitioning) };
}
protected IInformationControlCreator getOutlinePresenterControlCreator(
ISourceViewer sourceViewer, final String commandId) {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
int shellStyle = SWT.RESIZE;
int treeStyle = SWT.V_SCROLL | SWT.H_SCROLL;
return new RubyOutlineInformationControl(parent, shellStyle,
treeStyle, commandId);
}
};
}
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
if (getEditor() != null) {
ContentAssistant assistant = new ContentAssistant();
assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
assistant.setRestoreCompletionProposalSize(getSettings("completion_proposal_size")); //$NON-NLS-1$
assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE);
assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
//assistant.setStatusLineVisible(true);
//assistant.setStatusMessage("Hello!");
IContentAssistProcessor scriptProcessor = new RubyCompletionProcessor(
getEditor(), assistant, IDocument.DEFAULT_CONTENT_TYPE);
assistant.setContentAssistProcessor(scriptProcessor, IDocument.DEFAULT_CONTENT_TYPE);
RubyContentAssistPreference.getDefault().configure(assistant, fPreferenceStore);
return assistant;
}
return null;
}
public IInformationControlCreator getInformationControlCreator(
ISourceViewer sourceViewer) {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, SWT.NONE,
new HTMLTextPresenter(true), "");
}
};
}
protected void initializeQuickOutlineContexts(InformationPresenter presenter,
IInformationProvider provider) {
presenter.setInformationProvider(provider, RubyPartitions.RUBY_COMMENT);
presenter.setInformationProvider(provider, RubyPartitions.RUBY_DOC);
presenter.setInformationProvider(provider, RubyPartitions.RUBY_STRING);
}
}