/** * Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package com.python.pydev.refactoring.refactorer.search.copied; import java.text.MessageFormat; import java.util.Arrays; import java.util.Comparator; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.eclipse.search.ui.text.AbstractTextSearchViewPage; import org.eclipse.search.ui.text.Match; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.python.pydev.shared_ui.SharedUiPlugin; import org.python.pydev.shared_ui.UIConstants; import org.python.pydev.shared_ui.search.SearchMessages; public class FileLabelProvider extends LabelProvider { public static final int SHOW_LABEL = 1; public static final int SHOW_LABEL_PATH = 2; public static final int SHOW_PATH_LABEL = 3; private static final String fgSeparatorFormat = "{0} - {1}"; //$NON-NLS-1$ private static final String fgEllipses = " ... "; //$NON-NLS-1$ private final WorkbenchLabelProvider fLabelProvider; private final AbstractTextSearchViewPage fPage; private final Comparator<FileMatch> fMatchComparator; private final Image fLineMatchImage; private int fOrder; public FileLabelProvider(AbstractTextSearchViewPage page, int orderFlag) { fLabelProvider = new WorkbenchLabelProvider(); fOrder = orderFlag; fPage = page; fLineMatchImage = SharedUiPlugin.getImageCache().get(UIConstants.LINE_MATCH); fMatchComparator = new Comparator<FileMatch>() { @Override public int compare(FileMatch o1, FileMatch o2) { return o1.getOriginalOffset() - o2.getOriginalOffset(); } }; } public void setOrder(int orderFlag) { fOrder = orderFlag; } public int getOrder() { return fOrder; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) */ @Override public String getText(Object object) { return getStyledText(object); } public String getStyledText(Object element) { if (element instanceof LineElement) { return getLineElementLabel((LineElement) element); } if (!(element instanceof IResource)) { return new String(); } IResource resource = (IResource) element; if (!resource.exists()) { new String(SearchMessages.FileLabelProvider_removed_resource_label); } String name = BasicElementLabels.getResourceName(resource); if (fOrder == SHOW_LABEL) { return getColoredLabelWithCounts(resource, new String(name)); } String pathString = BasicElementLabels.getPathLabel(resource.getParent().getFullPath(), false); if (fOrder == SHOW_LABEL_PATH) { String str = new String(name); // String decorated = Messages.format(fgSeparatorFormat, new String[] { str, pathString }); // decorateColoredString(str, decorated, String.QUALIFIER_STYLER); return getColoredLabelWithCounts(resource, str); } String str = new String(MessageFormat.format(fgSeparatorFormat, pathString, name)); return getColoredLabelWithCounts(resource, str); } private String getLineElementLabel(LineElement lineElement) { int lineNumber = lineElement.getLine(); String lineNumberString = MessageFormat .format(SearchMessages.FileLabelProvider_line_number, lineNumber); String str = new String(lineNumberString); FileMatch[] matches = lineElement.getMatches(fPage.getInput()); Arrays.sort(matches, fMatchComparator); String content = lineElement.getContents(); int pos = evaluateLineStart(matches, content, lineElement.getOffset()); int length = content.length(); int charsToCut = getCharsToCut(length, matches); // number of characters to leave away if the line is too long for (int i = 0; i < matches.length; i++) { FileMatch match = matches[i]; int start = Math.max(match.getOriginalOffset() - lineElement.getOffset(), 0); // append gap between last match and the new one if (pos < start) { if (charsToCut > 0) { charsToCut = appendShortenedGap(content, pos, start, charsToCut, i == 0, str); } else { str += content.substring(pos, start); } } // append match int end = Math.min(match.getOriginalOffset() + match.getOriginalLength() - lineElement.getOffset(), lineElement.getLength()); str += content.substring(start, end); pos = end; } // append rest of the line if (charsToCut > 0) { appendShortenedGap(content, pos, length, charsToCut, false, str); } else { str += content.substring(pos); } return str; } private static final int MIN_MATCH_CONTEXT = 10; // minimal number of characters shown after and before a match private int appendShortenedGap(String content, int start, int end, int charsToCut, boolean isFirst, String str) { int gapLength = end - start; if (!isFirst) { gapLength -= MIN_MATCH_CONTEXT; } if (end < content.length()) { gapLength -= MIN_MATCH_CONTEXT; } if (gapLength < MIN_MATCH_CONTEXT) { // don't cut, gap is too small str += content.substring(start, end); return charsToCut; } int context = MIN_MATCH_CONTEXT; if (gapLength > charsToCut) { context += gapLength - charsToCut; } if (!isFirst) { str += content.substring(start, start + context); // give all extra context to the right side of a match context = MIN_MATCH_CONTEXT; } str += fgEllipses; if (end < content.length()) { str += content.substring(end - context, end); } return charsToCut - gapLength + fgEllipses.length(); } private int getCharsToCut(int contentLength, Match[] matches) { if (contentLength <= 256 || !"win32".equals(SWT.getPlatform()) || matches.length == 0) { //$NON-NLS-1$ return 0; // no shortening required } // XXX: workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=38519 return contentLength - 256 + Math.max(matches.length * fgEllipses.length(), 100); } private int evaluateLineStart(Match[] matches, String lineContent, int lineOffset) { int max = lineContent.length(); if (matches.length > 0) { FileMatch match = (FileMatch) matches[0]; max = match.getOriginalOffset() - lineOffset; if (max < 0) { return 0; } } for (int i = 0; i < max; i++) { char ch = lineContent.charAt(i); if (!Character.isWhitespace(ch) || ch == '\n' || ch == '\r') { return i; } } return max; } private String getColoredLabelWithCounts(Object element, String coloredName) { AbstractTextSearchResult result = fPage.getInput(); if (result == null) { return coloredName; } int matchCount = result.getMatchCount(element); if (matchCount <= 1) { return coloredName; } String countInfo = MessageFormat.format(SearchMessages.FileLabelProvider_count_format, matchCount); coloredName += " "; coloredName += countInfo; return coloredName; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object) */ @Override public Image getImage(Object element) { if (element instanceof LineElement) { return fLineMatchImage; } if (!(element instanceof IResource)) { return null; } IResource resource = (IResource) element; Image image = fLabelProvider.getImage(resource); return image; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.BaseLabelProvider#dispose() */ @Override public void dispose() { super.dispose(); fLabelProvider.dispose(); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.BaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String) */ @Override public boolean isLabelProperty(Object element, String property) { return fLabelProvider.isLabelProperty(element, property); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.BaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener) */ @Override public void removeListener(ILabelProviderListener listener) { super.removeListener(listener); fLabelProvider.removeListener(listener); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.BaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener) */ @Override public void addListener(ILabelProviderListener listener) { super.addListener(listener); fLabelProvider.addListener(listener); } // private static String decorateColoredString(String string, String decorated, Styler color) { // String label= string.toString(); // int originalStart= decorated.indexOf(label); // if (originalStart == -1) { // return new String(decorated); // the decorator did something wild // } // if (originalStart > 0) { // String newString= new String(decorated.substring(0, originalStart), color); // newString += string; // string= newString; // } // if (decorated.length() > originalStart + label.length()) { // decorator appended something // return string.append(decorated.substring(originalStart + label.length()), color); // } // return string; // no change // } }