|
From: Markus B. <mba...@us...> - 2005-10-23 19:31:39
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/search In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32277/src/org/rubypeople/rdt/internal/ui/search Added Files: RubySearchPage.java RubySearchTreeContentProvider.java RubySearchQuery.java RubySearchResultPage.java RubySearchResult.java RubySearchLabelProvider.java Log Message: very preliminary version of the Ruby Search UI, with lots of TODOs. Allows to search for Classes with regular expressions only. --- NEW FILE: RubySearchLabelProvider.java --- /* Copyright (c) 2005 RubyPeople. * * Author: Markus * * This file is part of the Ruby Development Tools (RDT) plugin for eclipse. RDT * is subject to the "Common Public License (CPL) v 1.0". You may not use RDT * except in compliance with the License. For further information see * org.rubypeople.rdt/rdt.license. * */ package org.rubypeople.rdt.internal.ui.search; import org.eclipse.jface.viewers.LabelProvider; import org.rubypeople.rdt.internal.core.symbols.SearchResult; public class RubySearchLabelProvider extends LabelProvider { public String getText(Object element) { if (element instanceof SearchResult) { SearchResult searchResult = (SearchResult) element ; return searchResult.getSymbol().toString() ; } return super.getText(element); } } --- NEW FILE: RubySearchPage.java --- /* Copyright (c) 2005 RubyPeople. * * Author: Markus * * This file is part of the Ruby Development Tools (RDT) plugin for eclipse. RDT * is subject to the "Common Public License (CPL) v 1.0". You may not use RDT * except in compliance with the License. For further information see * org.rubypeople.rdt/rdt.license. * * This file is based on * org.eclipse.jdt.internal.ui.search.JavaSearchPage * Copyright (c) 2000, 2005 IBM Corporation and others. */ package org.rubypeople.rdt.internal.ui.search; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.util.Assert; import org.eclipse.search.internal.core.SearchScope; import org.eclipse.search.internal.ui.Messages; import org.eclipse.search.internal.ui.ScopePart; import org.eclipse.search.internal.ui.SearchMessages; import org.eclipse.search.ui.ISearchPage; import org.eclipse.search.ui.ISearchPageContainer; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.NewSearchUI; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.rubypeople.rdt.core.IRubyElement; public class RubySearchPage extends DialogPage implements ISearchPage { // Shouldn't SearchPatternData be a public class in org.eclipse.search ? private static class SearchPatternData { private int searchFor; private int limitTo; private String pattern; private boolean isCaseSensitive; private IRubyElement rubyElement; private int scope; private IWorkingSet[] workingSets; public SearchPatternData(int searchFor, int limitTo, boolean isCaseSensitive, String pattern, IRubyElement element) { this(searchFor, limitTo, pattern, isCaseSensitive, element, ISearchPageContainer.WORKSPACE_SCOPE, null); } public SearchPatternData(int searchFor, int limitTo, String pattern, boolean isCaseSensitive, IRubyElement element, int scope, IWorkingSet[] workingSets) { this.searchFor = searchFor; this.limitTo = limitTo; this.pattern = pattern; this.isCaseSensitive = isCaseSensitive; this.scope = scope; this.workingSets = workingSets; setRubyElement(element); } public void setRubyElement(IRubyElement element) { this.rubyElement = element; } public boolean isCaseSensitive() { return isCaseSensitive; } public IRubyElement getRubyElement() { return rubyElement; } public int getLimitTo() { return limitTo; } public String getPattern() { return pattern; } public int getScope() { return scope; } public int getSearchFor() { return searchFor; } public IWorkingSet[] getWorkingSets() { return workingSets; } public void store(IDialogSettings settings) { settings.put("searchFor", searchFor); //$NON-NLS-1$ settings.put("scope", scope); //$NON-NLS-1$ settings.put("pattern", pattern); //$NON-NLS-1$ settings.put("limitTo", limitTo); //$NON-NLS-1$ // TODO // settings.put("rubyElement", rubyElement != null ? // rubyElement.getHandleIdentifier() : ""); //$NON-NLS-1$ // //$NON-NLS-2$ settings.put("isCaseSensitive", isCaseSensitive); //$NON-NLS-1$ if (workingSets != null) { String[] wsIds = new String[workingSets.length]; for (int i = 0; i < workingSets.length; i++) { wsIds[i] = workingSets[i].getId(); } settings.put("workingSets", wsIds); //$NON-NLS-1$ } else { settings.put("workingSets", new String[0]); //$NON-NLS-1$ } } public static SearchPatternData create(IDialogSettings settings) { String pattern = settings.get("pattern"); //$NON-NLS-1$ if (pattern.length() == 0) { return null; } // handle the RubyElement // this is copied from JavaSearchPage String[] wsIds = settings.getArray("workingSets"); //$NON-NLS-1$ IWorkingSet[] workingSets = null; if (wsIds != null && wsIds.length > 0) { IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); workingSets = new IWorkingSet[wsIds.length]; for (int i = 0; workingSets != null && i < wsIds.length; i++) { workingSets[i] = workingSetManager.getWorkingSet(wsIds[i]); if (workingSets[i] == null) { workingSets = null; } } } try { int searchFor = settings.getInt("searchFor"); //$NON-NLS-1$ int scope = settings.getInt("scope"); //$NON-NLS-1$ int limitTo = settings.getInt("limitTo"); //$NON-NLS-1$ boolean isCaseSensitive = settings.getBoolean("isCaseSensitive"); //$NON-NLS-1$ // TODO IRubyElement elem = null; // settings.get("rubyElement") ; return new SearchPatternData(searchFor, limitTo, pattern, isCaseSensitive, elem, scope, workingSets); } catch (NumberFormatException e) { return null; } } } private static final int HISTORY_SIZE = 12; // Dialog store id constants private final static String PAGE_NAME = "JavaSearchPage"; //$NON-NLS-1$ private final static String STORE_CASE_SENSITIVE = "CASE_SENSITIVE"; //$NON-NLS-1$ private final static String STORE_HISTORY = "HISTORY"; //$NON-NLS-1$ private final static String STORE_HISTORY_SIZE = "HISTORY_SIZE"; //$NON-NLS-1$ private final List fPreviousSearchPatterns; private SearchPatternData fInitialData; private IRubyElement fRubyElement; private boolean fFirstTime = true; private IDialogSettings fDialogSettings; private boolean fIsCaseSensitive; private Combo fPattern; private ISearchPageContainer fContainer; private Button fCaseSensitive; private Button[] fSearchFor; // TODO: externalize strings private String[] fSearchForText = { "class", "method" /* * SearchMessages.SearchPage_searchFor_type, * SearchMessages.SearchPage_searchFor_method, * SearchMessages.SearchPage_searchFor_module, * SearchMessages.SearchPage_searchFor_field */}; private Button[] fLimitTo; private String[] fLimitToText = { "declarations" /* * SearchMessages.SearchPage_limitTo_declarations, * SearchMessages.SearchPage_limitTo_implementors, * SearchMessages.SearchPage_limitTo_references, * SearchMessages.SearchPage_limitTo_allOccurrences */}; private Button fSearchJRE; private static final int INDEX_REFERENCES = 2; private static final int INDEX_ALL = 3; /** * */ public RubySearchPage() { fPreviousSearchPatterns = new ArrayList(); } // ---- Action Handling ------------------------------------------------ public boolean performAction() { NewSearchUI.runQueryInBackground(getSearchQuery()); return true; } private ISearchQuery getSearchQuery() { SearchPatternData patternData = getPatternData(); // Setup search scope SearchScope scope = null; switch (getContainer().getSelectedScope()) { case ISearchPageContainer.WORKSPACE_SCOPE: scope = SearchScope.newWorkspaceScope(); break; /* * case ISearchPageContainer.SELECTION_SCOPE: scope= * getSelectedResourcesScope(false); break; case * ISearchPageContainer.SELECTED_PROJECTS_SCOPE: scope= * getSelectedResourcesScope(true); break; */ case ISearchPageContainer.WORKING_SET_SCOPE: IWorkingSet[] workingSets = getContainer().getSelectedWorkingSets(); String desc = Messages.format(SearchMessages.WorkingSetScope, ScopePart.toString(workingSets)); scope = SearchScope.newSearchScope(desc, workingSets); } NewSearchUI.activateSearchResultView(); return new RubySearchQuery(scope, patternData.getPattern()); } private int getLimitTo() { for (int i = 0; i < fLimitTo.length; i++) { if (fLimitTo[i].getSelection()) return i; } return -1; } private void setLimitTo(int searchFor, int limitTo) { /* * if (!(searchFor == TYPE || searchFor == INTERFACE) && limitTo == * IMPLEMENTORS) { limitTo= REFERENCES; } * * if (!(searchFor == FIELD) && (limitTo == READ_ACCESSES || limitTo == * WRITE_ACCESSES)) { limitTo= REFERENCES; } * * for (int i= 0; i < fLimitTo.length; i++) { * fLimitTo[i].setSelection(limitTo == i); } * * fLimitTo[DECLARATIONS].setEnabled(true); * fLimitTo[IMPLEMENTORS].setEnabled(searchFor == INTERFACE || searchFor == * TYPE); fLimitTo[REFERENCES].setEnabled(true); * fLimitTo[ALL_OCCURRENCES].setEnabled(true); * fLimitTo[READ_ACCESSES].setEnabled(searchFor == FIELD); * fLimitTo[WRITE_ACCESSES].setEnabled(searchFor == FIELD); */ } private String[] getPreviousSearchPatterns() { // Search results are not persistent int patternCount = fPreviousSearchPatterns.size(); String[] patterns = new String[patternCount]; for (int i = 0; i < patternCount; i++) patterns[i] = ((SearchPatternData) fPreviousSearchPatterns.get(i)).getPattern(); return patterns; } private int getSearchFor() { for (int i = 0; i < fSearchFor.length; i++) { if (fSearchFor[i].getSelection()) return i; } Assert.isTrue(false, "shouldNeverHappen"); //$NON-NLS-1$ return -1; } private String getPattern() { return fPattern.getText(); } private SearchPatternData findInPrevious(String pattern) { for (Iterator iter = fPreviousSearchPatterns.iterator(); iter.hasNext();) { SearchPatternData element = (SearchPatternData) iter.next(); if (pattern.equals(element.getPattern())) { return element; } } return null; } /** * Return search pattern data and update previous searches. An existing * entry will be updated. */ private SearchPatternData getPatternData() { String pattern = getPattern(); SearchPatternData match = findInPrevious(pattern); if (match != null) { fPreviousSearchPatterns.remove(match); } match = new SearchPatternData(getSearchFor(), getLimitTo(), pattern, fCaseSensitive.getSelection(), fRubyElement, getContainer().getSelectedScope(), getContainer().getSelectedWorkingSets()); fPreviousSearchPatterns.add(0, match); // insert on top return match; } /* * Implements method from IDialogPage */ public void setVisible(boolean visible) { if (visible && fPattern != null) { if (fFirstTime) { fFirstTime = false; // Set item and text here to prevent page from resizing fPattern.setItems(getPreviousSearchPatterns()); // initSelections(); } fPattern.setFocus(); } // updateOKStatus(); super.setVisible(visible); } public boolean isValid() { return true; } // ---- Widget creation ------------------------------------------------ /** * Creates the page's content. */ public void createControl(Composite parent) { initializeDialogUnits(parent); // readConfiguration(); Composite result = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.horizontalSpacing = 10; result.setLayout(layout); Control expressionComposite = createExpression(result); expressionComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1)); Label separator = new Label(result, SWT.NONE); separator.setVisible(false); GridData data = new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1); data.heightHint = convertHeightInCharsToPixels(1) / 3; separator.setLayoutData(data); Control searchFor = createSearchFor(result); searchFor.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1)); Control limitTo = createLimitTo(result); limitTo.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1)); // createParticipants(result); SelectionAdapter javaElementInitializer = new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { if (getSearchFor() == fInitialData.getSearchFor()) fRubyElement = fInitialData.getRubyElement(); else fRubyElement = null; setLimitTo(getSearchFor(), getLimitTo()); doPatternModified(); } }; // fSearchFor[TYPE].addSelectionListener(javaElementInitializer); // fSearchFor[METHOD].addSelectionListener(javaElementInitializer); // fSearchFor[FIELD].addSelectionListener(javaElementInitializer); // fSearchFor[CONSTRUCTOR].addSelectionListener(javaElementInitializer); // fSearchFor[PACKAGE].addSelectionListener(javaElementInitializer); setControl(result); Dialog.applyDialogFont(result); // PlatformUI.getWorkbench().getHelpSystem().setHelp(result, // IJavaHelpContextIds.JAVA_SEARCH_PAGE); } /* * private Control createParticipants(Composite result) { if * (!SearchParticipantsExtensionPoint.hasAnyParticipants()) return new * Composite(result, SWT.NULL); Button selectParticipants= new * Button(result, SWT.PUSH); * selectParticipants.setText(SearchMessages.getString("SearchPage.select_participants.label")); * //$NON-NLS-1$ GridData gd= new GridData(); gd.verticalAlignment= * GridData.VERTICAL_ALIGN_BEGINNING; gd.horizontalAlignment= * GridData.HORIZONTAL_ALIGN_END; gd.grabExcessHorizontalSpace= false; * gd.horizontalAlignment= GridData.END; gd.horizontalSpan= 2; * selectParticipants.setLayoutData(gd); * selectParticipants.addSelectionListener(new SelectionAdapter() { public * void widgetSelected(SelectionEvent e) { * PreferencePageSupport.showPreferencePage(getShell(), * "org.eclipse.jdt.ui.preferences.SearchParticipantsExtensionPoint", new * SearchParticipantsExtensionPoint()); //$NON-NLS-1$ } * * }); return selectParticipants; } */ private Control createExpression(Composite parent) { Composite result = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.marginWidth = 0; layout.marginHeight = 0; result.setLayout(layout); // Pattern text + info Label label = new Label(result, SWT.LEFT); // TODO label.setText("Expression"); // label.setText(SearchMessages.SearchPage_expression_label); label.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1)); // Pattern combo fPattern = new Combo(result, SWT.SINGLE | SWT.BORDER); fPattern.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { // handlePatternSelected(); // updateOKStatus(); } }); fPattern.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { doPatternModified(); // updateOKStatus(); } }); GridData data = new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1); data.widthHint = convertWidthInCharsToPixels(50); fPattern.setLayoutData(data); // Ignore case checkbox fCaseSensitive = new Button(result, SWT.CHECK); // TODO fCaseSensitive.setText("CaseSensitive"); fCaseSensitive.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { fIsCaseSensitive = fCaseSensitive.getSelection(); } }); fCaseSensitive.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, 1, 1)); return result; } private boolean isValidSearchPattern() { if (getPattern().length() == 0) { return false; } if (fRubyElement != null) { return true; } // TODO return true; // return SearchPattern.createPattern(getPattern(), getSearchFor(), // getLimitTo(), SearchPattern.R_EXACT_MATCH) != null; } /* * (non-Javadoc) * * @see org.eclipse.jface.dialogs.DialogPage#dispose() */ public void dispose() { // writeConfiguration(); super.dispose(); } private void doPatternModified() { /* * if (fInitialData != null && * getPattern().equals(fInitialData.getPattern()) && * fInitialData.getJavaElement() != null && fInitialData.getSearchFor() == * getSearchFor()) { fCaseSensitive.setEnabled(false); * fCaseSensitive.setSelection(true); fJavaElement= * fInitialData.getJavaElement(); } else { fCaseSensitive.setEnabled(true); * fCaseSensitive.setSelection(fIsCaseSensitive); fJavaElement= null; } */ } private void setSearchFor(int searchFor) { for (int i = 0; i < fSearchFor.length; i++) { fSearchFor[i].setSelection(searchFor == i); } } private Control createSearchFor(Composite parent) { Group result = new Group(parent, SWT.NONE); // TODO result.setText("searchfor"); result.setLayout(new GridLayout(2, true)); fSearchFor = new Button[fSearchForText.length]; for (int i = 0; i < fSearchForText.length; i++) { Button button = new Button(result, SWT.RADIO); button.setText(fSearchForText[i]); button.setSelection(i == 0); button.setLayoutData(new GridData()); fSearchFor[i] = button; } // Fill with dummy radio buttons Label filler = new Label(result, SWT.NONE); filler.setVisible(false); filler.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1)); return result; } private Control createLimitTo(Composite parent) { Group result = new Group(parent, SWT.NONE); /* * result.setText("Limit to") * ;//SearchMessages.SearchPage_limitTo_label); result.setLayout(new * GridLayout(2, true)); * * SelectionAdapter listener= new SelectionAdapter() { public void * widgetSelected(SelectionEvent e) { //updateUseJRE(); } }; * * fLimitTo= new Button[fLimitToText.length]; for (int i= 0; i < * fLimitToText.length; i++) { Button button= new Button(result, * SWT.RADIO); button.setText(fLimitToText[i]); fLimitTo[i]= button; * button.setSelection(i == REFERENCES); * button.addSelectionListener(listener); button.setLayoutData(new * GridData()); } */ return result; } /* * Implements method from ISearchPage */ public void setContainer(ISearchPageContainer container) { fContainer = container; } /** * Returns the search page's container. */ private ISearchPageContainer getContainer() { return fContainer; } } --- NEW FILE: RubySearchResult.java --- /* Copyright (c) 2005 RubyPeople. * * Author: Markus * * This file is part of the Ruby Development Tools (RDT) plugin for eclipse. RDT * is subject to the "Common Public License (CPL) v 1.0". You may not use RDT * except in compliance with the License. For further information see * org.rubypeople.rdt/rdt.license. * */ package org.rubypeople.rdt.internal.ui.search; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.eclipse.search.ui.text.IEditorMatchAdapter; import org.eclipse.search.ui.text.IFileMatchAdapter; public class RubySearchResult extends AbstractTextSearchResult { private RubySearchQuery fRubySearchQuery ; public RubySearchResult(RubySearchQuery rubySearchQuery) { fRubySearchQuery = rubySearchQuery ; } public IEditorMatchAdapter getEditorMatchAdapter() { // TODO Auto-generated method stub return null; } public IFileMatchAdapter getFileMatchAdapter() { // TODO Auto-generated method stub return null; } public String getLabel() { return "Ruby search result for " + fRubySearchQuery.toString(); } public String getTooltip() { // TODO Auto-generated method stub return null; } public ImageDescriptor getImageDescriptor() { // TODO Auto-generated method stub return null; } public ISearchQuery getQuery() { return fRubySearchQuery; } } --- NEW FILE: RubySearchTreeContentProvider.java --- /* * Author: Markus * * Copyright (c) 2005 RubyPeople. * * This file is part of the Ruby Development Tools (RDT) plugin for eclipse. RDT * is subject to the "Common Public License (CPL) v 1.0". You may not use RDT * except in compliance with the License. For further information see * org.rubypeople.rdt/rdt.license. * * This file is based on org.eclipse.search.internal.ui.text.FileTreeContentProvider * Copyright (c) 2000, 2005 IBM Corporation and others. */ package org.rubypeople.rdt.internal.ui.search; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.search.internal.ui.text.IFileSearchContentProvider; import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.rubypeople.rdt.internal.core.symbols.SearchResult; public class RubySearchTreeContentProvider implements ITreeContentProvider, IFileSearchContentProvider { private final Object[] EMPTY_ARR= new Object[0]; private AbstractTextSearchResult fResult; private AbstractTreeViewer fTreeViewer; private Map fChildrenMap; RubySearchTreeContentProvider(AbstractTreeViewer viewer) { fTreeViewer= viewer; } public Object[] getElements(Object inputElement) { return getChildren(inputElement); } public void dispose() { // nothing to do } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (newInput instanceof RubySearchResult) { initialize((RubySearchResult) newInput); } } protected synchronized void initialize(AbstractTextSearchResult result) { fResult= result; fChildrenMap= new HashMap(); if (result != null) { Object[] elements= result.getElements(); for (int i= 0; i < elements.length; i++) { insert(elements[i], false); } } } protected void insert(Object child, boolean refreshViewer) { Object parent= getParent(child); while (parent != null) { if (insertChild(parent, child)) { if (refreshViewer) fTreeViewer.add(parent, child); } else { if (refreshViewer) fTreeViewer.refresh(parent); return; } child= parent; parent= getParent(child); } if (insertChild(fResult, child)) { if (refreshViewer) fTreeViewer.add(fResult, child); } } /** * returns true if the child already was a child of parent. * * @param parent * @param child * @return Returns <code>trye</code> if the child was added */ private boolean insertChild(Object parent, Object child) { Set children= (Set) fChildrenMap.get(parent); if (children == null) { children= new HashSet(); fChildrenMap.put(parent, children); } return children.add(child); } protected void remove(Object element, boolean refreshViewer) { // precondition here: fResult.getMatchCount(child) <= 0 if (hasChildren(element)) { if (refreshViewer) fTreeViewer.refresh(element); } else { if (fResult.getMatchCount(element) == 0) { fChildrenMap.remove(element); Object parent= getParent(element); if (parent != null) { removeFromSiblings(element, parent); remove(parent, refreshViewer); } else { removeFromSiblings(element, fResult); if (refreshViewer) fTreeViewer.refresh(); } } else { if (refreshViewer) { fTreeViewer.refresh(element); } } } } private void removeFromSiblings(Object element, Object parent) { Set siblings= (Set) fChildrenMap.get(parent); if (siblings != null) { siblings.remove(element); } } public Object[] getChildren(Object parentElement) { Set children= (Set) fChildrenMap.get(parentElement); if (children == null) return EMPTY_ARR; return children.toArray(); } public boolean hasChildren(Object element) { return getChildren(element).length > 0; } public synchronized void elementsChanged(Object[] updatedElements) { for (int i= 0; i < updatedElements.length; i++) { if (fResult.getMatchCount(updatedElements[i]) > 0) insert(updatedElements[i], true); else remove(updatedElements[i], true); } } public void clear() { initialize(fResult); fTreeViewer.refresh(); } /* * Group search results by the containing file. * */ public Object getParent(Object element) { if (element instanceof SearchResult) { SearchResult result = (SearchResult) element; return result.getLocation().getSourcePath(); } return null; } } --- NEW FILE: RubySearchResultPage.java --- /* * Author: Markus * * Copyright (c) 2005 RubyPeople. * * This file is part of the Ruby Development Tools (RDT) plugin for eclipse. RDT is * subject to the "Common Public License (CPL) v 1.0". You may not use RDT except in * compliance with the License. For further information see org.rubypeople.rdt/rdt.license. * */ package org.rubypeople.rdt.internal.ui.search; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.search.internal.ui.text.FileSearchPage.DecoratorIgnoringViewerSorter; import org.eclipse.search.ui.text.AbstractTextSearchViewPage; import org.eclipse.search.ui.text.Match; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.texteditor.ITextEditor; import org.rubypeople.rdt.internal.core.symbols.SearchResult; import org.rubypeople.rdt.internal.ui.RubyPlugin; public class RubySearchResultPage extends AbstractTextSearchViewPage { RubySearchTreeContentProvider fContentProvider; public RubySearchResultPage() { } protected void elementsChanged(Object[] objects) { if (fContentProvider != null) { fContentProvider.elementsChanged(objects); } } protected void clear() { // TODO Auto-generated method stub } protected void configureTreeViewer(TreeViewer viewer) { viewer.setUseHashlookup(true); RubySearchLabelProvider innerLabelProvider = new RubySearchLabelProvider(); viewer.setLabelProvider(new DecoratingLabelProvider(innerLabelProvider, PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator())); fContentProvider = new RubySearchTreeContentProvider(viewer); viewer.setContentProvider(fContentProvider); viewer.setSorter(new DecoratorIgnoringViewerSorter(innerLabelProvider)); // TODO: addDragAdapters(viewer); } protected void configureTableViewer(TableViewer viewer) { // TODO: When is a table viewer needed ? } protected IEditorPart openEditor(Match match, boolean activate) { // TODO: like OpenEditor: consider NewSearchUI.reuseEditor() ? IWorkbenchPage page = RubyPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage(); try { SearchResult result = (SearchResult) match.getElement(); IPath sourcePath = result.getLocation().getSourcePath(); IResource resource = RubyPlugin.getWorkspace().getRoot().findMember(sourcePath); IFile file = (IFile) resource.getAdapter(org.eclipse.core.resources.IFile.class); if (file == null) { RubyPlugin.log("Couldn't convert search result to file: " + resource.getFullPath()); } else { return IDE.openEditor(page, file, activate); } } catch (PartInitException e) { RubyPlugin.log(e); } return null; } protected void showMatch(Match match, int offset, int length, boolean activate) throws PartInitException { // TODO: show search marker IEditorPart editor = openEditor(match, activate); if (offset != 0 && length != 0) { if (editor instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) editor; textEditor.selectAndReveal(offset, length); } } } } --- NEW FILE: RubySearchQuery.java --- /* Copyright (c) 2005 RubyPeople. * * Author: Markus * * This file is part of the Ruby Development Tools (RDT) plugin for eclipse. RDT * is subject to the "Common Public License (CPL) v 1.0". You may not use RDT * except in compliance with the License. For further information see * org.rubypeople.rdt/rdt.license. * */ package org.rubypeople.rdt.internal.ui.search; import java.util.Iterator; import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.search.internal.core.SearchScope; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.ISearchResult; import org.eclipse.search.ui.NewSearchUI; import org.eclipse.search.ui.text.Match; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.internal.core.symbols.SearchResult; public class RubySearchQuery implements ISearchQuery { private String fSearchString; private SearchScope fScope; private RubySearchResult fResult; public RubySearchQuery(SearchScope scope, String searchString) { fScope = scope; fSearchString = searchString; } public boolean canRerun() { // TODO Auto-generated method stub return false; } public boolean canRunInBackground() { return true; } public String getLabel() { // TODO Auto-generated method stub return "RubySearchJob"; } public ISearchResult getSearchResult() { if (fResult == null) { fResult = new RubySearchResult(this); // new SearchResultUpdater(fResult); } return fResult; } public IStatus run(IProgressMonitor monitor) throws OperationCanceledException { Set entries = RubyCore.getPlugin().getSymbolIndex().find(fSearchString); for (Iterator iter = entries.iterator(); iter.hasNext();) { SearchResult searchResult = (SearchResult) iter.next(); int startOffset = searchResult.getLocation().getPosition().getStartOffset(); int length = searchResult.getLocation().getPosition().getEndOffset() - startOffset; fResult.addMatch(new Match(searchResult, Match.UNIT_CHARACTER, startOffset, length)); } MultiStatus status = new MultiStatus(NewSearchUI.PLUGIN_ID, IStatus.OK, "Alright", null); return status; } public String toString() { return "reg exp. query for " + fSearchString; } } |