package org.rubypeople.rdt.ui.text; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import org.eclipse.core.runtime.Preferences; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentExtension3; import org.eclipse.jface.text.IDocumentPartitioner; import org.eclipse.jface.text.rules.FastPartitioner; import org.eclipse.jface.text.rules.IPartitionTokenScanner; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditorPreferences; import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants; import org.rubypeople.rdt.internal.ui.text.MergingPartitionScanner; import org.rubypeople.rdt.internal.ui.text.RubyColorManager; import org.rubypeople.rdt.internal.ui.text.RubyPartitionScanner; import org.rubypeople.rdt.internal.ui.text.ruby.AbstractRubyScanner; import org.rubypeople.rdt.internal.ui.text.ruby.AbstractRubyTokenScanner; import org.rubypeople.rdt.internal.ui.text.ruby.RubyCommentScanner; import org.rubypeople.rdt.internal.ui.text.ruby.RubyColoringTokenScanner; import org.rubypeople.rdt.internal.ui.text.ruby.SingleTokenRubyScanner; public class RubyTextTools { /** * This tools' preference listener. */ private class PreferenceListener implements IPropertyChangeListener, Preferences.IPropertyChangeListener { public void propertyChange(PropertyChangeEvent event) { adaptToPreferenceChange(event); } public void propertyChange(Preferences.PropertyChangeEvent event) { adaptToPreferenceChange(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event.getNewValue())); } } protected static String[] keywords; protected RubyColorManager fColorManager; protected IPartitionTokenScanner partitionScanner; protected AbstractRubyTokenScanner fCodeScanner; protected AbstractRubyScanner fMultilineCommentScanner, fSinglelineCommentScanner, FStringScanner; private IPreferenceStore fPreferenceStore; private Preferences fCorePreferenceStore; /** The preference change listener */ private PreferenceListener fPreferenceListener = new PreferenceListener(); /** * Creates a new Ruby text tools collection. * * @param store the preference store to initialize the text tools. The text tool * instance installs a listener on the passed preference store to adapt itself to * changes in the preference store. In general <code>PreferenceConstants. * getPreferenceStore()</code> should be used to initialize the text tools. * @see org.rubypeople.rdt.ui.PreferenceConstants#getPreferenceStore() * @since 2.0 */ public RubyTextTools(IPreferenceStore store) { this(store, null, true); } /** * Creates a new Ruby text tools collection. * * @param store * the preference store to initialize the text tools. The text * tool instance installs a listener on the passed preference * store to adapt itself to changes in the preference store. In * general <code>PreferenceConstants. * getPreferenceStore()</code> * should be used to initialize the text tools. * @param coreStore * optional preference store to initialize the text tools. The * text tool instance installs a listener on the passed * preference store to adapt itself to changes in the preference * store. * @see org.rubypeople.rdt.ui.PreferenceConstants#getPreferenceStore() * @since 2.1 */ public RubyTextTools(IPreferenceStore store, Preferences coreStore) { this(store, coreStore, true); } /** * Creates a new Ruby text tools collection. * * @param store * the preference store to initialize the text tools. The text * tool instance installs a listener on the passed preference * store to adapt itself to changes in the preference store. In * general <code>PreferenceConstants. * getPreferenceStore()</code> * should be used to initialize the text tools. * @param coreStore * optional preference store to initialize the text tools. The * text tool instance installs a listener on the passed * preference store to adapt itself to changes in the preference * store. * @param autoDisposeOnDisplayDispose * if <code>true</code> the color manager automatically * disposes all managed colors when the current display gets * disposed and all calls to * {@link org.eclipse.jface.text.source.ISharedTextColors#dispose()} * are ignored. * @see org.rubypeople.rdt.ui.PreferenceConstants#getPreferenceStore() * @since 2.1 */ public RubyTextTools(IPreferenceStore store, Preferences coreStore, boolean autoDisposeOnDisplayDispose) { super(); fColorManager = new RubyColorManager(autoDisposeOnDisplayDispose); partitionScanner = new MergingPartitionScanner(); fCodeScanner = new RubyColoringTokenScanner(fColorManager, store); fMultilineCommentScanner = new RubyCommentScanner(fColorManager, store, coreStore, IRubyColorConstants.RUBY_MULTI_LINE_COMMENT); fSinglelineCommentScanner = new RubyCommentScanner(fColorManager, store, coreStore, IRubyColorConstants.RUBY_SINGLE_LINE_COMMENT); FStringScanner = new SingleTokenRubyScanner(fColorManager, store, IRubyColorConstants.RUBY_STRING); fPreferenceStore = store; fPreferenceStore.addPropertyChangeListener(fPreferenceListener); fCorePreferenceStore = coreStore; if (fCorePreferenceStore != null) fCorePreferenceStore.addPropertyChangeListener(fPreferenceListener); } /** * Adapts the behavior of the contained components to the change encoded in * the given event. * * @param event * the event to which to adapt * @since 2.0 * @deprecated As of 3.0, no replacement */ protected void adaptToPreferenceChange(PropertyChangeEvent event) { if (fCodeScanner.affectsBehavior(event)) fCodeScanner.adaptToPreferenceChange(event); if (fMultilineCommentScanner.affectsBehavior(event)) fMultilineCommentScanner.adaptToPreferenceChange(event); if (fSinglelineCommentScanner.affectsBehavior(event)) fSinglelineCommentScanner.adaptToPreferenceChange(event); if (FStringScanner.affectsBehavior(event)) FStringScanner.adaptToPreferenceChange(event); } public IDocumentPartitioner createDocumentPartitioner() { return new FastPartitioner(getPartitionScanner(), RubyPartitionScanner.LEGAL_CONTENT_TYPES); } protected IPartitionTokenScanner getPartitionScanner() { return partitionScanner; } public IPreferenceStore getPreferenceStore() { return RubyPlugin.getDefault().getPreferenceStore(); } public static String[] getKeyWords() { if (keywords == null) { String csvKeywords = RubyEditorPreferences.getString("keywords"); List keywordList = new ArrayList(); StringTokenizer tokenizer = new StringTokenizer(csvKeywords, ","); while (tokenizer.hasMoreTokens()) keywordList.add(tokenizer.nextToken()); keywords = new String[keywordList.size()]; keywordList.toArray(keywords); } return keywords; } public boolean affectsTextPresentation(PropertyChangeEvent event) { return fCodeScanner.affectsBehavior(event) || fMultilineCommentScanner.affectsBehavior(event) || fSinglelineCommentScanner.affectsBehavior(event) || FStringScanner.affectsBehavior(event); } /** * Sets up the Ruby document partitioner for the given document for the * given partitioning. * * @param document * the document to be set up * @param partitioning * the document partitioning * @since 3.0 */ public void setupRubyDocumentPartitioner(IDocument document, String partitioning) { IDocumentPartitioner partitioner = createDocumentPartitioner(); if (document instanceof IDocumentExtension3) { IDocumentExtension3 extension3 = (IDocumentExtension3) document; extension3.setDocumentPartitioner(partitioning, partitioner); } else { document.setDocumentPartitioner(partitioner); } partitioner.connect(document); } /** * Disposes all the individual tools of this tools collection. */ public void dispose() { fCodeScanner = null; fMultilineCommentScanner = null; fSinglelineCommentScanner = null; // fJavaDocScanner= null; partitionScanner = null; if (fColorManager != null) { fColorManager.dispose(); fColorManager = null; } if (fPreferenceStore != null) { fPreferenceStore.removePropertyChangeListener(fPreferenceListener); fPreferenceStore = null; if (fCorePreferenceStore != null) { fCorePreferenceStore.removePropertyChangeListener(fPreferenceListener); fCorePreferenceStore = null; } fPreferenceListener = null; } } /** * Returns the color manager which is used to manage any Ruby-specific * colors needed for such things like syntax highlighting. * <p> * Clients which are only interested in the color manager of the Ruby UI * plug-in should use {@link org.rubypeople.rdt.ui.RubyUI#getColorManager()}. * </p> * * @return the color manager to be used for Ruby text viewers * @see org.rubypeople.rdt.ui.RubyUI#getColorManager() */ public IColorManager getColorManager() { return fColorManager; } /** * Returns this text tool's core preference store. * * @return the core preference store * @since 0.8.0 */ public Preferences getCorePreferenceStore() { return fCorePreferenceStore; } /** * Sets up the Ruby document partitioner for the given document for the * default partitioning. * * @param document * the document to be set up * @since 0.8.0 */ public void setupRubyDocumentPartitioner(IDocument document) { setupRubyDocumentPartitioner(document, IDocumentExtension3.DEFAULT_PARTITIONING); } }