|
From: Christopher W. <caw...@us...> - 2006-03-25 02:37:52
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/browsing In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11479/src/org/rubypeople/rdt/internal/ui/browsing Added Files: MembersView.java RubyBrowsingPart.java RubyBrowsingContentProvider.java TypesView.java RubyElementTypeComparator.java ProjectContentProvider.java RubyBrowsingPerspectiveFactory.java ProjectsView.java SimpleView.java Log Message: my initial working version of a Ruby Browsing Perspective --- NEW FILE: SimpleView.java --- package org.rubypeople.rdt.internal.ui.browsing; import java.util.ArrayList; import java.util.Iterator; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.List; import org.eclipse.ui.part.ViewPart; import org.rubypeople.rdt.core.IMethod; import org.rubypeople.rdt.core.IParent; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyModel; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IType; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.core.RubyModel; import org.rubypeople.rdt.internal.core.RubyModelManager; public class SimpleView extends ViewPart { public SimpleView() { super(); } public void createPartControl(Composite parent) { Group methodsGroup = new Group(parent, 8); methodsGroup.setText("Methods"); methodsGroup.setLayout(new FillLayout()); List methodsList = new List(methodsGroup, 0); methodsList.add("Methods"); Group typesGroup = new Group(parent, 8); typesGroup.setText("Types"); typesGroup.setLayout(new FillLayout()); List typeList = new List(typesGroup, 0); typeList.add("Types"); typeList.addSelectionListener(new TypeListener(typeList, methodsList)); java.util.List projects = new ArrayList(); try { RubyModel model = RubyModelManager.getRubyModelManager() .getRubyModel(); projects = model.getChildrenOfType(IRubyElement.RUBY_PROJECT); } catch (RubyModelException e) { // TODO Auto-generated catch block e.printStackTrace(); } Group projectsGroup = new Group(parent, 8); projectsGroup.setText("Projects"); projectsGroup.setLayout(new FillLayout()); List projectList = new List(projectsGroup, 0); for (Iterator iter = projects.iterator(); iter.hasNext();) { IRubyElement project = (IRubyElement) iter.next(); projectList.add(project.getElementName()); } projectList.addSelectionListener(new ProjectListener(projectList, typeList)); } public void setFocus() { // TODO Auto-generated method stub } private static class ProjectListener implements SelectionListener { private List projectList; private List typeList; private ProjectListener(List project, List types) { this.projectList = project; this.typeList = types; } public void widgetSelected(SelectionEvent e) { String[] selectedProjectNames = projectList.getSelection(); if (selectedProjectNames == null || selectedProjectNames.length == 0) return; typeList.removeAll(); for (int i = 0; i < selectedProjectNames.length; i++) { IRubyModel model = RubyModelManager.getRubyModelManager() .getRubyModel(); IRubyProject rubyProject = model .getRubyProject(selectedProjectNames[i]); java.util.List types = getTypes(rubyProject); for (Iterator iter = types.iterator(); iter.hasNext();) { typeList.add(((IType) iter.next()).getElementName()); } } } private java.util.List getTypes(IRubyElement element) { java.util.List types = new ArrayList(); if (element.isType(IRubyElement.TYPE)) types.add(element); if (element instanceof IParent) { IParent parent = (IParent) element; try { IRubyElement[] children = parent.getChildren(); for (int i = 0; i < children.length; i++) { types.addAll(getTypes(children[i])); } } catch (RubyModelException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return types; } public void widgetDefaultSelected(SelectionEvent e) { // TODO Auto-generated method stub } } private static class TypeListener implements SelectionListener { private List methodList; private List typeList; private TypeListener(List types, List methods) { this.methodList = methods; this.typeList = types; } public void widgetSelected(SelectionEvent e) { String[] selectedTypes = typeList.getSelection(); if (selectedTypes == null || selectedTypes.length == 0) return; methodList.removeAll(); for (int i = 0; i < selectedTypes.length; i++) { IRubyModel model = RubyModelManager.getRubyModelManager() .getRubyModel(); IRubyProject rubyProject = model .getRubyProject(selectedTypes[i]); // TODO Get all the methods for the seleted Types and add them to the // method list java.util.List methods = getMethods(rubyProject); for (Iterator iter = methods.iterator(); iter.hasNext();) { methodList.add(((IMethod) iter.next()).getElementName()); } } } private java.util.List getMethods(IRubyElement element) { java.util.List methods = new ArrayList(); if (element.isType(IRubyElement.METHOD)) methods.add(element); if (element instanceof IParent) { IParent parent = (IParent) element; try { IRubyElement[] children = parent.getChildren(); for (int i = 0; i < children.length; i++) { methods.addAll(getMethods(children[i])); } } catch (RubyModelException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return methods; } public void widgetDefaultSelected(SelectionEvent e) { // TODO Auto-generated method stub } } } --- NEW FILE: RubyElementTypeComparator.java --- /******************************************************************************* * 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.internal.ui.browsing; import java.util.Comparator; import org.rubypeople.rdt.core.IRubyElement; public class RubyElementTypeComparator implements Comparator { /** * Compares two Ruby element types. A type is considered to be * greater if it may contain the other. * * @return an int less than 0 if object1 is less than object2, * 0 if they are equal, and > 0 if object1 is greater * * @see Comparator#compare(Object, Object) */ public int compare(Object o1, Object o2) { if (!(o1 instanceof IRubyElement) || !(o2 instanceof IRubyElement)) throw new ClassCastException(); return getIdForRubyElement((IRubyElement)o1) - getIdForRubyElement((IRubyElement)o2); } /** * Compares two Ruby element types. A type is considered to be * greater if it may contain the other. * * @return an int < 0 if object1 is less than object2, * 0 if they are equal, and > 0 if object1 is greater * * @see Comparator#compare(Object, Object) */ public int compare(Object o1, int elementType) { if (!(o1 instanceof IRubyElement)) throw new ClassCastException(); return getIdForRubyElement((IRubyElement)o1) - getIdForRubyElementType(elementType); } int getIdForRubyElement(IRubyElement element) { return getIdForRubyElementType(element.getElementType()); } int getIdForRubyElementType(int elementType) { switch (elementType) { case IRubyElement.RUBY_MODEL: return 130; case IRubyElement.RUBY_PROJECT: return 120; case IRubyElement.SCRIPT: return 90; case IRubyElement.TYPE: return 70; case IRubyElement.FIELD: return 60; case IRubyElement.METHOD: return 50; case IRubyElement.IMPORT_CONTAINER: return 20; case IRubyElement.IMPORT_DECLARATION: return 10; default : return 1; } } } --- NEW FILE: RubyBrowsingPart.java --- package org.rubypeople.rdt.internal.ui.browsing; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.util.Assert; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.search.ui.ISearchResultView; import org.eclipse.search.ui.ISearchResultViewPart; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.part.IShowInSource; import org.eclipse.ui.part.ShowInContext; import org.eclipse.ui.part.ViewPart; import org.osgi.framework.Bundle; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.IType; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.ui.viewsupport.AppearanceAwareLabelProvider; import org.rubypeople.rdt.internal.ui.viewsupport.DecoratingRubyLabelProvider; import org.rubypeople.rdt.internal.ui.viewsupport.RubyElementImageProvider; import org.rubypeople.rdt.internal.ui.viewsupport.RubyUILabelProvider; import org.rubypeople.rdt.ui.StandardRubyElementContentProvider; public abstract class RubyBrowsingPart extends ViewPart implements ISelectionListener { private StructuredViewer fViewer; private RubyUILabelProvider fLabelProvider; protected IWorkbenchPart fPreviousSelectionProvider; protected Object fPreviousSelectedElement; /* * Ensure selection changed events being processed only if * initiated by user interaction with this part. */ private boolean fProcessSelectionEvents= true; private RubyElementTypeComparator fTypeComparator; private IPartListener2 fPartListener= new IPartListener2() { public void partActivated(IWorkbenchPartReference ref) { } public void partBroughtToTop(IWorkbenchPartReference ref) { } public void partInputChanged(IWorkbenchPartReference ref) { } public void partClosed(IWorkbenchPartReference ref) { } public void partDeactivated(IWorkbenchPartReference ref) { } public void partOpened(IWorkbenchPartReference ref) { } public void partVisible(IWorkbenchPartReference ref) { if (ref != null && ref.getId() == getSite().getId()){ fProcessSelectionEvents= true; IWorkbenchPage page= getSite().getWorkbenchWindow().getActivePage(); if (page != null) selectionChanged(page.getActivePart(), page.getSelection()); } } public void partHidden(IWorkbenchPartReference ref) { if (ref != null && ref.getId() == getSite().getId()) fProcessSelectionEvents= false; } }; public void createPartControl(Composite parent) { Assert.isTrue(fViewer == null); fViewer = new TreeViewer(parent); fTypeComparator= new RubyElementTypeComparator(); fLabelProvider= createLabelProvider(); fViewer.setLabelProvider(new DecoratingRubyLabelProvider(fLabelProvider)); fViewer.setUseHashlookup(true); getSite().setSelectionProvider(fViewer); fViewer.setContentProvider(createContentProvider()); setInitialInput(); // Initialize selection // TODO Use selection from editor, etc //setInitialSelection(); // Listen to page changes getViewSite().getPage().addPostSelectionListener(this); getViewSite().getPage().addPartListener(fPartListener); } /** * Creates the the content provider of this part. */ protected IContentProvider createContentProvider() { return new RubyBrowsingContentProvider(true, this); } protected final StructuredViewer getViewer() { return fViewer; } protected void setInitialInput() { // Use the selection, if any ISelection selection = getSite().getPage().getSelection(); Object input = getSingleElementFromSelection(selection); if (!(input instanceof IRubyElement)) { // Use the input of the page input = getSite().getPage().getInput(); if (!(input instanceof IRubyElement) && input instanceof IAdaptable) input = ((IAdaptable) input).getAdapter(IRubyElement.class); } setInput(findInputForRubyElement((IRubyElement) input)); } protected RubyUILabelProvider createLabelProvider() { return new AppearanceAwareLabelProvider( AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS, AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS | RubyElementImageProvider.SMALL_ICONS ); } protected void setInput(Object input) { setViewerInput(input); // TODO Update the title //updateTitle(); } private void setViewerInput(Object input) { fProcessSelectionEvents= false; fViewer.setInput(input); fProcessSelectionEvents= true; } private boolean isSearchResultView(IWorkbenchPart part) { return isSearchPlugInActivated() && (part instanceof ISearchResultView || part instanceof ISearchResultViewPart); } // FIXME Move this to a ruby SearchUtil class public static boolean isSearchPlugInActivated() { return Platform.getBundle("org.eclipse.search").getState() == Bundle.ACTIVE; //$NON-NLS-1$ } protected boolean needsToProcessSelectionChanged(IWorkbenchPart part, ISelection selection) { if (!fProcessSelectionEvents || part == this || isSearchResultView(part)){ if (part == this) fPreviousSelectionProvider= part; return false; } return true; } public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (!needsToProcessSelectionChanged(part, selection)) return; // TODO Handle editor selections // if (fToggleLinkingAction.isChecked() && (part instanceof ITextEditor)) { // setSelectionFromEditor(part, selection); // return; // } if (!(selection instanceof IStructuredSelection)) return; // Set selection Object selectedElement= getSingleElementFromSelection(selection); if (selectedElement != null && (part == null || part.equals(fPreviousSelectionProvider)) && selectedElement.equals(fPreviousSelectedElement)) return; fPreviousSelectedElement= selectedElement; Object currentInput= getViewer().getInput(); if (selectedElement != null && selectedElement.equals(currentInput)) { IRubyElement elementToSelect= findElementToSelect(selectedElement); if (elementToSelect != null && getTypeComparator().compare(selectedElement, elementToSelect) < 0) setSelection(new StructuredSelection(elementToSelect), true); // TODO Uncomment when we have a MembersView // else if (elementToSelect == null && (this instanceof MembersView)) { // setSelection(StructuredSelection.EMPTY, true); // fPreviousSelectedElement= StructuredSelection.EMPTY; // } fPreviousSelectionProvider= part; return; } // Clear input if needed if (part != fPreviousSelectionProvider && selectedElement != null && !selectedElement.equals(currentInput) && isInputResetBy(selectedElement, currentInput, part)) { if (!isAncestorOf(selectedElement, currentInput)) setInput(null); fPreviousSelectionProvider= part; return; } else if (selection.isEmpty() && !isInputResetBy(part)) { fPreviousSelectionProvider= part; return; } else if (selectedElement == null && part == fPreviousSelectionProvider) { setInput(null); fPreviousSelectionProvider= part; return; } fPreviousSelectionProvider= part; // Adjust input and set selection and adjustInputAndSetSelection(selectedElement); } void setSelection(ISelection selection, boolean reveal) { if (selection != null && selection.equals(fViewer.getSelection())) return; fProcessSelectionEvents= false; fViewer.setSelection(selection, reveal); fProcessSelectionEvents= true; } protected Object getInput() { return fViewer.getInput(); } public void setFocus() { fViewer.getControl().setFocus(); } /** * Answer the property defined by key. */ public Object getAdapter(Class key) { if (key == IShowInSource.class) { return getShowInSource(); } // TODO Uncomment when we have RubyUIHelp // if (key == IContextProvider.class) // return RubyUIHelp.getHelpContextProvider(this, getHelpContextId()); return super.getAdapter(key); } /** * Returns the <code>IShowInSource</code> for this view. */ protected IShowInSource getShowInSource() { return new IShowInSource() { public ShowInContext getShowInContext() { return new ShowInContext( null, getSite().getSelectionProvider().getSelection()); } }; } void adjustInputAndSetSelection(Object o) { if (!(o instanceof IRubyElement)) { if (o == null) setInput(null); setSelection(StructuredSelection.EMPTY, true); return; } IRubyElement je= (IRubyElement)o; IRubyElement elementToSelect= getSuitableRubyElement(findElementToSelect(je)); IRubyElement newInput= findInputForRubyElement(je); IRubyElement oldInput= null; if (getInput() instanceof IRubyElement) oldInput= (IRubyElement)getInput(); if (elementToSelect == null && !isValidInput(newInput) && (newInput == null && !isAncestorOf(je, oldInput))) // Clear input setInput(null); else if (mustSetNewInput(elementToSelect, oldInput, newInput)) { // Adjust input to selection setInput(newInput); // Recompute suitable element since it depends on the viewer's input elementToSelect= getSuitableRubyElement(elementToSelect); } if (elementToSelect != null && elementToSelect.exists()) setSelection(new StructuredSelection(elementToSelect), true); else setSelection(StructuredSelection.EMPTY, true); } /** * Converts the given Java element to one which is suitable for this * view. It takes into account whether the view shows working copies or not. * * @param obj the Java element to be converted * @return an element suitable for this view */ IRubyElement getSuitableRubyElement(Object obj) { if (!(obj instanceof IRubyElement)) return null; IRubyElement element= (IRubyElement)obj; if (fTypeComparator.compare(element, IRubyElement.SCRIPT) > 0) return element; if (isInputAWorkingCopy()) { IRubyElement wc= getWorkingCopy(element); if (wc != null) element= wc; return element; } else { return element.getPrimaryElement(); } } boolean isInputAWorkingCopy() { return ((StandardRubyElementContentProvider)getViewer().getContentProvider()).getProvideWorkingCopy(); } /** * Tries to find the given element in a workingcopy. */ protected static IRubyElement getWorkingCopy(IRubyElement input) { // MA: with new working copy story original == working copy return input; } /** * Compute if a new input must be set. * * @return <code>true</code> if the input has to be set * @since 3.0 */ private boolean mustSetNewInput(IRubyElement elementToSelect, IRubyElement oldInput, IRubyElement newInput) { return (newInput == null || !newInput.equals(oldInput)) && (elementToSelect == null || oldInput == null || (!(false && (elementToSelect.getParent().equals(oldInput.getParent())) && (!isAncestorOf(getViewPartInput(), elementToSelect))))); } /* (non-Javadoc) * @see org.eclipse.jdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput() */ public Object getViewPartInput() { if (fViewer != null) { return fViewer.getInput(); } return null; } /** * Gets the typeComparator. * @return Returns a RubyElementTypeComparator */ protected Comparator getTypeComparator() { return fTypeComparator; } private boolean isInputResetBy(Object newInput, Object input, IWorkbenchPart part) { if (newInput == null) return part == fPreviousSelectionProvider; if (input instanceof IRubyElement && newInput instanceof IRubyElement) return getTypeComparator().compare(newInput, input) > 0; else return false; } private boolean isInputResetBy(IWorkbenchPart part) { if (!(part instanceof RubyBrowsingPart)) return true; Object thisInput= getViewer().getInput(); Object partInput= ((RubyBrowsingPart)part).getViewer().getInput(); if(thisInput instanceof Collection) thisInput= ((Collection)thisInput).iterator().next(); if(partInput instanceof Collection) partInput= ((Collection)partInput).iterator().next(); if (thisInput instanceof IRubyElement && partInput instanceof IRubyElement) return getTypeComparator().compare(partInput, thisInput) > 0; else return true; } protected boolean isAncestorOf(Object ancestor, Object element) { if (element instanceof IRubyElement && ancestor instanceof IRubyElement) return !element.equals(ancestor) && internalIsAncestorOf((IRubyElement)ancestor, (IRubyElement)element); return false; } private boolean internalIsAncestorOf(IRubyElement ancestor, IRubyElement element) { if (element != null) return element.equals(ancestor) || internalIsAncestorOf(ancestor, element.getParent()); else return false; } protected final IRubyElement findElementToSelect(Object obj) { if (obj instanceof IRubyElement) return findElementToSelect((IRubyElement)obj); return null; } /** * Finds the element which has to be selected in this part. * * @param je the Ruby element which has the focus */ abstract protected IRubyElement findElementToSelect(IRubyElement je); protected final Object getSingleElementFromSelection(ISelection selection) { if (!(selection instanceof StructuredSelection) || selection.isEmpty()) return null; Iterator iter= ((StructuredSelection)selection).iterator(); Object firstElement= iter.next(); if (!(firstElement instanceof IRubyElement)) { if (firstElement instanceof IMarker) firstElement= ((IMarker)firstElement).getResource(); if (firstElement instanceof IAdaptable) { IRubyElement je= (IRubyElement)((IAdaptable)firstElement).getAdapter(IRubyElement.class); if (je == null && firstElement instanceof IFile) { IContainer parent= ((IFile)firstElement).getParent(); if (parent != null) return (IRubyElement)parent.getAdapter(IRubyElement.class); else return null; } else return je; } else return firstElement; } Object currentInput= getViewer().getInput(); if (currentInput == null || !currentInput.equals(findInputForRubyElement((IRubyElement)firstElement))) if (iter.hasNext()) // multi-selection and view is empty return null; else // OK: single selection and view is empty return firstElement; // be nice to multi-selection while (iter.hasNext()) { Object element= iter.next(); if (!(element instanceof IRubyElement)) return null; if (!currentInput.equals(findInputForRubyElement((IRubyElement)element))) return null; } return firstElement; } /** * Finds the closest Ruby element which can be used as input for * this part and has the given Ruby element as child * * @param je the Ruby element for which to search the closest input * @return the closest Ruby element used as input for this part */ protected IRubyElement findInputForRubyElement(IRubyElement je) { if (je == null || !je.exists()) return null; if (isValidInput(je)) return je; return findInputForRubyElement(je.getParent()); } /** * Answers if the given <code>element</code> is a valid * input for this part. * * @param element the object to test * @return <code>true</code> if the given element is a valid input */ abstract protected boolean isValidInput(Object element); /** * Answers if the given <code>element</code> is a valid * element for this part. * * @param element the object to test * @return <code>true</code> if the given element is a valid element */ protected boolean isValidElement(Object element) { if (element == null) return false; element= getSuitableRubyElement(element); if (element == null) return false; Object input= getViewer().getInput(); if (input == null) return false; if (input instanceof Collection) return ((Collection)input).contains(element); else return input.equals(element); } protected IType getTypeForRubyScript(IRubyScript script) { script = (IRubyScript) getSuitableRubyElement(script); // Use primary type if possible IType primaryType = script.findPrimaryType(); if (primaryType != null) return primaryType; // Use first top-level type try { IType[] types = script.getTypes(); if (types.length > 0) return types[0]; else return null; } catch (RubyModelException ex) { return null; } } public void dispose() { if (fViewer != null) { getViewSite().getPage().removePostSelectionListener(this); getViewSite().getPage().removePartListener(fPartListener); fViewer= null; } super.dispose(); } } --- NEW FILE: RubyBrowsingPerspectiveFactory.java --- /******************************************************************************* * 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.internal.ui.browsing; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.search.ui.NewSearchUI; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPerspectiveFactory; import org.eclipse.ui.IPlaceholderFolderLayout; import org.eclipse.ui.console.IConsoleConstants; import org.eclipse.ui.progress.IProgressConstants; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.ui.PreferenceConstants; import org.rubypeople.rdt.ui.RubyUI; public class RubyBrowsingPerspectiveFactory implements IPerspectiveFactory { /* * XXX: This is a workaround for: http://dev.eclipse.org/bugs/show_bug.cgi?id=13070 */ static IRubyElement fgRubyElementFromAction; /** * Constructs a new Default layout engine. */ public RubyBrowsingPerspectiveFactory() { super(); } public void createInitialLayout(IPageLayout layout) { if (stackBrowsingViewsVertically()) createVerticalLayout(layout); else createHorizontalLayout(layout); // action sets layout.addActionSet(IDebugUIConstants.LAUNCH_ACTION_SET); layout.addActionSet(RubyUI.ID_ACTION_SET); layout.addActionSet(RubyUI.ID_ELEMENT_CREATION_ACTION_SET); layout.addActionSet(IPageLayout.ID_NAVIGATE_ACTION_SET); // views - ruby //layout.addShowViewShortcut(RubyUI.ID_TYPE_HIERARCHY); layout.addShowViewShortcut(RubyUI.ID_PROJECTS_VIEW); layout.addShowViewShortcut(RubyUI.ID_TYPES_VIEW); layout.addShowViewShortcut(RubyUI.ID_MEMBERS_VIEW); // layout.addShowViewShortcut(RubyUI.ID_SOURCE_VIEW); // views - search layout.addShowViewShortcut(NewSearchUI.SEARCH_VIEW_ID); // views - debugging layout.addShowViewShortcut(IConsoleConstants.ID_CONSOLE_VIEW); // views - standard workbench layout.addShowViewShortcut(IPageLayout.ID_OUTLINE); layout.addShowViewShortcut(IPageLayout.ID_PROBLEM_VIEW); layout.addShowViewShortcut(IPageLayout.ID_RES_NAV); // new actions - Ruby project creation wizard layout.addNewWizardShortcut("org.rubypeople.rdt.ui.wizards.NewProjectCreationWizard"); //$NON-NLS-1$ layout.addNewWizardShortcut("org.rubypeople.rdt.ui.wizards.NewClassCreationWizard"); //$NON-NLS-1$ layout.addNewWizardShortcut("org.eclipse.ui.wizards.new.folder");//$NON-NLS-1$ layout.addNewWizardShortcut("org.eclipse.ui.wizards.new.file");//$NON-NLS-1$ layout.addNewWizardShortcut("org.eclipse.ui.editors.wizards.UntitledTextFileWizard");//$NON-NLS-1$ } private void createVerticalLayout(IPageLayout layout) { String relativePartId= IPageLayout.ID_EDITOR_AREA; int relativePos= IPageLayout.LEFT; IPlaceholderFolderLayout placeHolderLeft= layout.createPlaceholderFolder("left", IPageLayout.LEFT, (float)0.25, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$ //placeHolderLeft.addPlaceholder(RubyUI.ID_TYPE_HIERARCHY); placeHolderLeft.addPlaceholder(IPageLayout.ID_OUTLINE); placeHolderLeft.addPlaceholder(IPageLayout.ID_RES_NAV); if (shouldShowProjectsView()) { layout.addView(RubyUI.ID_PROJECTS_VIEW, IPageLayout.LEFT, (float)0.25, IPageLayout.ID_EDITOR_AREA); relativePartId= RubyUI.ID_PROJECTS_VIEW; relativePos= IPageLayout.BOTTOM; } layout.addView(RubyUI.ID_TYPES_VIEW, relativePos, (float)0.33, relativePartId); layout.addView(RubyUI.ID_MEMBERS_VIEW, IPageLayout.BOTTOM, (float)0.50, RubyUI.ID_TYPES_VIEW); IPlaceholderFolderLayout placeHolderBottom= layout.createPlaceholderFolder("bottom", IPageLayout.BOTTOM, (float)0.75, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$ placeHolderBottom.addPlaceholder(IPageLayout.ID_PROBLEM_VIEW); placeHolderBottom.addPlaceholder(NewSearchUI.SEARCH_VIEW_ID); placeHolderBottom.addPlaceholder(IConsoleConstants.ID_CONSOLE_VIEW); placeHolderBottom.addPlaceholder(IPageLayout.ID_BOOKMARKS); // placeHolderBottom.addPlaceholder(RubyUI.ID_SOURCE_VIEW); placeHolderBottom.addPlaceholder(IProgressConstants.PROGRESS_VIEW_ID); } private void createHorizontalLayout(IPageLayout layout) { String relativePartId= IPageLayout.ID_EDITOR_AREA; int relativePos= IPageLayout.TOP; if (shouldShowProjectsView()) { layout.addView(RubyUI.ID_PROJECTS_VIEW, IPageLayout.TOP, (float)0.25, IPageLayout.ID_EDITOR_AREA); relativePartId= RubyUI.ID_PROJECTS_VIEW; relativePos= IPageLayout.RIGHT; } layout.addView(RubyUI.ID_TYPES_VIEW, relativePos, (float)0.33, relativePartId); layout.addView(RubyUI.ID_MEMBERS_VIEW, IPageLayout.RIGHT, (float)0.50, RubyUI.ID_TYPES_VIEW); IPlaceholderFolderLayout placeHolderLeft= layout.createPlaceholderFolder("left", IPageLayout.LEFT, (float)0.25, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$ // placeHolderLeft.addPlaceholder(RubyUI.ID_TYPE_HIERARCHY); placeHolderLeft.addPlaceholder(IPageLayout.ID_OUTLINE); placeHolderLeft.addPlaceholder(IPageLayout.ID_RES_NAV); IPlaceholderFolderLayout placeHolderBottom= layout.createPlaceholderFolder("bottom", IPageLayout.BOTTOM, (float)0.75, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$ placeHolderBottom.addPlaceholder(IPageLayout.ID_PROBLEM_VIEW); placeHolderBottom.addPlaceholder(NewSearchUI.SEARCH_VIEW_ID); placeHolderBottom.addPlaceholder(IConsoleConstants.ID_CONSOLE_VIEW); placeHolderBottom.addPlaceholder(IPageLayout.ID_BOOKMARKS); // placeHolderBottom.addPlaceholder(RubyUI.ID_SOURCE_VIEW); placeHolderBottom.addPlaceholder(IProgressConstants.PROGRESS_VIEW_ID); } private boolean shouldShowProjectsView() { return fgRubyElementFromAction == null || fgRubyElementFromAction.getElementType() == IRubyElement.RUBY_MODEL; } private boolean stackBrowsingViewsVertically() { return PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.BROWSING_STACK_VERTICALLY); } /* * XXX: This is a workaround for: http://dev.eclipse.org/bugs/show_bug.cgi?id=13070 */ static void setInputFromAction(IAdaptable input) { if (input instanceof IRubyElement) fgRubyElementFromAction= (IRubyElement)input; else fgRubyElementFromAction= null; } } --- NEW FILE: ProjectContentProvider.java --- package org.rubypeople.rdt.internal.ui.browsing; import java.util.Iterator; import org.eclipse.jface.util.Assert; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.rubypeople.rdt.core.IRubyProject; public class ProjectContentProvider extends RubyBrowsingContentProvider implements IContentProvider { ProjectContentProvider(RubyBrowsingPart browsingPart) { super(false, browsingPart); } /* * (non-Javadoc) Method declared on ITreeContentProvider. */ public Object[] getChildren(Object element) { if (!exists(element)) return NO_CHILDREN; try { startReadInDisplayThread(); if (element instanceof IStructuredSelection) { Assert.isLegal(false); Object[] result = new Object[0]; Class clazz = null; Iterator iter = ((IStructuredSelection) element).iterator(); while (iter.hasNext()) { Object item = iter.next(); if (clazz == null) clazz = item.getClass(); if (clazz == item.getClass()) result = concatenate(result, getChildren(item)); else return NO_CHILDREN; } return result; } if (element instanceof IStructuredSelection) { Assert.isLegal(false); Object[] result = new Object[0]; Iterator iter = ((IStructuredSelection) element).iterator(); while (iter.hasNext()) result = concatenate(result, getChildren(iter.next())); return result; } if (element instanceof IRubyProject) return NO_CHILDREN; return super.getChildren(element); //} catch (RubyModelException e) { // return NO_CHILDREN; } finally { finishedReadInDisplayThread(); } } /* * * @see ITreeContentProvider */ public boolean hasChildren(Object element) { return element instanceof IRubyProject && super.hasChildren(element); } } --- NEW FILE: TypesView.java --- package org.rubypeople.rdt.internal.ui.browsing; 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.IType; public class TypesView extends RubyBrowsingPart { /** * Answers if the given <code>element</code> is a valid input for this * part. * * @param element * the object to test * @return <true> if the given element is a valid input */ protected boolean isValidInput(Object element) { return element instanceof IRubyProject; } /** * Finds the element which has to be selected in this part. * * @param je * the Ruby element which has the focus */ protected IRubyElement findElementToSelect(IRubyElement je) { if (je == null) return null; switch (je.getElementType()) { case IRubyElement.TYPE: IType type = ((IType) je).getDeclaringType(); if (type == null) type = (IType) je; return getSuitableRubyElement(type); case IRubyElement.SCRIPT: return getTypeForRubyScript((IRubyScript) je); case IRubyElement.IMPORT_CONTAINER: case IRubyElement.IMPORT_DECLARATION: return findElementToSelect(je.getParent()); default: if (je instanceof IMember) return findElementToSelect(((IMember) je).getDeclaringType()); return null; } } /** * Answers if the given <code>element</code> is a valid * element for this part. * * @param element the object to test * @return <true> if the given element is a valid element */ protected boolean isValidElement(Object element) { if (element instanceof IRubyScript) return super.isValidElement(((IRubyScript)element).getParent()); else if (element instanceof IType) { IType type= (IType)element; return type.getDeclaringType() == null && isValidElement(type.getRubyScript()); } return false; } } --- NEW FILE: MembersView.java --- package org.rubypeople.rdt.internal.ui.browsing; 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.IRubyScript; import org.rubypeople.rdt.core.IType; import org.rubypeople.rdt.core.RubyModelException; public class MembersView extends RubyBrowsingPart { /** * Answers if the given <code>element</code> is a valid * input for this part. * * @param element the object to test * @return <true> if the given element is a valid input */ protected boolean isValidInput(Object element) { if (element instanceof IType) { IType type= (IType)element; return type.getDeclaringType() == null; } return false; } /** * Answers if the given <code>element</code> is a valid * element for this part. * * @param element the object to test * @return <true> if the given element is a valid element */ protected boolean isValidElement(Object element) { if (element instanceof IMember) return super.isValidElement(((IMember)element).getDeclaringType()); else if (element instanceof IImportDeclaration) return isValidElement(((IRubyElement)element).getParent()); else if (element instanceof IImportContainer) { Object input= getViewer().getInput(); if (input instanceof IRubyElement) { IRubyScript cu= (IRubyScript)((IRubyElement)input).getAncestor(IRubyElement.SCRIPT); if (cu != null) { IRubyScript importContainerCu= (IRubyScript)((IRubyElement)element).getAncestor(IRubyElement.SCRIPT); return cu.equals(importContainerCu); } } } return false; } /** * Finds the element which has to be selected in this part. * * @param je the Ruby element which has the focus */ protected IRubyElement findElementToSelect(IRubyElement je) { if (je == null) return null; switch (je.getElementType()) { case IRubyElement.TYPE: if (((IType)je).getDeclaringType() == null) return null; // fall through case IRubyElement.METHOD: // fall through case IRubyElement.FIELD: // fall through case IRubyElement.IMPORT_CONTAINER: return getSuitableRubyElement(je); case IRubyElement.IMPORT_DECLARATION: je= getSuitableRubyElement(je); if (je != null) { IRubyScript cu= (IRubyScript)je.getParent().getParent(); try { if (cu.getImports()[0].equals(je)) { Object selectedElement= getSingleElementFromSelection(getViewer().getSelection()); if (selectedElement instanceof IImportContainer) return (IImportContainer)selectedElement; } } catch (RubyModelException ex) { // return je; } return je; } break; } return null; } /** * Finds the closest Ruby element which can be used as input for * this part and has the given Ruby element as child * * @param je the Ruby element for which to search the closest input * @return the closest Ruby element used as input for this part */ protected IRubyElement findInputForRubyElement(IRubyElement je) { if (je == null || !je.exists()) return null; switch (je.getElementType()) { case IRubyElement.TYPE: IType type= ((IType)je).getDeclaringType(); if (type == null) return je; else return findInputForRubyElement(type); case IRubyElement.SCRIPT: return getTypeForRubyScript((IRubyScript)je); case IRubyElement.IMPORT_DECLARATION: return findInputForRubyElement(je.getParent()); case IRubyElement.IMPORT_CONTAINER: IRubyElement parent= je.getParent(); if (parent instanceof IRubyScript) { return getTypeForRubyScript((IRubyScript)parent); } default: if (je instanceof IMember) return findInputForRubyElement(((IMember)je).getDeclaringType()); } return null; } boolean isInputAWorkingCopy() { Object input= getViewer().getInput(); if (input instanceof IRubyElement) { IRubyScript cu= (IRubyScript)((IRubyElement)input).getAncestor(IRubyElement.SCRIPT); if (cu != null) return cu.isWorkingCopy(); } return false; } } --- NEW FILE: RubyBrowsingContentProvider.java --- package org.rubypeople.rdt.internal.ui.browsing; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.rubypeople.rdt.core.IImportContainer; import org.rubypeople.rdt.core.IParent; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.ISourceReference; import org.rubypeople.rdt.core.IType; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.ui.StandardRubyElementContentProvider; public class RubyBrowsingContentProvider extends StandardRubyElementContentProvider { private RubyBrowsingPart fBrowsingPart; private StructuredViewer fViewer; private int fReadsInDisplayThread; private Object fInput; public RubyBrowsingContentProvider(boolean provideMembers, RubyBrowsingPart browsingPart) { super(provideMembers); fBrowsingPart = browsingPart; fViewer = fBrowsingPart.getViewer(); // TODO Add element change listener // RubyCore.addElementChangedListener(this); } public boolean hasChildren(Object element) { startReadInDisplayThread(); try { return super.hasChildren(element); } finally { finishedReadInDisplayThread(); } } public Object[] getChildren(Object element) { if (!exists(element)) return NO_CHILDREN; startReadInDisplayThread(); try { if (element instanceof Collection) { Collection elements = (Collection) element; if (elements.isEmpty()) return NO_CHILDREN; Object[] result = new Object[0]; Iterator iter = ((Collection) element).iterator(); while (iter.hasNext()) { Object[] children = getChildren(iter.next()); if (children != NO_CHILDREN) result = concatenate(result, children); } return result; } if (fProvideMembers && element instanceof IType) return getChildren((IType) element); if (fProvideMembers && element instanceof ISourceReference && element instanceof IParent) return super.getChildren(element); if (element instanceof IRubyProject) return getRubyTypes((IRubyProject) element); return super.getChildren(element); } catch (RubyModelException e) { return NO_CHILDREN; } finally { finishedReadInDisplayThread(); } } private Object[] getChildren(IType type) throws RubyModelException{ IParent parent= type.getRubyScript(); if (type.getDeclaringType() != null) return type.getChildren(); // Add import declarations IRubyElement[] members= parent.getChildren(); ArrayList tempResult= new ArrayList(members.length); for (int i= 0; i < members.length; i++) if ((members[i] instanceof IImportContainer)) tempResult.add(members[i]); tempResult.addAll(Arrays.asList(type.getChildren())); return tempResult.toArray(); } private Object[] getRubyTypes(IRubyProject project) throws RubyModelException { Object[] scripts = getRubyScripts(project); List list = new ArrayList(); for (int i = 0; i < scripts.length; i++) { IRubyScript script = (IRubyScript) scripts[i]; Object[] types = script.getTypes(); for (int j = 0; j < types.length; j++) { list.add(types[j]); } } return concatenate(list.toArray(), new Object[] {}); } protected Object[] getRubyScripts(IRubyProject project) throws RubyModelException { if (!project.getProject().isOpen()) return NO_CHILDREN; return project.getRubyScripts(); } private boolean isDisplayThread() { Control ctrl = fViewer.getControl(); if (ctrl == null) return false; Display currentDisplay = Display.getCurrent(); return currentDisplay != null && currentDisplay.equals(ctrl.getDisplay()); } protected void startReadInDisplayThread() { if (isDisplayThread()) fReadsInDisplayThread++; } protected void finishedReadInDisplayThread() { if (isDisplayThread()) fReadsInDisplayThread--; } /* * (non-Javadoc) Method declared on IContentProvider. */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { super.inputChanged(viewer, oldInput, newInput); if (newInput instanceof Collection) { // Get a template object from the collection Collection col = (Collection) newInput; if (!col.isEmpty()) newInput = col.iterator().next(); else newInput = null; } fInput = newInput; } /* * (non-Javadoc) Method declared on IContentProvider. */ public void dispose() { super.dispose(); // TODO Listen for element changes // RubyCore.removeElementChangedListener(this); } /** * Returns the parent for the element. * <p> * Note: This method will return a working copy if the parent is a working * copy. The super class implementation returns the original element * instead. * </p> */ protected Object internalGetParent(Object element) { if (element instanceof IRubyProject) { return ((IRubyProject) element).getRubyModel(); } // try to map resources to the containing package fragment if (element instanceof IResource) { IResource parent = ((IResource) element).getParent(); Object jParent = RubyCore.create(parent); if (jParent != null) return jParent; return parent; } if (element instanceof IRubyElement) return ((IRubyElement) element).getParent(); return null; } } --- NEW FILE: ProjectsView.java --- package org.rubypeople.rdt.internal.ui.browsing; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.part.IShowInTargetList; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyModel; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.ui.RubyUI; public class ProjectsView extends RubyBrowsingPart { /** * Creates the the content provider of this part. */ protected IContentProvider createContentProvider() { return new ProjectContentProvider(this); } protected void setInitialInput() { IRubyElement root = RubyCore .create(RubyPlugin.getWorkspace().getRoot()); getViewer().setInput(root); // TODO Update the title // updateTitle(); } /** * Answer the property defined by key. */ public Object getAdapter(Class key) { if (key == IShowInTargetList.class) { return new IShowInTargetList() { public String[] getShowInTargetIds() { return new String[] { RubyUI.ID_TYPES_VIEW, IPageLayout.ID_RES_NAV }; } }; } return super.getAdapter(key); } /** * Answers if the given <code>element</code> is a valid input for this * part. * * @param element * the object to test * @return <true> if the given element is a valid input */ protected boolean isValidInput(Object element) { return element instanceof IRubyModel; } /** * Answers if the given <code>element</code> is a valid element for this * part. * * @param element * the object to test * @return <true> if the given element is a valid element */ protected boolean isValidElement(Object element) { return element instanceof IRubyProject; } /** * Finds the element which has to be selected in this part. * * @param je the Ruby element which has the focus */ protected IRubyElement findElementToSelect(IRubyElement je) { if (je == null) return null; switch (je.getElementType()) { case IRubyElement.RUBY_MODEL : return null; case IRubyElement.RUBY_PROJECT: return je; default : return findElementToSelect(je.getParent()); } } } |