/* * Copyright (c) 2009 Andrejs Jermakovics. * * 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: * Andrejs Jermakovics - initial implementation */ package it.unibz.instasearch.ui; import it.unibz.instasearch.InstaSearchPlugin; import it.unibz.instasearch.indexing.SearchQuery; import it.unibz.instasearch.indexing.SearchResultDoc; import it.unibz.instasearch.prefs.PreferenceConstants; import it.unibz.instasearch.ui.ResultContentProvider.MatchLine; import java.util.Collection; import java.util.Locale; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.StyledString.Styler; import org.eclipse.search.ui.text.Match; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.RGB; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.model.WorkbenchLabelProvider; class ResultLabelProvider extends LabelProvider implements IStyledLabelProvider, IPropertyChangeListener { private static final String ECLIPSE_SEARCH_UI_MATCH_HIGHLIGHT = "org.eclipse.search.ui.match.highlight"; private static final String HIGHLIGHT_COLOR_NAME = "it.unibz.instasearch.ui.HighlightColor"; private static final String IMG_OBJ_TEXT_SEARCH_LINE = "org.eclipse.search.ui.line_match"; private static final String MORE_RESULTS_LABEL = "More..."; private static final String FIND_SIMILAR_LABEL = "Find similar..."; private static final String DOWN_ARROW_IMG_KEY = "down_arrow"; private ImageRegistry imageRegistry = new ImageRegistry(); private Styler highlightStyle; private WorkbenchLabelProvider labelProvider; private ResultContentProvider contentProvider; private Image matchImage; private boolean showMatchCount; private boolean showFullPath; public ResultLabelProvider(ResultContentProvider contentProvider) { Color searchColor = JFaceResources.getColorRegistry().get(ECLIPSE_SEARCH_UI_MATCH_HIGHLIGHT); JFaceResources.getColorRegistry().put(HIGHLIGHT_COLOR_NAME, (searchColor!=null?searchColor.getRGB():new RGB(206, 204, 247))); this.labelProvider = new WorkbenchLabelProvider(); this.highlightStyle = StyledString.createColorRegistryStyler(null, HIGHLIGHT_COLOR_NAME); this.contentProvider = contentProvider; this.matchImage = InstaSearchUI.getSharedImage(IMG_OBJ_TEXT_SEARCH_LINE); imageRegistry.put(DOWN_ARROW_IMG_KEY, InstaSearchPlugin.getImageDescriptor(DOWN_ARROW_IMG_KEY)); this.showMatchCount = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_MATCH_COUNT); this.showFullPath = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_FULL_PATH); InstaSearchPlugin.addPreferenceChangeListener(this); } public StyledString getStyledText(Object element) { if(element instanceof SearchResultDoc) { SearchResultDoc doc = (SearchResultDoc) element; return decorateFile(doc); } else if(element instanceof MatchLine) { MatchLine lineMatches = (MatchLine) element; return decorateLineMatches(lineMatches); } else if( element instanceof SearchQuery ) { // we have search query in 2 cases: SearchQuery query = (SearchQuery) element; if( !query.isLimited() ) return new StyledString(MORE_RESULTS_LABEL); else return new StyledString(FIND_SIMILAR_LABEL); } return new StyledString(element.toString()); } private StyledString decorateFile(SearchResultDoc doc) { String fileName = doc.getFileName(); StyledString str = new StyledString(fileName); Collection<String> searchTerms = contentProvider.getSearchTerms(); for(String searchTerm: searchTerms) // highlight matches { int termPos = fileName.toLowerCase(Locale.ENGLISH).indexOf(searchTerm); if( termPos != -1 ) str.setStyle(termPos, searchTerm.length(), highlightStyle); } int matchCount = doc.getMatchCount(); if( matchCount > 1 && showMatchCount ) { str.append(" (", StyledString.COUNTER_STYLER); str.append(Integer.toString(matchCount), StyledString.COUNTER_STYLER); str.append(" matches)", StyledString.COUNTER_STYLER); } str.append(" - ", StyledString.QUALIFIER_STYLER); str.append(doc.getProjectName(), StyledString.QUALIFIER_STYLER); if( showFullPath ) { String filePath = getCompactFilePath(doc, fileName); if( !"".equals(filePath) ) { str.append(" - ", StyledString.QUALIFIER_STYLER); str.append(filePath, StyledString.QUALIFIER_STYLER); } } if( InstaSearchPlugin.isDebug() ) { str.append(" - [", StyledString.DECORATIONS_STYLER); str.append(String.format("%.03f", doc.getScore()), StyledString.DECORATIONS_STYLER); str.append("]", StyledString.DECORATIONS_STYLER); } return str; } /** * File path without the project name and without the filename * * @param doc * @param fileName * @return */ private String getCompactFilePath(SearchResultDoc doc, String fileName) { String projectName = doc.getProjectName(); String filePath = doc.getFilePath(); int end = filePath.length()-1, start = filePath.indexOf(projectName); if( start == -1 ) start = 0; else start = start + projectName.length() + 1; if( filePath.endsWith(fileName) ) end = filePath.length() - fileName.length() - 1; if( start > end ) return ""; filePath = filePath.substring(start, end); return filePath; } private StyledString decorateLineMatches(MatchLine lineMatches) { String line = lineMatches.getLine(); StyledString str = new StyledString(line); for(Match m: lineMatches.getMatches()) { str.setStyle(m.getOffset(), m.getLength(), highlightStyle); } StyledString ret = new StyledString(); ret.append(lineMatches.getLineNumber() + ": ", StyledString.QUALIFIER_STYLER); ret.append(str); return ret; } public Image getImage(Object element) { try { if(element instanceof SearchResultDoc) { SearchResultDoc doc = (SearchResultDoc) element; Image image = null; if( !doc.isInJar() ) image = labelProvider.getImage(doc.getFile()); if( image == null ) image = getFileImage(doc); if( image == null ) image = InstaSearchUI.getSharedImage(ISharedImages.IMG_OBJ_FILE); return image; } else if( element instanceof MatchLine ) return matchImage ; else if( element instanceof Exception ) return InstaSearchUI.getSharedImage(ISharedImages.IMG_OBJS_WARN_TSK); else if( element instanceof SearchQuery ) return imageRegistry.get(DOWN_ARROW_IMG_KEY); } catch(Exception e) { InstaSearchPlugin.log(e); return InstaSearchUI.getSharedImage(ISharedImages.IMG_OBJS_WARN_TSK); } return InstaSearchUI.getSharedImage(ISharedImages.IMG_OBJS_INFO_TSK); // no results } private Image getFileImage(SearchResultDoc doc) { String ext = doc.getFileExtension(); Image fileImage = imageRegistry.get(ext); if( fileImage == null ) { ImageDescriptor imageDescriptor = PlatformUI.getWorkbench().getEditorRegistry().getImageDescriptor(doc.getFileName()); fileImage = imageDescriptor.createImage(true); imageRegistry.put(ext, fileImage); // cache created images for extensions } return fileImage; } public void propertyChange(PropertyChangeEvent event) { // update preferences if( PreferenceConstants.P_SHOW_MATCH_COUNT.equals(event.getProperty())) showMatchCount = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_MATCH_COUNT); else if( PreferenceConstants.P_SHOW_FULL_PATH.equals(event.getProperty())) showFullPath = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_FULL_PATH); } @Override public void dispose() { super.dispose(); imageRegistry.dispose(); InstaSearchPlugin.removePreferenceChangeListener(this); } }