|
From: Christopher W. <caw...@us...> - 2006-04-12 21:26:30
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25379/src/org/rubypeople/rdt/internal/ui/rubyeditor Modified Files: RubyAbstractEditor.java EditorUtility.java RubyEditor.java Log Message: a number of changes: - Re-arrange the preferences - add ability to edit ruby editor font - whole new syntax coloring page - new underline/strikethrough options for syntax coloring - fix bug delaying preference changes from applying on syntax coloring to open editors. - Add hyperlink between syntax coloring and general text editor prefs (which apply to coloring/fonts/appearance) - Remove some deprecated code Index: RubyEditor.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java,v retrieving revision 1.41 retrieving revision 1.42 diff -C2 -d -r1.41 -r1.42 *** RubyEditor.java 8 Apr 2006 05:40:06 -0000 1.41 --- RubyEditor.java 12 Apr 2006 21:26:25 -0000 1.42 *************** *** 63,68 **** --- 63,71 ---- import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IPageLayout; + import org.eclipse.ui.IPartListener2; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchPage; + import org.eclipse.ui.IWorkbenchPartReference; + import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.SelectionEnabler; import org.eclipse.ui.actions.ActionContext; *************** *** 134,137 **** --- 137,146 ---- private IMarker fLastMarkerTarget = null; + /** + * The folding runner. + * @since 0.9.0 + */ + private ToggleFoldingRunner fFoldingRunner; + /** The editor's bracket matcher */ protected RubyPairMatcher fBracketMatcher= new RubyPairMatcher(BRACKETS); *************** *** 639,642 **** --- 648,676 ---- } } + + ISourceViewer sourceViewer= getSourceViewer(); + if (sourceViewer == null) + return; + + if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) { + if (sourceViewer instanceof ProjectionViewer) { + ProjectionViewer projectionViewer= (ProjectionViewer) sourceViewer; + if (fProjectionModelUpdater != null) + fProjectionModelUpdater.uninstall(); + // either freshly enabled or provider changed + fProjectionModelUpdater= RubyPlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider(); + if (fProjectionModelUpdater != null) { + fProjectionModelUpdater.install(this, projectionViewer); + } + } + return; + } + + if (PreferenceConstants.EDITOR_FOLDING_ENABLED.equals(property)) { + if (sourceViewer instanceof ProjectionViewer) { + new ToggleFoldingRunner().runWhenNextVisible(); + } + return; + } } *************** *** 1244,1246 **** --- 1278,1380 ---- return false; } + + /** + * Runner that will toggle folding either instantly (if the editor is + * visible) or the next time it becomes visible. If a runner is started when + * there is already one registered, the registered one is canceled as + * toggling folding twice is a no-op. + * <p> + * The access to the fFoldingRunner field is not thread-safe, it is assumed + * that <code>runWhenNextVisible</code> is only called from the UI thread. + * </p> + * + * @since 0.9.0 + */ + private final class ToggleFoldingRunner implements IPartListener2 { + /** + * The workbench page we registered the part listener with, or + * <code>null</code>. + */ + private IWorkbenchPage fPage; + + /** + * Does the actual toggling of projection. + */ + private void toggleFolding() { + ISourceViewer sourceViewer= getSourceViewer(); + if (sourceViewer instanceof ProjectionViewer) { + ProjectionViewer pv= (ProjectionViewer) sourceViewer; + if (pv.isProjectionMode() != isFoldingEnabled()) { + if (pv.canDoOperation(ProjectionViewer.TOGGLE)) + pv.doOperation(ProjectionViewer.TOGGLE); + } + } + } + + /** + * Makes sure that the editor's folding state is correct the next time + * it becomes visible. If it already is visible, it toggles the folding + * state. If not, it either registers a part listener to toggle folding + * when the editor becomes visible, or cancels an already registered + * runner. + */ + public void runWhenNextVisible() { + // if there is one already: toggling twice is the identity + if (fFoldingRunner != null) { + fFoldingRunner.cancel(); + return; + } + IWorkbenchPartSite site= getSite(); + if (site != null) { + IWorkbenchPage page= site.getPage(); + if (!page.isPartVisible(RubyEditor.this)) { + // if we're not visible - defer until visible + fPage= page; + fFoldingRunner= this; + page.addPartListener(this); + return; + } + } + // we're visible - run now + toggleFolding(); + } + + /** + * Remove the listener and clear the field. + */ + private void cancel() { + if (fPage != null) { + fPage.removePartListener(this); + fPage= null; + } + if (fFoldingRunner == this) + fFoldingRunner= null; + } + + /* + * @see org.eclipse.ui.IPartListener2#partVisible(org.eclipse.ui.IWorkbenchPartReference) + */ + public void partVisible(IWorkbenchPartReference partRef) { + if (RubyEditor.this.equals(partRef.getPart(false))) { + cancel(); + toggleFolding(); + } + } + + /* + * @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference) + */ + public void partClosed(IWorkbenchPartReference partRef) { + if (RubyEditor.this.equals(partRef.getPart(false))) { + cancel(); + } + } + + public void partActivated(IWorkbenchPartReference partRef) {} + public void partBroughtToTop(IWorkbenchPartReference partRef) {} + public void partDeactivated(IWorkbenchPartReference partRef) {} + public void partOpened(IWorkbenchPartReference partRef) {} + public void partHidden(IWorkbenchPartReference partRef) {} + public void partInputChanged(IWorkbenchPartReference partRef) {} + } } \ No newline at end of file Index: RubyAbstractEditor.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** RubyAbstractEditor.java 25 Mar 2006 02:37:44 -0000 1.24 --- RubyAbstractEditor.java 12 Apr 2006 21:26:25 -0000 1.25 *************** *** 1,11 **** --- 1,18 ---- package org.rubypeople.rdt.internal.ui.rubyeditor; + import java.util.ArrayList; import java.util.Iterator; + import java.util.List; + import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; + import org.eclipse.core.runtime.preferences.IEclipsePreferences; + import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.TextSelection; import org.eclipse.jface.text.source.ISourceViewer; + import org.eclipse.jface.util.IPropertyChangeListener; + import org.eclipse.jface.util.ListenerList; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelection; *************** *** 14,17 **** --- 21,26 ---- import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.custom.StyledText; + import org.eclipse.swt.graphics.Point; + import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IPartService; *************** *** 20,35 **** --- 29,51 ---- import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextEditor; + import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.eclipse.ui.texteditor.ChainedPreferenceStore; import org.eclipse.ui.views.contentoutline.ContentOutline; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; + import org.osgi.service.prefs.BackingStoreException; import org.rubypeople.rdt.core.IImportContainer; import org.rubypeople.rdt.core.IImportDeclaration; import org.rubypeople.rdt.core.IMember; import org.rubypeople.rdt.core.IRubyElement; + import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.ISourceRange; import org.rubypeople.rdt.core.ISourceReference; + import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.RubyModelException; + import org.rubypeople.rdt.core.formatter.DefaultCodeFormatterConstants; import org.rubypeople.rdt.internal.ui.RubyPlugin; + import org.rubypeople.rdt.internal.ui.text.IRubyPartitions; + import org.rubypeople.rdt.internal.ui.text.PreferencesAdapter; import org.rubypeople.rdt.ui.IWorkingCopyManager; import org.rubypeople.rdt.ui.text.RubySourceViewerConfiguration; *************** *** 47,56 **** protected AbstractSelectionChangedListener fOutlineSelectionChangedListener = new OutlineSelectionChangedListener(); private RubyOutlinePage fOutlinePage; ! private IPreferenceStore createCombinedPreferenceStore() { ! IPreferenceStore rdtStore = RubyPlugin.getDefault().getPreferenceStore(); ! IPreferenceStore generalTextStore = EditorsUI.getPreferenceStore(); ! return new ChainedPreferenceStore(new IPreferenceStore[] { rdtStore, generalTextStore}); ! } /** --- 63,89 ---- protected AbstractSelectionChangedListener fOutlineSelectionChangedListener = new OutlineSelectionChangedListener(); private RubyOutlinePage fOutlinePage; + + /** + * Creates and returns the preference store for this Ruby editor with the given input. + * + * @param input The editor input for which to create the preference store + * @return the preference store for this editor + * + * @since 0.9.0 + */ + private IPreferenceStore createCombinedPreferenceStore(IEditorInput input) { + List stores= new ArrayList(3); ! IRubyProject project= EditorUtility.getRubyProject(input); ! if (project != null) { ! stores.add(new EclipsePreferencesAdapter(new ProjectScope(project.getProject()), RubyCore.PLUGIN_ID)); ! } ! ! stores.add(RubyPlugin.getDefault().getPreferenceStore()); ! stores.add(new PreferencesAdapter(RubyCore.getPlugin().getPluginPreferences())); ! stores.add(EditorsUI.getPreferenceStore()); ! ! return new ChainedPreferenceStore((IPreferenceStore[]) stores.toArray(new IPreferenceStore[stores.size()])); ! } /** *************** *** 77,85 **** protected void initializeEditor() { super.initializeEditor(); ! setPreferenceStore(this.createCombinedPreferenceStore()); ! ! textTools = RubyPlugin.getDefault().getRubyTextTools(); ! setSourceViewerConfiguration(new RubySourceViewerConfiguration(textTools, this)); } /* --- 110,132 ---- protected void initializeEditor() { super.initializeEditor(); ! IPreferenceStore store= createCombinedPreferenceStore(null); ! setPreferenceStore(store); ! RubyTextTools textTools= RubyPlugin.getDefault().getRubyTextTools(); ! setSourceViewerConfiguration(new RubySourceViewerConfiguration(textTools.getColorManager(), store, this, IRubyPartitions.RUBY_PARTITIONING)); } + + /* + * @see org.eclipse.ui.texteditor.AbstractTextEditor#setPreferenceStore(org.eclipse.jface.preference.IPreferenceStore) + * @since 0.9.0 + */ + protected void setPreferenceStore(IPreferenceStore store) { + super.setPreferenceStore(store); + if (getSourceViewerConfiguration() instanceof RubySourceViewerConfiguration) { + RubyTextTools textTools= RubyPlugin.getDefault().getRubyTextTools(); + setSourceViewerConfiguration(new RubySourceViewerConfiguration(textTools.getColorManager(), store, this, IRubyPartitions.RUBY_PARTITIONING)); + } + if (getSourceViewer() instanceof RubySourceViewer) + ((RubySourceViewer)getSourceViewer()).setPreferenceStore(store); + } /* *************** *** 125,128 **** --- 172,225 ---- } } + + protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { + + String property= event.getProperty(); + + if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) { + /* + * Ignore tab setting since we rely on the formatter preferences. + * We do this outside the try-finally block to avoid that EDITOR_TAB_WIDTH + * is handled by the sub-class (AbstractDecoratedTextEditor). + */ + return; + } + + try { + + ISourceViewer sourceViewer= getSourceViewer(); + if (sourceViewer == null) + return; + + ((RubySourceViewerConfiguration)getSourceViewerConfiguration()).handlePropertyChangeEvent(event); + + if (DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE.equals(property) + || DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE.equals(property) + || DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR.equals(property)) { + StyledText textWidget= sourceViewer.getTextWidget(); + int tabWidth= getSourceViewerConfiguration().getTabWidth(sourceViewer); + if (textWidget.getTabs() != tabWidth) + textWidget.setTabs(tabWidth); + return; + } + + } finally { + super.handlePreferenceStoreChanged(event); + } + + if (AbstractDecoratedTextEditorPreferenceConstants.SHOW_RANGE_INDICATOR.equals(property)) { + // superclass already installed the range indicator + Object newValue= event.getNewValue(); + ISourceViewer viewer= getSourceViewer(); + if (newValue != null && viewer != null) { + if (Boolean.valueOf(newValue.toString()).booleanValue()) { + // adjust the highlightrange in order to get the magnet right after changing the selection + Point selection= viewer.getSelectedRange(); + adjustHighlightRange(selection.x, selection.y); + } + } + + } + } protected void handleOutlinePageSelection(SelectionChangedEvent event) { *************** *** 308,312 **** protected boolean affectsTextPresentation(PropertyChangeEvent event) { ! return textTools.affectsTextPresentation(event); } --- 405,409 ---- protected boolean affectsTextPresentation(PropertyChangeEvent event) { ! return ((RubySourceViewerConfiguration)getSourceViewerConfiguration()).affectsTextPresentation(event) || super.affectsTextPresentation(event); } *************** *** 390,392 **** --- 487,786 ---- protected abstract IRubyElement getElementAt(int offset); + /** + * Adapts an options {@link IEclipsePreferences} to {@link org.eclipse.jface.preference.IPreferenceStore}. + * <p> + * This preference store is read-only i.e. write access + * throws an {@link java.lang.UnsupportedOperationException}. + * </p> + * + * @since 3.1 + */ + private static class EclipsePreferencesAdapter implements IPreferenceStore { + + /** + * Preference change listener. Listens for events preferences + * fires a {@link org.eclipse.jface.util.PropertyChangeEvent} + * on this adapter with arguments from the received event. + */ + private class PreferenceChangeListener implements IEclipsePreferences.IPreferenceChangeListener { + + /** + * {@inheritDoc} + */ + public void preferenceChange(final IEclipsePreferences.PreferenceChangeEvent event) { + if (Display.getCurrent() == null) { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + firePropertyChangeEvent(event.getKey(), event.getOldValue(), event.getNewValue()); + } + }); + } else { + firePropertyChangeEvent(event.getKey(), event.getOldValue(), event.getNewValue()); + } + } + } + + // TODO When we move to Eclipse 3.2 change ListenerList to eclipse.core.runtime.ListenerList + /** Listeners on on this adapter */ + private ListenerList fListeners= new ListenerList(); + + /** Listener on the node */ + private IEclipsePreferences.IPreferenceChangeListener fListener= new PreferenceChangeListener(); + + /** wrapped node */ + private final IScopeContext fContext; + private final String fQualifier; + + /** + * Initialize with the node to wrap + * + * @param context The context to access + */ + public EclipsePreferencesAdapter(IScopeContext context, String qualifier) { + fContext= context; + fQualifier= qualifier; + } + + private IEclipsePreferences getNode() { + return fContext.getNode(fQualifier); + } + + /** + * {@inheritDoc} + */ + public void addPropertyChangeListener(IPropertyChangeListener listener) { + if (fListeners.size() == 0) + getNode().addPreferenceChangeListener(fListener); + fListeners.add(listener); + } + + /** + * {@inheritDoc} + */ + public void removePropertyChangeListener(IPropertyChangeListener listener) { + fListeners.remove(listener); + if (fListeners.size() == 0) { + getNode().removePreferenceChangeListener(fListener); + } + } + + /** + * {@inheritDoc} + */ + public boolean contains(String name) { + return getNode().get(name, null) != null; + } + + /** + * {@inheritDoc} + */ + public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) { + PropertyChangeEvent event= new PropertyChangeEvent(this, name, oldValue, newValue); + Object[] listeners= fListeners.getListeners(); + for (int i= 0; i < listeners.length; i++) + ((IPropertyChangeListener) listeners[i]).propertyChange(event); + } + + /** + * {@inheritDoc} + */ + public boolean getBoolean(String name) { + return getNode().getBoolean(name, BOOLEAN_DEFAULT_DEFAULT); + } + + /** + * {@inheritDoc} + */ + public boolean getDefaultBoolean(String name) { + return BOOLEAN_DEFAULT_DEFAULT; + } + + /** + * {@inheritDoc} + */ + public double getDefaultDouble(String name) { + return DOUBLE_DEFAULT_DEFAULT; + } + + /** + * {@inheritDoc} + */ + public float getDefaultFloat(String name) { + return FLOAT_DEFAULT_DEFAULT; + } + + /** + * {@inheritDoc} + */ + public int getDefaultInt(String name) { + return INT_DEFAULT_DEFAULT; + } + + /** + * {@inheritDoc} + */ + public long getDefaultLong(String name) { + return LONG_DEFAULT_DEFAULT; + } + + /** + * {@inheritDoc} + */ + public String getDefaultString(String name) { + return STRING_DEFAULT_DEFAULT; + } + + /** + * {@inheritDoc} + */ + public double getDouble(String name) { + return getNode().getDouble(name, DOUBLE_DEFAULT_DEFAULT); + } + + /** + * {@inheritDoc} + */ + public float getFloat(String name) { + return getNode().getFloat(name, FLOAT_DEFAULT_DEFAULT); + } + + /** + * {@inheritDoc} + */ + public int getInt(String name) { + return getNode().getInt(name, INT_DEFAULT_DEFAULT); + } + + /** + * {@inheritDoc} + */ + public long getLong(String name) { + return getNode().getLong(name, LONG_DEFAULT_DEFAULT); + } + + /** + * {@inheritDoc} + */ + public String getString(String name) { + return getNode().get(name, STRING_DEFAULT_DEFAULT); + } + + /** + * {@inheritDoc} + */ + public boolean isDefault(String name) { + return false; + } + + /** + * {@inheritDoc} + */ + public boolean needsSaving() { + try { + return getNode().keys().length > 0; + } catch (BackingStoreException e) { + // ignore + } + return true; + } + + /** + * {@inheritDoc} + */ + public void putValue(String name, String value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, double value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, float value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, int value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, long value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, String defaultObject) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, boolean value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setToDefault(String name) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, double value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, float value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, int value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, long value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, String value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, boolean value) { + throw new UnsupportedOperationException(); + } + + } } \ No newline at end of file Index: EditorUtility.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/EditorUtility.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** EditorUtility.java 30 Mar 2006 03:09:31 -0000 1.2 --- EditorUtility.java 12 Apr 2006 21:26:25 -0000 1.3 *************** *** 5,8 **** --- 5,9 ---- import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; + import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; *************** *** 28,34 **** --- 29,37 ---- import org.rubypeople.rdt.core.IMember; import org.rubypeople.rdt.core.IRubyElement; + import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.ISourceRange; import org.rubypeople.rdt.core.ISourceReference; + import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.corext.util.RubyModelUtil; *************** *** 235,238 **** --- 238,263 ---- } } + + /** + * Returns the Ruby project for a given editor input or <code>null</code> if no corresponding + * Ruby project exists. + * + * @param input the editor input + * @return the corresponding Ruby project + * + * @since 0.9.0 + */ + public static IRubyProject getRubyProject(IEditorInput input) { + IRubyProject rProject= null; + if (input instanceof IFileEditorInput) { + IProject project= ((IFileEditorInput)input).getFile().getProject(); + if (project != null) { + rProject= RubyCore.create(project); + if (!rProject.exists()) + rProject= null; + } + } + return rProject; + } } |