|
From: <caw...@us...> - 2007-07-07 00:59:17
|
Revision: 2726
http://svn.sourceforge.net/rubyeclipse/?rev=2726&view=rev
Author: cawilliams
Date: 2007-07-06 17:59:07 -0700 (Fri, 06 Jul 2007)
Log Message:
-----------
First cut at Quick Outline
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/plugin.xml
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.properties
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorActionContributor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubySourceViewer.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/text/RubySourceViewerConfiguration.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyOutlineInformationControl.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/TextMessages.properties
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/OverrideIndicatorLabelDecorator.java
Modified: trunk/org.rubypeople.rdt.ui/plugin.xml
===================================================================
--- trunk/org.rubypeople.rdt.ui/plugin.xml 2007-07-07 00:29:33 UTC (rev 2725)
+++ trunk/org.rubypeople.rdt.ui/plugin.xml 2007-07-07 00:59:07 UTC (rev 2726)
@@ -482,6 +482,11 @@
contextId="org.rubypeople.rdt.ui.rubyEditorScope"
commandId="org.rubypeople.rdt.ui.edit.text.ruby.open.type"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
+ <key
+ sequence="M1+O"
+ contextId="org.rubypeople.rdt.ui.rubyEditorScope"
+ commandId="org.rubypeople.rdt.ui.edit.text.ruby.show.outline"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
</extension>
<extension point="org.eclipse.ui.commands">
<category
@@ -571,6 +576,12 @@
id="org.rubypeople.rdt.ui.edit.text.ruby.open.type"
name="%OpenTypeAction.label">
</command>
+ <command
+ name="%ActionDefinition.show.outline.name"
+ description="%ActionDefinition.show.outline.description"
+ categoryId="org.eclipse.ui.category.navigate"
+ id="org.rubypeople.rdt.ui.edit.text.ruby.show.outline">
+ </command>
<command
name="%ActionDefinition.toggleComment.name"
description="%ActionDefinition.toggleComment.description"
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.properties
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.properties 2007-07-07 00:29:33 UTC (rev 2725)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.properties 2007-07-07 00:59:07 UTC (rev 2726)
@@ -130,6 +130,9 @@
HTMLTextPresenter_ellipsis=...
HTML2TextReader_listItemPrefix=\t-
+RubyOutlineControl_statusFieldText_hideInheritedMembers= Press ''{0}'' to hide inherited members
+RubyOutlineControl_statusFieldText_showInheritedMembers= Press ''{0}'' to show inherited members
+
RDocPathErrorTitle=RDoc path error
RDocPathError=The input path for RDoc is blank or incorrect. Use preferences to enter a valid RDoc path.
ErrorRunningRdocTitle=Error running RDoc
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java 2007-07-07 00:29:33 UTC (rev 2725)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java 2007-07-07 00:59:07 UTC (rev 2726)
@@ -92,6 +92,7 @@
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.SelectionEnabler;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.actions.ActionGroup;
@@ -251,6 +252,11 @@
action= new GotoMatchingBracketAction(this);
action.setActionDefinitionId(IRubyEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
+
+ action= new TextOperationAction(RubyEditorMessages.getBundleForConstructedKeys(),"ShowOutline.", this, RubySourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
+ action.setActionDefinitionId(IRubyEditorActionDefinitionIds.SHOW_OUTLINE);
+ setAction(IRubyEditorActionDefinitionIds.SHOW_OUTLINE, action);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(action, IRubyHelpContextIds.SHOW_OUTLINE_ACTION);
action = new FormatAction(RubyPlugin.getDefault().getPluginProperties(), "FormatAction.", this);
action.setActionDefinitionId(IRubyEditorActionDefinitionIds.FORMAT);
@@ -272,7 +278,7 @@
resAction= new InformationDispatchAction(RubyEditorMessages.getBundleForConstructedKeys(), "ShowRDoc.", (TextOperationAction) resAction); //$NON-NLS-1$
resAction.setActionDefinitionId(IRubyEditorActionDefinitionIds.SHOW_RDOC);
setAction("ShowRDoc", resAction); //$NON-NLS-1$
-// PlatformUI.getWorkbench().getHelpSystem().setHelp(resAction, IRubyHelpContextIds.SHOW_JAVADOC_ACTION);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(resAction, IRubyHelpContextIds.SHOW_JAVADOC_ACTION);
SurroundWithBeginRescueAction beginRescueAction = new SurroundWithBeginRescueAction(this);
beginRescueAction.setActionDefinitionId(IRubyEditorActionDefinitionIds.SURROUND_WITH_BEGIN_RESCUE);
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorActionContributor.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorActionContributor.java 2007-07-07 00:29:33 UTC (rev 2725)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorActionContributor.java 2007-07-07 00:59:07 UTC (rev 2726)
@@ -31,6 +31,7 @@
protected RetargetTextEditorAction contentAssistProposal;
private RetargetTextEditorAction fGotoMatchingBracket;
+ private RetargetTextEditorAction fShowOutline;
private RetargetTextEditorAction fQuickAssistAction;
private RetargetAction fRetargetShowRubyDoc;
@@ -44,6 +45,9 @@
fRetargetShowRubyDoc.setActionDefinitionId(IRubyEditorActionDefinitionIds.SHOW_RDOC);
markAsPartListener(fRetargetShowRubyDoc);
+ fShowOutline= new RetargetTextEditorAction(RubyEditorMessages.getBundleForConstructedKeys(), "ShowOutline."); //$NON-NLS-1$
+ fShowOutline.setActionDefinitionId(IRubyEditorActionDefinitionIds.SHOW_OUTLINE);
+
contentAssistProposal = new RetargetTextEditorAction(RubyUIMessages.getResourceBundle(),
"ContentAssistProposal.");
fGotoMatchingBracket = new RetargetTextEditorAction(b, "GotoMatchingBracket."); //$NON-NLS-1$
@@ -61,15 +65,20 @@
fPartListeners.add(action);
}
- public void contributeToMenu(IMenuManager menuManager) {
- IMenuManager editMenu = menuManager.findMenuUsingPath(IWorkbenchActionConstants.M_EDIT);
+ public void contributeToMenu(IMenuManager menu) {
+ IMenuManager editMenu = menu.findMenuUsingPath(IWorkbenchActionConstants.M_EDIT);
if (editMenu != null) {
editMenu.add(new Separator());
editMenu.add(contentAssistProposal);
editMenu.add(fQuickAssistAction);
}
- IMenuManager gotoMenu= menuManager.findMenuUsingPath("navigate/goTo"); //$NON-NLS-1$
+ IMenuManager navigateMenu= menu.findMenuUsingPath(IWorkbenchActionConstants.M_NAVIGATE);
+ if (navigateMenu != null) {
+ navigateMenu.appendToGroup(IWorkbenchActionConstants.SHOW_EXT, fShowOutline);
+ }
+
+ IMenuManager gotoMenu= menu.findMenuUsingPath("navigate/goTo"); //$NON-NLS-1$
if (gotoMenu != null) {
gotoMenu.add(new Separator("additions2")); //$NON-NLS-1$
gotoMenu.appendToGroup("additions2", fGotoMatchingBracket); //$NON-NLS-1$
@@ -88,7 +97,8 @@
fGotoMatchingBracket.setAction(getAction(textEditor,
GotoMatchingBracketAction.GOTO_MATCHING_BRACKET));
fQuickAssistAction.setAction(getAction(textEditor, ITextEditorActionConstants.QUICK_ASSIST));
-
+ fShowOutline.setAction(getAction(textEditor, IRubyEditorActionDefinitionIds.SHOW_OUTLINE));
+ fShowRubyDoc.setAction(getAction(textEditor, "ShowRDoc")); //$NON-NLS-1$
if (part instanceof RubyEditor) {
RubyEditor javaEditor= (RubyEditor) part;
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubySourceViewer.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubySourceViewer.java 2007-07-07 00:29:33 UTC (rev 2725)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubySourceViewer.java 2007-07-07 00:59:07 UTC (rev 2726)
@@ -21,6 +21,7 @@
import org.eclipse.jface.text.IAutoEditStrategy;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.information.IInformationPresenter;
import org.eclipse.jface.text.link.ILinkedModeListener;
import org.eclipse.jface.text.link.InclusivePositionUpdater;
import org.eclipse.jface.text.link.LinkedModeModel;
@@ -42,14 +43,33 @@
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.AbstractTextEditor;
+import org.rubypeople.rdt.ui.text.RubySourceViewerConfiguration;
public class RubySourceViewer extends ProjectionViewer implements IPropertyChangeListener {
+ /**
+ * Text operation code for requesting the outline for the current input.
+ */
+ public static final int SHOW_OUTLINE= 51;
+
+ /**
+ * Text operation code for requesting the outline for the element at the current position.
+ */
+ public static final int OPEN_STRUCTURE= 52;
+
+ /**
+ * Text operation code for requesting the hierarchy for the current input.
+ */
+ public static final int SHOW_HIERARCHY= 53;
+
private boolean fIgnoreTextConverters = false;
/** The linked position list for code auto edit */
protected final LinkedList fPositionList = new LinkedList();
+ private IInformationPresenter fOutlinePresenter;
+ private IInformationPresenter fStructurePresenter;
+
/**
* This viewer's foreground color.
* @since 0.8.0
@@ -190,7 +210,22 @@
}
super.configure(configuration);
+ if (configuration instanceof RubySourceViewerConfiguration) {
+ RubySourceViewerConfiguration javaSVCconfiguration= (RubySourceViewerConfiguration)configuration;
+ fOutlinePresenter= javaSVCconfiguration.getOutlinePresenter(this, false);
+ if (fOutlinePresenter != null)
+ fOutlinePresenter.install(this);
+ fStructurePresenter= javaSVCconfiguration.getOutlinePresenter(this, true);
+ if (fStructurePresenter != null)
+ fStructurePresenter.install(this);
+
+// fHierarchyPresenter= javaSVCconfiguration.getHierarchyPresenter(this, true);
+// if (fHierarchyPresenter != null)
+// fHierarchyPresenter.install(this);
+
+ }
+
if (fPreferenceStore != null) {
fPreferenceStore.addPropertyChangeListener(this);
initializeViewerColors();
@@ -204,21 +239,33 @@
* @since 0.8.0
*/
public void unconfigure() {
- if (fForegroundColor != null) {
- fForegroundColor.dispose();
- fForegroundColor= null;
- }
- if (fBackgroundColor != null) {
- fBackgroundColor.dispose();
- fBackgroundColor= null;
- }
+ if (fOutlinePresenter != null) {
+ fOutlinePresenter.uninstall();
+ fOutlinePresenter= null;
+ }
+ if (fStructurePresenter != null) {
+ fStructurePresenter.uninstall();
+ fStructurePresenter= null;
+ }
+// if (fHierarchyPresenter != null) {
+// fHierarchyPresenter.uninstall();
+// fHierarchyPresenter= null;
+// }
+ if (fForegroundColor != null) {
+ fForegroundColor.dispose();
+ fForegroundColor= null;
+ }
+ if (fBackgroundColor != null) {
+ fBackgroundColor.dispose();
+ fBackgroundColor= null;
+ }
- if (fPreferenceStore != null)
- fPreferenceStore.removePropertyChangeListener(this);
+ if (fPreferenceStore != null)
+ fPreferenceStore.removePropertyChangeListener(this);
- super.unconfigure();
+ super.unconfigure();
- fIsConfigured= false;
+ fIsConfigured= false;
}
/*
@@ -266,10 +313,41 @@
return null;
}
+
+ /*
+ * @see ITextOperationTarget#canDoOperation(int)
+ */
+ public boolean canDoOperation(int operation) {
+ if (operation == SHOW_OUTLINE)
+ return fOutlinePresenter != null;
+ if (operation == OPEN_STRUCTURE)
+ return fStructurePresenter != null;
+// if (operation == SHOW_HIERARCHY)
+// return fHierarchyPresenter != null;
+ return super.canDoOperation(operation);
+ }
+
public void doOperation(int operation) {
- if (getTextWidget() == null || !redraws()) { return; }
- super.doOperation(operation);
+ if (getTextWidget() == null)
+ return;
+
+ switch (operation) {
+ case SHOW_OUTLINE:
+ if (fOutlinePresenter != null)
+ fOutlinePresenter.showInformation();
+ return;
+ case OPEN_STRUCTURE:
+ if (fStructurePresenter != null)
+ fStructurePresenter.showInformation();
+ return;
+// case SHOW_HIERARCHY:
+// if (fHierarchyPresenter != null)
+// fHierarchyPresenter.showInformation();
+// return;
+ }
+
+ super.doOperation(operation);
}
/*
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyOutlineInformationControl.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyOutlineInformationControl.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyOutlineInformationControl.java 2007-07-07 00:59:07 UTC (rev 2726)
@@ -0,0 +1,713 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.ui.text;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.IDecoratorManager;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.keys.KeySequence;
+import org.eclipse.ui.keys.SWTKeySupport;
+import org.rubypeople.rdt.core.IMember;
+import org.rubypeople.rdt.core.IMethod;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.core.ITypeHierarchy;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.internal.corext.util.Messages;
+import org.rubypeople.rdt.internal.corext.util.MethodOverrideTester;
+import org.rubypeople.rdt.internal.corext.util.SuperTypeHierarchyCache;
+import org.rubypeople.rdt.internal.ui.IRubyHelpContextIds;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.rubypeople.rdt.internal.ui.RubyPluginImages;
+import org.rubypeople.rdt.internal.ui.RubyUIMessages;
+import org.rubypeople.rdt.internal.ui.typehierarchy.AbstractHierarchyViewerSorter;
+import org.rubypeople.rdt.internal.ui.util.StringMatcher;
+import org.rubypeople.rdt.internal.ui.viewsupport.AppearanceAwareLabelProvider;
+import org.rubypeople.rdt.internal.ui.viewsupport.MemberFilter;
+import org.rubypeople.rdt.ui.OverrideIndicatorLabelDecorator;
+import org.rubypeople.rdt.ui.ProblemsLabelDecorator;
+import org.rubypeople.rdt.ui.RubyElementLabels;
+import org.rubypeople.rdt.ui.StandardRubyElementContentProvider;
+
+/**
+ * Show outline in light-weight control.
+ *
+ * @since 2.1
+ */
+public class RubyOutlineInformationControl extends AbstractInformationControl {
+
+ private KeyAdapter fKeyAdapter;
+ private OutlineContentProvider fOutlineContentProvider;
+ private IRubyElement fInput= null;
+
+ private OutlineSorter fOutlineSorter;
+
+ private OutlineLabelProvider fInnerLabelProvider;
+ protected Color fForegroundColor;
+
+ private boolean fShowOnlyMainType;
+ private LexicalSortingAction fLexicalSortingAction;
+ private SortByDefiningTypeAction fSortByDefiningTypeAction;
+ private ShowOnlyMainTypeAction fShowOnlyMainTypeAction;
+ private Map fTypeHierarchies= new HashMap();
+
+ private String fPattern;
+
+ private class OutlineLabelProvider extends AppearanceAwareLabelProvider {
+
+ private boolean fShowDefiningType;
+
+ private OutlineLabelProvider() {
+ super(AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS, AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS);
+ }
+
+ /*
+ * @see ILabelProvider#getText
+ */
+ public String getText(Object element) {
+ String text= super.getText(element);
+ if (fShowDefiningType) {
+ try {
+ IType type= getDefiningType(element);
+ if (type != null) {
+ StringBuffer buf= new StringBuffer(super.getText(type));
+ buf.append(RubyElementLabels.CONCAT_STRING);
+ buf.append(text);
+ return buf.toString();
+ }
+ } catch (RubyModelException e) {
+ }
+ }
+ return text;
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.viewsupport.RubyUILabelProvider#getForeground(java.lang.Object)
+ */
+ public Color getForeground(Object element) {
+ if (fOutlineContentProvider.isShowingInheritedMembers()) {
+ if (element instanceof IRubyElement) {
+ IRubyElement je= (IRubyElement)element;
+ je= je.getAncestor(IRubyElement.SCRIPT);
+ if (fInput.equals(je)) {
+ return null;
+ }
+ }
+ return fForegroundColor;
+ }
+ return null;
+ }
+
+ public void setShowDefiningType(boolean showDefiningType) {
+ fShowDefiningType= showDefiningType;
+ }
+
+ public boolean isShowDefiningType() {
+ return fShowDefiningType;
+ }
+
+ private IType getDefiningType(Object element) throws RubyModelException {
+ int kind= ((IRubyElement) element).getElementType();
+
+ if (kind != IRubyElement.METHOD && kind != IRubyElement.FIELD) {
+ return null;
+ }
+ IType declaringType= ((IMember) element).getDeclaringType();
+ if (kind != IRubyElement.METHOD) {
+ return declaringType;
+ }
+ ITypeHierarchy hierarchy= getSuperTypeHierarchy(declaringType);
+ if (hierarchy == null) {
+ return declaringType;
+ }
+ IMethod method= (IMethod) element;
+ MethodOverrideTester tester= new MethodOverrideTester(declaringType, hierarchy);
+ IMethod res= tester.findDeclaringMethod(method, true);
+ if (res == null || method.equals(res)) {
+ return declaringType;
+ }
+ return res.getDeclaringType();
+ }
+ }
+
+
+ private class OutlineTreeViewer extends TreeViewer {
+
+ private boolean fIsFiltering= false;
+
+ private OutlineTreeViewer(Tree tree) {
+ super(tree);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Object[] getFilteredChildren(Object parent) {
+ Object[] result = getRawChildren(parent);
+ int unfilteredChildren= result.length;
+ ViewerFilter[] filters = getFilters();
+ if (filters != null) {
+ for (int i= 0; i < filters.length; i++)
+ result = filters[i].filter(this, parent, result);
+ }
+ fIsFiltering= unfilteredChildren != result.length;
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void internalExpandToLevel(Widget node, int level) {
+ if (!fIsFiltering && node instanceof Item) {
+ Item i= (Item) node;
+ if (i.getData() instanceof IRubyElement) {
+ IRubyElement je= (IRubyElement) i.getData();
+ if (je.getElementType() == IRubyElement.IMPORT_CONTAINER || isInnerType(je)) {
+ setExpanded(i, false);
+ return;
+ }
+ }
+ }
+ super.internalExpandToLevel(node, level);
+ }
+
+ private boolean isInnerType(IRubyElement element) {
+ if (element != null && element.getElementType() == IRubyElement.TYPE) {
+ IType type= (IType)element;
+ try {
+ return type.isMember();
+ } catch (RubyModelException e) {
+ IRubyElement parent= type.getParent();
+ if (parent != null) {
+ int parentElementType= parent.getElementType();
+ return (parentElementType != IRubyElement.SCRIPT);
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+
+ private class OutlineContentProvider extends StandardRubyElementContentProvider {
+
+ private boolean fShowInheritedMembers;
+
+ /**
+ * Creates a new Outline content provider.
+ *
+ * @param showInheritedMembers <code>true</code> iff inherited members are shown
+ */
+ private OutlineContentProvider(boolean showInheritedMembers) {
+ super(true);
+ fShowInheritedMembers= showInheritedMembers;
+ }
+
+ public boolean isShowingInheritedMembers() {
+ return fShowInheritedMembers;
+ }
+
+ public void toggleShowInheritedMembers() {
+ Tree tree= getTreeViewer().getTree();
+
+ tree.setRedraw(false);
+ fShowInheritedMembers= !fShowInheritedMembers;
+ getTreeViewer().refresh();
+ getTreeViewer().expandToLevel(2);
+
+ // reveal selection
+ Object selectedElement= getSelectedElement();
+ if (selectedElement != null)
+ getTreeViewer().reveal(selectedElement);
+
+ tree.setRedraw(true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object[] getChildren(Object element) {
+ if (fShowOnlyMainType) {
+ if (element instanceof IRubyScript) {
+ element= getMainType((IRubyScript)element);
+ }
+
+ if (element == null)
+ return NO_CHILDREN;
+ }
+
+ if (fShowInheritedMembers && element instanceof IType) {
+ IType type= (IType)element;
+ if (type.getDeclaringType() == null) {
+ ITypeHierarchy th= getSuperTypeHierarchy(type);
+ if (th != null) {
+ List children= new ArrayList();
+ IType[] superClasses= th.getAllSupertypes(type);
+ children.addAll(Arrays.asList(super.getChildren(type)));
+ for (int i= 0, scLength= superClasses.length; i < scLength; i++)
+ children.addAll(Arrays.asList(super.getChildren(superClasses[i])));
+ return children.toArray();
+ }
+ }
+ }
+ return super.getChildren(element);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ super.inputChanged(viewer, oldInput, newInput);
+ fTypeHierarchies.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose() {
+ super.dispose();
+ fTypeHierarchies.clear();
+ }
+ }
+
+
+ private class ShowOnlyMainTypeAction extends Action {
+
+ private static final String STORE_GO_INTO_TOP_LEVEL_TYPE_CHECKED= "GoIntoTopLevelTypeAction.isChecked"; //$NON-NLS-1$
+
+ private TreeViewer fOutlineViewer;
+
+ private ShowOnlyMainTypeAction(TreeViewer outlineViewer) {
+ super(TextMessages.RubyOutlineInformationControl_GoIntoTopLevelType_label, IAction.AS_CHECK_BOX);
+ setToolTipText(TextMessages.RubyOutlineInformationControl_GoIntoTopLevelType_tooltip);
+ setDescription(TextMessages.RubyOutlineInformationControl_GoIntoTopLevelType_description);
+
+ RubyPluginImages.setLocalImageDescriptors(this, "gointo_toplevel_type.gif"); //$NON-NLS-1$
+
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IRubyHelpContextIds.GO_INTO_TOP_LEVEL_TYPE_ACTION);
+
+ fOutlineViewer= outlineViewer;
+
+ boolean showclass= getDialogSettings().getBoolean(STORE_GO_INTO_TOP_LEVEL_TYPE_CHECKED);
+ setTopLevelTypeOnly(showclass);
+ }
+
+ /*
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ public void run() {
+ setTopLevelTypeOnly(!fShowOnlyMainType);
+ }
+
+ private void setTopLevelTypeOnly(boolean show) {
+ fShowOnlyMainType= show;
+ setChecked(show);
+
+ Tree tree= fOutlineViewer.getTree();
+ tree.setRedraw(false);
+
+ fOutlineViewer.refresh(false);
+ if (!fShowOnlyMainType)
+ fOutlineViewer.expandToLevel(2);
+
+
+ // reveal selection
+ Object selectedElement= getSelectedElement();
+ if (selectedElement != null)
+ fOutlineViewer.reveal(selectedElement);
+
+ tree.setRedraw(true);
+
+ getDialogSettings().put(STORE_GO_INTO_TOP_LEVEL_TYPE_CHECKED, show);
+ }
+ }
+
+ private class OutlineSorter extends AbstractHierarchyViewerSorter {
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.typehierarchy.AbstractHierarchyViewerSorter#getHierarchy(org.eclipse.jdt.core.IType)
+ * @since 3.2
+ */
+ protected ITypeHierarchy getHierarchy(IType type) {
+ return getSuperTypeHierarchy(type);
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.typehierarchy.AbstractHierarchyViewerSorter#isSortByDefiningType()
+ * @since 3.2
+ */
+ public boolean isSortByDefiningType() {
+ return fSortByDefiningTypeAction.isChecked();
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.typehierarchy.AbstractHierarchyViewerSorter#isSortAlphabetically()
+ * @since 3.2
+ */
+ public boolean isSortAlphabetically() {
+ return fLexicalSortingAction.isChecked();
+ }
+ }
+
+
+ private class LexicalSortingAction extends Action {
+
+ private static final String STORE_LEXICAL_SORTING_CHECKED= "LexicalSortingAction.isChecked"; //$NON-NLS-1$
+
+ private TreeViewer fOutlineViewer;
+
+ private LexicalSortingAction(TreeViewer outlineViewer) {
+ super(TextMessages.RubyOutlineInformationControl_LexicalSortingAction_label, IAction.AS_CHECK_BOX);
+ setToolTipText(TextMessages.RubyOutlineInformationControl_LexicalSortingAction_tooltip);
+ setDescription(TextMessages.RubyOutlineInformationControl_LexicalSortingAction_description);
+
+ RubyPluginImages.setLocalImageDescriptors(this, "alphab_sort_co.gif"); //$NON-NLS-1$
+
+ fOutlineViewer= outlineViewer;
+
+ boolean checked=getDialogSettings().getBoolean(STORE_LEXICAL_SORTING_CHECKED);
+ setChecked(checked);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IRubyHelpContextIds.LEXICAL_SORTING_BROWSING_ACTION);
+ }
+
+ public void run() {
+ valueChanged(isChecked(), true);
+ }
+
+ private void valueChanged(final boolean on, boolean store) {
+ setChecked(on);
+ BusyIndicator.showWhile(fOutlineViewer.getControl().getDisplay(), new Runnable() {
+ public void run() {
+ fOutlineViewer.refresh(false);
+ }
+ });
+
+ if (store)
+ getDialogSettings().put(STORE_LEXICAL_SORTING_CHECKED, on);
+ }
+ }
+
+
+ private class SortByDefiningTypeAction extends Action {
+
+ private static final String STORE_SORT_BY_DEFINING_TYPE_CHECKED= "SortByDefiningType.isChecked"; //$NON-NLS-1$
+
+ private TreeViewer fOutlineViewer;
+
+ /**
+ * Creates the action.
+ *
+ * @param outlineViewer the outline viewer
+ */
+ private SortByDefiningTypeAction(TreeViewer outlineViewer) {
+ super(TextMessages.RubyOutlineInformationControl_SortByDefiningTypeAction_label);
+ setDescription(TextMessages.RubyOutlineInformationControl_SortByDefiningTypeAction_description);
+ setToolTipText(TextMessages.RubyOutlineInformationControl_SortByDefiningTypeAction_tooltip);
+
+ RubyPluginImages.setLocalImageDescriptors(this, "definingtype_sort_co.gif"); //$NON-NLS-1$
+
+ fOutlineViewer= outlineViewer;
+
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IRubyHelpContextIds.SORT_BY_DEFINING_TYPE_ACTION);
+
+ boolean state= getDialogSettings().getBoolean(STORE_SORT_BY_DEFINING_TYPE_CHECKED);
+ setChecked(state);
+ fInnerLabelProvider.setShowDefiningType(state);
+ }
+
+ /*
+ * @see Action#actionPerformed
+ */
+ public void run() {
+ BusyIndicator.showWhile(fOutlineViewer.getControl().getDisplay(), new Runnable() {
+ public void run() {
+ fInnerLabelProvider.setShowDefiningType(isChecked());
+ getDialogSettings().put(STORE_SORT_BY_DEFINING_TYPE_CHECKED, isChecked());
+
+ setMatcherString(fPattern, false);
+ fOutlineViewer.refresh(true);
+
+ // reveal selection
+ Object selectedElement= getSelectedElement();
+ if (selectedElement != null)
+ fOutlineViewer.reveal(selectedElement);
+ }
+ });
+ }
+ }
+
+ /**
+ * String matcher that can match two patterns.
+ *
+ * @since 3.2
+ */
+ private static class OrStringMatcher extends StringMatcher {
+
+ private StringMatcher fMatcher1;
+ private StringMatcher fMatcher2;
+
+ private OrStringMatcher(String pattern1, String pattern2, boolean ignoreCase, boolean foo) {
+ super("", false, false); //$NON-NLS-1$
+ fMatcher1= new StringMatcher(pattern1, ignoreCase, false);
+ fMatcher2= new StringMatcher(pattern2, ignoreCase, false);
+ }
+
+ public boolean match(String text) {
+ return fMatcher2.match(text) || fMatcher1.match(text);
+ }
+
+ }
+
+
+ /**
+ * Creates a new Ruby outline information control.
+ *
+ * @param parent
+ * @param shellStyle
+ * @param treeStyle
+ * @param commandId
+ */
+ public RubyOutlineInformationControl(Shell parent, int shellStyle, int treeStyle, String commandId) {
+ super(parent, shellStyle, treeStyle, commandId, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Text createFilterText(Composite parent) {
+ Text text= super.createFilterText(parent);
+ text.addKeyListener(getKeyAdapter());
+ return text;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected TreeViewer createTreeViewer(Composite parent, int style) {
+ Tree tree= new Tree(parent, SWT.SINGLE | (style & ~SWT.MULTI));
+ GridData gd= new GridData(GridData.FILL_BOTH);
+ gd.heightHint= tree.getItemHeight() * 12;
+ tree.setLayoutData(gd);
+
+ final TreeViewer treeViewer= new OutlineTreeViewer(tree);
+
+ // Hard-coded filters
+ treeViewer.addFilter(new NamePatternFilter());
+ treeViewer.addFilter(new MemberFilter());
+
+ fForegroundColor= parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY);
+
+ fInnerLabelProvider= new OutlineLabelProvider();
+ fInnerLabelProvider.addLabelDecorator(new ProblemsLabelDecorator(null));
+ IDecoratorManager decoratorMgr= PlatformUI.getWorkbench().getDecoratorManager();
+ if (decoratorMgr.getEnabled("org.rubypeople.rdt.ui.override.decorator")) //$NON-NLS-1$
+ fInnerLabelProvider.addLabelDecorator(new OverrideIndicatorLabelDecorator(null));
+
+ treeViewer.setLabelProvider(fInnerLabelProvider);
+
+ fLexicalSortingAction= new LexicalSortingAction(treeViewer);
+ fSortByDefiningTypeAction= new SortByDefiningTypeAction(treeViewer);
+ fShowOnlyMainTypeAction= new ShowOnlyMainTypeAction(treeViewer);
+
+ fOutlineContentProvider= new OutlineContentProvider(false);
+ treeViewer.setContentProvider(fOutlineContentProvider);
+ fOutlineSorter= new OutlineSorter();
+ treeViewer.setSorter(fOutlineSorter);
+ treeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
+
+
+ treeViewer.getTree().addKeyListener(getKeyAdapter());
+
+ return treeViewer;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getStatusFieldText() {
+ KeySequence[] sequences= getInvokingCommandKeySequences();
+ if (sequences == null || sequences.length == 0)
+ return ""; //$NON-NLS-1$
+
+ String keySequence= sequences[0].format();
+
+ if (fOutlineContentProvider.isShowingInheritedMembers())
+ return Messages.format(RubyUIMessages.RubyOutlineControl_statusFieldText_hideInheritedMembers, keySequence);
+ else
+ return Messages.format(RubyUIMessages.RubyOutlineControl_statusFieldText_showInheritedMembers, keySequence);
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.text.AbstractInformationControl#getId()
+ * @since 3.0
+ */
+ protected String getId() {
+ return "org.eclipse.jdt.internal.ui.text.QuickOutline"; //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInput(Object information) {
+ if (information == null || information instanceof String) {
+ inputChanged(null, null);
+ return;
+ }
+ IRubyElement je= (IRubyElement)information;
+ IRubyScript cu= (IRubyScript)je.getAncestor(IRubyElement.SCRIPT);
+ if (cu != null)
+ fInput= cu;
+
+ inputChanged(fInput, information);
+ }
+
+ private KeyAdapter getKeyAdapter() {
+ if (fKeyAdapter == null) {
+ fKeyAdapter= new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ int accelerator = SWTKeySupport.convertEventToUnmodifiedAccelerator(e);
+ KeySequence keySequence = KeySequence.getInstance(SWTKeySupport.convertAcceleratorToKeyStroke(accelerator));
+ KeySequence[] sequences= getInvokingCommandKeySequences();
+ if (sequences == null)
+ return;
+ for (int i= 0; i < sequences.length; i++) {
+ if (sequences[i].equals(keySequence)) {
+ e.doit= false;
+ toggleShowInheritedMembers();
+ return;
+ }
+ }
+ }
+ };
+ }
+ return fKeyAdapter;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void handleStatusFieldClicked() {
+ toggleShowInheritedMembers();
+ }
+
+ protected void toggleShowInheritedMembers() {
+ long flags= fInnerLabelProvider.getTextFlags();
+ flags ^= RubyElementLabels.ALL_POST_QUALIFIED;
+ fInnerLabelProvider.setTextFlags(flags);
+ fOutlineContentProvider.toggleShowInheritedMembers();
+ updateStatusFieldText();
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.text.AbstractInformationControl#fillViewMenu(org.eclipse.jface.action.IMenuManager)
+ */
+ protected void fillViewMenu(IMenuManager viewMenu) {
+ super.fillViewMenu(viewMenu);
+ viewMenu.add(fShowOnlyMainTypeAction);
+
+ viewMenu.add(new Separator("Sorters")); //$NON-NLS-1$
+ viewMenu.add(fLexicalSortingAction);
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.text.AbstractInformationControl#setMatcherString(java.lang.String, boolean)
+ * @since 3.2
+ */
+ protected void setMatcherString(String pattern, boolean update) {
+ fPattern= pattern;
+ if (pattern.length() == 0 || !fSortByDefiningTypeAction.isChecked()) {
+ super.setMatcherString(pattern, update);
+ return;
+ }
+
+ boolean ignoreCase= pattern.toLowerCase().equals(pattern);
+ String pattern2= "*" + RubyElementLabels.CONCAT_STRING + pattern; //$NON-NLS-1$
+ fStringMatcher= new OrStringMatcher(pattern, pattern2, ignoreCase, false);
+
+ if (update)
+ stringMatcherUpdated();
+
+ }
+
+ private ITypeHierarchy getSuperTypeHierarchy(IType type) {
+ ITypeHierarchy th= (ITypeHierarchy)fTypeHierarchies.get(type);
+ if (th == null) {
+ try {
+ th= SuperTypeHierarchyCache.getTypeHierarchy(type, getProgressMonitor());
+ } catch (RubyModelException e) {
+ return null;
+ } catch (OperationCanceledException e) {
+ return null;
+ }
+ fTypeHierarchies.put(type, th);
+ }
+ return th;
+ }
+
+ private IProgressMonitor getProgressMonitor() {
+ IWorkbenchPage wbPage= RubyPlugin.getActivePage();
+ if (wbPage == null)
+ return null;
+
+ IEditorPart editor= wbPage.getActiveEditor();
+ if (editor == null)
+ return null;
+
+ return editor.getEditorSite().getActionBars().getStatusLineManager().getProgressMonitor();
+ }
+
+ /**
+ * Returns the primary type of a compilation unit (has the same
+ * name as the compilation unit).
+ *
+ * @param compilationUnit the compilation unit
+ * @return returns the primary type of the compilation unit, or
+ * <code>null</code> if is does not have one
+ */
+ private IType getMainType(IRubyScript compilationUnit) {
+
+ if (compilationUnit == null)
+ return null;
+
+ return compilationUnit.findPrimaryType();
+ }
+
+}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/TextMessages.properties
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/TextMessages.properties (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/TextMessages.properties 2007-07-07 00:59:07 UTC (rev 2726)
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2007 Aptana, Inc.
+#
+# 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. If redistributing this code,
+# this entire header must remain intact.
+###############################################################################
+# messages.properties
+# contains externalized strings for this package
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file should be translated.
+RubyOutlineInformationControl_LexicalSortingAction_label= &Sort
+RubyOutlineInformationControl_LexicalSortingAction_tooltip= Sort
+RubyOutlineInformationControl_LexicalSortingAction_description= Enable Sorting
+
+RubyOutlineInformationControl_SortByDefiningTypeAction_label= Sort by the Defining &Type
+RubyOutlineInformationControl_SortByDefiningTypeAction_tooltip= Sort Members by the Defining Type
+RubyOutlineInformationControl_SortByDefiningTypeAction_description= Sort members by the defining type
+
+RubyOutlineInformationControl_GoIntoTopLevelType_label= &Go Into Top Level Type
+RubyOutlineInformationControl_GoIntoTopLevelType_tooltip= Go Into Top Level Type
+RubyOutlineInformationControl_GoIntoTopLevelType_description= Show children of top level type only
\ No newline at end of file
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/OverrideIndicatorLabelDecorator.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/OverrideIndicatorLabelDecorator.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/OverrideIndicatorLabelDecorator.java 2007-07-07 00:59:07 UTC (rev 2726)
@@ -0,0 +1,242 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.rubypeople.rdt.ui;
+
+import org.eclipse.debug.internal.ui.ImageDescriptorRegistry;
+import org.eclipse.debug.internal.ui.views.launch.ImageImageDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ILightweightLabelDecorator;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.rubypeople.rdt.core.IMethod;
+import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.core.ITypeHierarchy;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.internal.corext.util.MethodOverrideTester;
+import org.rubypeople.rdt.internal.corext.util.RubyModelUtil;
+import org.rubypeople.rdt.internal.corext.util.SuperTypeHierarchyCache;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.rubypeople.rdt.internal.ui.RubyPluginImages;
+
+/**
+ * LabelDecorator that decorates an method's image with override or implements overlays.
+ * The viewer using this decorator is responsible for updating the images on element changes.
+ *
+ * <p>
+ * This class may be instantiated; it is not intended to be subclassed.
+ * </p>
+ *
+ * @since 2.0
+ */
+public class OverrideIndicatorLabelDecorator implements ILabelDecorator, ILightweightLabelDecorator {
+
+ private ImageDescriptorRegistry fRegistry;
+ private boolean fUseNewRegistry= false;
+
+ /**
+ * Creates a decorator. The decorator creates an own image registry to cache
+ * images.
+ */
+ public OverrideIndicatorLabelDecorator() {
+ this(null);
+ fUseNewRegistry= true;
+ }
+
+ /*
+ * Creates decorator with a shared image registry.
+ *
+ * @param registry The registry to use or <code>null</code> to use the Ruby plugin's
+ * image registry.
+ */
+ /**
+ * Note: This constructor is for internal use only. Clients should not call this constructor.
+ * @param registry The registry to use.
+ */
+ public OverrideIndicatorLabelDecorator(ImageDescriptorRegistry registry) {
+ fRegistry= registry;
+ }
+
+ private ImageDescriptorRegistry getRegistry() {
+ if (fRegistry == null) {
+ fRegistry= fUseNewRegistry ? new ImageDescriptorRegistry() : RubyPlugin.getImageDescriptorRegistry();
+ }
+ return fRegistry;
+ }
+
+
+ /* (non-Rubydoc)
+ * @see ILabelDecorator#decorateText(String, Object)
+ */
+ public String decorateText(String text, Object element) {
+ return text;
+ }
+
+ /* (non-Rubydoc)
+ * @see ILabelDecorator#decorateImage(Image, Object)
+ */
+ public Image decorateImage(Image image, Object element) {
+ int adornmentFlags= computeAdornmentFlags(element);
+ if (adornmentFlags != 0) {
+ ImageDescriptor baseImage= new ImageImageDescriptor(image);
+ Rectangle bounds= image.getBounds();
+ return getRegistry().get(new RubyElementImageDescriptor(baseImage, adornmentFlags, new Point(bounds.width, bounds.height)));
+ }
+ return image;
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this method.
+ * @param element The element to decorate
+ * @return Resulting decorations (combination of RubyElementImageDescriptor.IMPLEMENTS
+ * and RubyElementImageDescriptor.OVERRIDES)
+ */
+ public int computeAdornmentFlags(Object element) {
+ if (element instanceof IMethod) {
+ try {
+ IMethod method= (IMethod) element;
+ if (!method.getRubyProject().isOnLoadpath(method)) {
+ return 0;
+ }
+ if (!method.isConstructor() && method.getVisibility() != IMethod.PRIVATE && !method.isSingleton()) {
+ int res= getOverrideIndicators(method);
+ return res;
+ }
+ } catch (RubyModelException e) {
+ if (!e.isDoesNotExist()) {
+ RubyPlugin.log(e);
+ }
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this method.
+ * @param method The element to decorate
+ * @return Resulting decorations (combination of RubyElementImageDescriptor.IMPLEMENTS
+ * and RubyElementImageDescriptor.OVERRIDES)
+ * @throws RubyModelException
+ */
+ protected int getOverrideIndicators(IMethod method) throws RubyModelException {
+// Node astRoot= RubyPlugin.getDefault().getASTProvider().getAST((IRubyElement) method.getOpenable(), ASTProvider.WAIT_NO, null);
+// if (astRoot != null) {
+// int res= findInHierarchyWithAST(astRoot, method);
+// if (res != -1) {
+// return res;
+// }
+// }
+
+ IType type= method.getDeclaringType();
+
+ MethodOverrideTester methodOverrideTester= SuperTypeHierarchyCache.getMethodOverrideTester(type);
+ IMethod defining= methodOverrideTester.findOverriddenMethod(method, true);
+ if (defining != null) {
+ return RubyElementImageDescriptor.OVERRIDES;
+ }
+ return 0;
+ }
+
+// private int findInHierarchyWithAST(Node astRoot, IMethod method) throws RubyModelException {
+// Node methodNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(astRoot, method.getNameRange().getOffset(), new INodeAcceptor() {
+//
+// public boolean doesAccept(Node node) {
+// return node instanceof MethodDefNode;
+// }
+//
+// });
+//
+// Node node= NodeFinder.perform(astRoot, method.getNameRange());
+// if (node instanceof SimpleName && node.getParent() instanceof MethodDeclaration) {
+// IMethodBinding binding= ((MethodDeclaration) node.getParent()).resolveBinding();
+// if (binding != null) {
+// IMethodBinding defining= Bindings.findOverriddenMethod(binding, true);
+// if (defining != null) {
+// return RubyElementImageDescriptor.OVERRIDES;
+// }
+// return 0;
+// }
+// }
+// return -1;
+// }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this method.
+ * @param type The declaring type of the method to decorate.
+ * @param hierarchy The type hierarchy of the declaring type.
+ * @param name The name of the method to find.
+ * @param paramTypes The parameter types of the method to find.
+ * @return The resulting decoration.
+ * @throws RubyModelException
+ * @deprecated Not used anymore. This method is not accurate for methods in generic types.
+ */
+ protected int findInHierarchy(IType type, ITypeHierarchy hierarchy, String name, String[] paramTypes) throws RubyModelException {
+ IType superClass= hierarchy.getSuperclass(type);
+ if (superClass != null) {
+ IMethod res= RubyModelUtil.findMethodInHierarchy(hierarchy, superClass, name, paramTypes, false);
+ if (res != null && res.getVisibility() != IMethod.PRIVATE && RubyModelUtil.isVisibleInHierarchy(res, type.getSourceFolder())) {
+ return RubyElementImageDescriptor.OVERRIDES;
+ }
+ }
+ IType[] interfaces= hierarchy.getSuperInterfaces(type);
+ for (int i= 0; i < interfaces.length; i++) {
+ IMethod res= RubyModelUtil.findMethodInHierarchy(hierarchy, interfaces[i], name, paramTypes, false);
+ if (res != null) {
+ return RubyElementImageDescriptor.OVERRIDES;
+ }
+ }
+ return 0;
+ }
+
+ /* (non-Rubydoc)
+ * @see IBaseLabelProvider#addListener(ILabelProviderListener)
+ */
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ /* (non-Rubydoc)
+ * @see IBaseLabelProvider#dispose()
+ */
+ public void dispose() {
+ if (fRegistry != null && fUseNewRegistry) {
+ fRegistry.dispose();
+ }
+ }
+
+ /* (non-Rubydoc)
+ * @see IBaseLabelProvider#isLabelProperty(Object, String)
+ */
+ public boolean isLabelProperty(Object element, String property) {
+ return true;
+ }
+
+ /* (non-Rubydoc)
+ * @see IBaseLabelProvider#removeListener(ILabelProviderListener)
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration)
+ */
+ public void decorate(Object element, IDecoration decoration) {
+ int adornmentFlags= computeAdornmentFlags(element);
+ if ((adornmentFlags & RubyElementImageDescriptor.IMPLEMENTS) != 0) {
+ decoration.addOverlay(RubyPluginImages.DESC_OVR_IMPLEMENTS);
+ } else if ((adornmentFlags & RubyElementImageDescriptor.OVERRIDES) != 0) {
+ decoration.addOverlay(RubyPluginImages.DESC_OVR_OVERRIDES);
+ }
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/text/RubySourceViewerConfiguration.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/text/RubySourceViewerConfiguration.java 2007-07-07 00:29:33 UTC (rev 2725)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/text/RubySourceViewerConfiguration.java 2007-07-07 00:59:07 UTC (rev 2726)
@@ -4,6 +4,7 @@
import org.eclipse.core.runtime.NullProgressMonitor;
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;
@@ -51,6 +52,8 @@
import org.rubypeople.rdt.internal.ui.text.RubyAnnotationHover;
import org.rubypeople.rdt.internal.ui.text.RubyCommentScanner;
import org.rubypeople.rdt.internal.ui.text.RubyDoubleClickSelector;
+import org.rubypeople.rdt.internal.ui.text.RubyElementProvider;
+import org.rubypeople.rdt.internal.ui.text.RubyOutlineInformationControl;
import org.rubypeople.rdt.internal.ui.text.RubyPartitionScanner;
import org.rubypeople.rdt.internal.ui.text.RubyReconciler;
import org.rubypeople.rdt.internal.ui.text.comment.CommentFormattingStrategy;
@@ -68,6 +71,7 @@
import org.rubypeople.rdt.internal.ui.text.ruby.hover.RubyEditorTextHoverDescriptor;
import org.rubypeople.rdt.internal.ui.text.ruby.hover.RubyEditorTextHoverProxy;
import org.rubypeople.rdt.internal.ui.text.ruby.hover.RubyInformationProvider;
+import org.rubypeople.rdt.ui.actions.IRubyEditorActionDefinitionIds;
public class RubySourceViewerConfiguration extends TextSourceViewerConfiguration {
@@ -539,5 +543,53 @@
return new RubyCorrectionAssistant(getEditor());
return null;
}
+
+ /**
+ * Returns the outline presenter which will determine and shown
+ * information requested for the current cursor position.
+ *
+ * @param sourceViewer the source viewer to be configured by this configuration
+ * @param doCodeResolve a boolean which specifies whether code resolve should be used to compute the Java element
+ * @return an information presenter
+ * @since 2.1
+ */
+ public IInformationPresenter getOutlinePresenter(ISourceViewer sourceViewer, boolean doCodeResolve) {
+ InformationPresenter presenter;
+ if (doCodeResolve)
+ presenter= new InformationPresenter(getOutlinePresenterControlCreator(sourceViewer, IRubyEditorActionDefinitionIds.OPEN_STRUCTURE));
+ else
+ presenter= new InformationPresenter(getOutlinePresenterControlCreator(sourceViewer, IRubyEditorActionDefinitionIds.SHOW_OUTLINE));
+ presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+ presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
+ IInformationProvider provider= new RubyElementProvider(getEditor(), doCodeResolve);
+ presenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE);
+ presenter.setInformationProvider(provider, IRubyPartitions.RUBY_MULTI_LINE_COMMENT);
+ presenter.setInformationProvider(provider, IRubyPartitions.RUBY_SINGLE_LINE_COMMENT);
+ presenter.setInformationProvider(provider, IRubyPartitions.RUBY_STRING);
+ presenter.setInformationProvider(provider, IRubyPartitions.RUBY_REGULAR_EXPRESSION);
+ presenter.setInformationProvider(provider, IRubyPartitions.RUBY_COMMAND);
+ presenter.setSizeConstraints(50, 20, true, false);
+ return presenter;
+ }
+
+ /**
+ * Returns the outline presenter control creator. The creator is a factory creating outline
+ * presenter controls for the given source viewer. This implementation always returns a creator
+ * for <code>JavaOutlineInformationControl</code> instances.
+ *
+ * @param sourceViewer the source viewer to be configured by this configuration
+ * @param commandId the ID of the command that opens this control
+ * @return an information control creator
+ * @since 1.0
+ */
+ private 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);
+ }
+ };
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|