### Eclipse Workspace Patch 1.0 #P org.eclipse.jface.snippets Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.snippets/META-INF/MANIFEST.MF,v retrieving revision 1.1 diff -u -r1.1 MANIFEST.MF --- META-INF/MANIFEST.MF 11 Sep 2006 15:19:15 -0000 1.1 +++ META-INF/MANIFEST.MF 26 Jun 2007 21:53:59 -0000 @@ -6,4 +6,5 @@ Bundle-Vendor: Eclipse.org Require-Bundle: org.eclipse.jface, org.eclipse.jface.databinding, - org.eclipse.core.runtime + org.eclipse.core.runtime, + org.eclipse.jface.text Index: Eclipse JFace Snippets/org/eclipse/jface/snippets/viewers/Snippet042StyleRangeProviderFull.java =================================================================== RCS file: Eclipse JFace Snippets/org/eclipse/jface/snippets/viewers/Snippet042StyleRangeProviderFull.java diff -N Eclipse JFace Snippets/org/eclipse/jface/snippets/viewers/Snippet042StyleRangeProviderFull.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Eclipse JFace Snippets/org/eclipse/jface/snippets/viewers/Snippet042StyleRangeProviderFull.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,283 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 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.eclipse.jface.snippets.viewers; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ColumnPixelData; +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITableColorProvider; +import org.eclipse.jface.viewers.ITableFontProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.OwnerDrawLabelProvider; +import org.eclipse.jface.viewers.StyledTextCellLabelProvider; +import org.eclipse.jface.viewers.StyledTextSupport; +import org.eclipse.jface.viewers.TableLayout; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; + +/** + * A TableViewer using a StyleRangeLabelProvider to show some of the + * posibilities: + * + * + * @author Michael Krkoska + */ +public class Snippet042StyleRangeProviderFull { + + private static final String[] TEXT = new String[] { + "TextStyle defines a set of styles that can be\n" + + "applied to a range of text. The hashCode() method\n" + + "in this class uses the values of the public fields to", + "compute the hash value.\uFFFC When storing instances\n" + + "of the class in hashed collections do not modify\n" + + "these fields after the object has been inserted.", + "Application code does not need to explicitly\n" + + "release the resources managed and thus no\n" + + "dispose() method is provided.\uFFFC", }; + private static final Pattern METHODS = Pattern.compile("\\w+\\(\\)"); + private static final int SHELL_WIDTH = 640; + private static final Display DISPLAY = Display.getDefault(); + private static int IMAGE_SIZE = 16; + private static final Image IMAGE1 = new Image(DISPLAY, DISPLAY + .getSystemImage(SWT.ICON_WARNING).getImageData().scaledTo( + IMAGE_SIZE, IMAGE_SIZE)); + private static final Image IMAGE2 = new Image(DISPLAY, DISPLAY + .getSystemImage(SWT.ICON_ERROR).getImageData().scaledTo(IMAGE_SIZE, + IMAGE_SIZE)); + + public static void main(String[] args) { + + Shell shell = new Shell(DISPLAY, SWT.CLOSE); + shell.setSize(SHELL_WIDTH, 300); + shell.setLayout(new GridLayout(2, false)); + + Snippet042StyleRangeProviderFull example = new Snippet042StyleRangeProviderFull(); + example.createPartControl(shell); + + shell.open(); + + while (!shell.isDisposed()) { + if (!DISPLAY.readAndDispatch()) { + DISPLAY.sleep(); + } + } + DISPLAY.dispose(); + } + + private TableViewer viewer; + + private Text text; + + public Snippet042StyleRangeProviderFull() { + int defaultSize = JFaceResources.getDefaultFontDescriptor() + .getFontData()[0].getHeight(); + JFaceResources.getFontRegistry().put( + "Courier", + new FontData[] { new FontData("Courier New", defaultSize, + SWT.NORMAL) }); + FontData[] fontData = JFaceResources.getFontRegistry() + .defaultFontDescriptor().getFontData(); + fontData[0].setHeight(fontData[0].getHeight() + 2); + JFaceResources.getFontRegistry().put("BiggerDefault", fontData); + } + + public void createPartControl(Composite parent) { + Label label = new Label(parent, SWT.NONE); + label.setText("type something here:"); + + text = new Text(parent, SWT.NONE); + text.setText("hash"); + text.setSelection(0, 4); + text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + text.addListener(SWT.Modify, new Listener() { + + public void handleEvent(Event event) { + viewer.refresh(); + } + }); + + // SWT.FULL_SELECTION is needed on win32 as long as Bug 168807 exists + viewer = new TableViewer(parent, SWT.FULL_SELECTION); + + GridData data = new GridData(GridData.GRAB_HORIZONTAL + | GridData.GRAB_VERTICAL | GridData.FILL_BOTH); + data.horizontalSpan = 2; + viewer.getControl().setLayoutData(data); + + viewer.setContentProvider(new ArrayContentProvider()); + createColumns(); + + OwnerDrawLabelProvider.setUpOwnerDraw(viewer); + viewer.setInput(TEXT); + } + + private void createColumns() { + TableLayout layout = new TableLayout(); + viewer.getTable().setLayout(layout); + viewer.getTable().setHeaderVisible(true); + viewer.getTable().setLinesVisible(true); + + int width = SHELL_WIDTH - 2 * 5 + - viewer.getTable().getShell().computeTrim(0, 0, 0, 0).width; + int width1 = width / 2; + int width2 = width - width1; + + TableViewerColumn tc = new TableViewerColumn(viewer, SWT.NONE); + tc.getColumn().setText("col1"); + layout.addColumnData(new ColumnPixelData(width1)); + tc.setLabelProvider(new MyStyleRangeLabelProviderCol1(viewer, + new MyStyledFontSupport())); + + tc = new TableViewerColumn(viewer, SWT.NONE); + tc.getColumn().setText("col2"); + layout.addColumnData(new ColumnPixelData(width2)); + tc.setLabelProvider(new MyStyleRangeLabelProviderCol2(viewer, + new MyStyledFontSupport())); + } + + private class MyStyledFontSupport extends StyledTextSupport { + + public StyleRange[] getStyleRanges(Object element, String label) { + String searchText = text.getText(); + TextPresentation tp = new TextPresentation(); + if (searchText.length() > 0) { + Color yellow = text.getDisplay().getSystemColor( + SWT.COLOR_YELLOW); + int index = -1; + while ((index = label.indexOf(searchText, index + 1)) >= 0) { + StyleRange styleRange = new StyleRange(index, searchText + .length(), null, yellow); + tp.mergeStyleRange(styleRange); + } + } + + Font courier = JFaceResources.getFont("Courier"); + Matcher matcher = METHODS.matcher(label); + while (matcher.find()) { + StyleRange styleRange = new StyleRange(matcher.start(), matcher + .end() + - matcher.start(), null, null); + styleRange.font = courier; + tp.mergeStyleRange(styleRange); + } + + List ranges = new ArrayList(); + for (Iterator iterator = tp.getAllStyleRangeIterator(); iterator + .hasNext();) { + ranges.add(iterator.next()); + } + return (StyleRange[]) ranges.toArray(new StyleRange[ranges.size()]); + } + + } + + private final class MyStyleRangeLabelProviderCol1 extends + StyledTextCellLabelProvider { + + private MyStyleRangeLabelProviderCol1(ColumnViewer viewer, + StyledTextSupport fontSupport) { + super(viewer, fontSupport); + } + + public Color getBackground(Object element) { + return null; + } + + public Image getImage(Object element) { + return IMAGE1; + } + + public String getText(Object element) { + return element.toString(); + } + + public Font getFont(Object element) { + if (element == TEXT[0]) { + return JFaceResources.getFont("BiggerDefault"); + } + return null; + } + + public Color getForeground(Object element) { + if (element == TEXT[1]) { + return DISPLAY.getSystemColor(SWT.COLOR_DARK_RED); + } + return null; + } + } + + private final class MyStyleRangeLabelProviderCol2 extends + StyledTextCellLabelProvider { + + private MyStyleRangeLabelProviderCol2(ColumnViewer viewer, + StyledTextSupport fontSupport) { + super(viewer, fontSupport); + } + + public Color getBackground(Object element) { + return null; + } + + public Image getImage(Object element) { + return IMAGE2; + } + + public String getText(Object element) { + return element.toString(); + } + + public Font getFont(Object element) { + if (element == TEXT[1]) { + return JFaceResources.getFont("BiggerDefault"); + } + return null; + } + + public Color getForeground(Object element) { + if (element == TEXT[2]) { + return DISPLAY.getSystemColor(SWT.COLOR_DARK_RED); + } + return null; + } + } + +} #P org.eclipse.jface Index: src/org/eclipse/jface/viewers/StyledTextSupport.java =================================================================== RCS file: src/org/eclipse/jface/viewers/StyledTextSupport.java diff -N src/org/eclipse/jface/viewers/StyledTextSupport.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jface/viewers/StyledTextSupport.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,323 @@ +/******************************************************************************* + * Copyright (c) 2007 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.eclipse.jface.viewers; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Device; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.GlyphMetrics; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.graphics.TextLayout; +import org.eclipse.swt.graphics.TextStyle; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; + +/** + * @since 3.3 + * + */ +public abstract class StyledTextSupport { + /** + * This is the char which can be used as placeholder for an image in the + * label. + */ + public static final char IMAGE_PLACEHOLDER = '\uFFFC'; + + /** + * Style constant for centering the viewer's items vertically if their + * heights are less than the maximum vertical height. + */ + public static final int CENTER_ITEMS_VERTICALLY = 1; + /** + * Style constant for centering the text of a viewer's item vertically if + * its height is less than the height of the item's image. + */ + public static final int CENTER_TEXT_VERTICALLY = 2; + + boolean centerItemsVertically = false; + boolean centerTextVertically = false; + + private Map styledFonts = new HashMap(); + + /** + * Returns an array of StyleRange instances which are to be applied to the + * label. + * + * @param element + * The element whose label is going to be displayed + * @param label + * The label for which to provide the StyleRanges + * @return An array of StyleRange instances, may be null if no styles are to + * be applied for this label. + */ + public abstract StyleRange[] getStyleRanges(Object element, String label); + + /** + * Creates a TextLayout instance for either measuring or painting the item, + * using the StyleRanges supplied by + * {@link StyledTextSupport#getStyleRanges(Object, String)}. + * + * Adds an image at the first occurence of + * {@link StyledTextSupport#IMAGE_PLACEHOLDER} or at the beginning of the + * label. + * + * @param event + * the measure or paint event for which a TextLayout is needed + * @param label + * the label to display. + * @param image + * the image to display. May be null. + * @param defaultFont + * the default font for the label. If null the system default + * font is used. + * @param defaultBackground + * the default background color. May be null. + * @param element + * the model element used to obtain label and styles. + * @return a TextLayout instance which must be disposed after use. + */ + protected TextLayout createTextLayout(Event event, String label, + Image image, Font defaultFont, Color defaultBackground, + Object element) { + + Display display = event.display; + TextLayout layout = new TextLayout(display); + + int maxFontHeight = 0; + if (defaultFont != null) { + layout.setFont(defaultFont); + maxFontHeight = getFontHeight(defaultFont); + } else { + maxFontHeight = getFontHeight(display.getSystemFont()); + } + + int rangeOffset = 0, imageOffset = 0; + GlyphMetrics imageMetrics = null; + TextStyle imageStyle = null; + if (image != null) { + int index = label.indexOf(IMAGE_PLACEHOLDER); + String labelWithImage = label; + if (index < 0) { + labelWithImage = IMAGE_PLACEHOLDER + " " + label; //$NON-NLS-1$ + rangeOffset = 2; + } + layout.setText(labelWithImage); + imageOffset = Math.max(0, index); + Rectangle bounds = image.getBounds(); + imageStyle = new TextStyle(null, null, null); + imageMetrics = new GlyphMetrics(bounds.height, 0, bounds.width); + imageStyle.metrics = imageMetrics; + } else { + layout.setText(label); + } + + StyleRange[] styleRanges = getStyleRanges(element, label); + if (styleRanges != null) { + for (int i = 0; i < styleRanges.length; i++) { + StyleRange styleRange = styleRanges[i]; + checkFont(display, styleRange); + layout.setStyle(styleRange, styleRange.start + rangeOffset, + styleRange.start + rangeOffset + styleRange.length - 1); + if (styleRange.font != null) { + maxFontHeight = Math.max(maxFontHeight, + getFontHeight(styleRange.font)); + } + } + } + + if (imageStyle != null) { + layout.setStyle(imageStyle, imageOffset, imageOffset); + } + + if (centerTextVertically && imageMetrics != null) { + int lineCount = layout.getLineCount(); + if (lineCount == 1 && imageMetrics.ascent > maxFontHeight) { + // vertically center the text if there is an image bigger than + // the text. + int height = imageMetrics.ascent; + int space = (height - maxFontHeight); + imageMetrics.ascent = (maxFontHeight) + Math.round(space / 2f); + // TODO why does it look better (at least on win xp) with this + // added pixel? + layout.setDescent(height - imageMetrics.ascent + 1); + } + + } + + if (defaultBackground != null) { + int[] ranges = layout.getRanges(); + int oldEnd = -1; + TextStyle[] styles = layout.getStyles(); + for (int i = 0, length = ranges.length; i < length; i += 2) { + int start = ranges[i]; + int end = ranges[i + 1]; + if (start > oldEnd + 1) { + TextStyle style = new TextStyle(null, null, + defaultBackground); + layout.setStyle(style, oldEnd + 1, start - 1); + } + + TextStyle style = styles[i >> 1]; + if (style.background == null) { + style.background = defaultBackground; + layout.setStyle(style, start, end); + } + + oldEnd = end; + } + if (layout.getText().length() > oldEnd + 1) { + TextStyle style = new TextStyle(null, null, defaultBackground); + layout.setStyle(style, oldEnd + 1, + layout.getText().length() - 1); + } + } + + return layout; + } + + /** + * Handle the erase event. The default implementation does nothing to ensure + * keep native selection highlighting working. + * + * @param event + * the erase event + * @param element + * the model object + * @see SWT#EraseItem + */ + protected void erase(Event event, Object element) { + event.detail &= ~SWT.FOREGROUND; + } + + /** + * @param event + * @param element + * @param viewerLabel + */ + protected void measure(Event event, Object element, ViewerLabel viewerLabel) { + String label = viewerLabel.getText(); + Image image = viewerLabel.getImage(); + Font font = viewerLabel.getFont(); + Color defaultBackground = viewerLabel.getBackground(); + TextLayout textLayout = createTextLayout(event, label, image, font, + defaultBackground, element); + Rectangle bounds = textLayout.getBounds(); + event.setBounds(new Rectangle(0, 0, bounds.width, bounds.height)); + textLayout.dispose(); + } + + /** + * @param event + * @param element + * @param viewerLabel + */ + protected void paint(Event event, Object element, ViewerLabel viewerLabel) { + String label = viewerLabel.getText(); + Image image = viewerLabel.getImage(); + Font font = viewerLabel.getFont(); + Color defaultBackground = viewerLabel.getBackground(); + TextLayout textLayout = createTextLayout(event, label, image, font, + defaultBackground, element); + GC gc = event.gc; + Color oldForeground = gc.getForeground(), oldBackground = gc + .getBackground(); + Color foreground = viewerLabel.getForeground(); + if (foreground != null) { + gc.setForeground(foreground); + } + + if (defaultBackground != null) { + gc.setBackground(defaultBackground); + } + + int heightOffset = 0; + if (centerItemsVertically) { + heightOffset = (event.height - textLayout.getBounds().height) / 2; + heightOffset = Math.max(0, heightOffset); + } + + textLayout.draw(gc, event.x, event.y + heightOffset); + + if (image != null) { + int imageOffset = Math.max(0, label.indexOf(IMAGE_PLACEHOLDER)); + int lineIndex = textLayout.getLineIndex(imageOffset); + FontMetrics lineMetrics = textLayout.getLineMetrics(lineIndex); + Point point = textLayout.getLocation(imageOffset, false); + GlyphMetrics glyphMetrics = textLayout.getStyle(imageOffset).metrics; + int y = event.y + point.y + lineMetrics.getAscent() + - glyphMetrics.ascent + heightOffset; + // Following line is because of a strange incorrect measurement of 3 + // pixels under win32 in some cases. + y = Math.max(event.y, y); + gc.drawImage(image, event.x + point.x, y); + } + textLayout.dispose(); + + gc.setForeground(oldForeground); + gc.setBackground(oldBackground); + } + + int getFontHeight(Font font) { + int h = 0; + FontData[] fontData = font.getFontData(); + for (int i = 0; i < fontData.length; i++) { + h = Math.max(h, (int) fontData[i].height); + } + return h; + } + + private void checkFont(Device device, StyleRange styleRange) { + int fontStyle = styleRange.fontStyle; + if (fontStyle != SWT.NORMAL) { + Font font = styleRange.font; + if (font == null) { + font = JFaceResources.getDefaultFont(); + } + boolean wrongStyle = false; + FontData[] fontData = font.getFontData(); + for (int i = 0, length = fontData.length; i < length && !wrongStyle; i++) { + if (fontData[i].getStyle() != fontStyle) { + wrongStyle = true; + } + } + if (wrongStyle) { + fontData = getFontData(font, fontStyle); + // TODO using fontData[0] as cache key might be wrong on motif + Font styledFont = (Font) styledFonts.get(fontData[0]); + if (styledFont == null) { + styledFont = new Font(device, fontData); + styledFonts.put(fontData[0], styledFont); + } + } + styleRange.font = font; + } + } + + private FontData[] getFontData(Font font, int style) { + FontData[] fontDatas = font.getFontData(); + for (int i = 0; i < fontDatas.length; i++) { + fontDatas[i].setStyle(style); + } + return fontDatas; + } +} Index: src/org/eclipse/jface/viewers/StyledTextCellLabelProvider.java =================================================================== RCS file: src/org/eclipse/jface/viewers/StyledTextCellLabelProvider.java diff -N src/org/eclipse/jface/viewers/StyledTextCellLabelProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jface/viewers/StyledTextCellLabelProvider.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2007 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.eclipse.jface.viewers; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Event; + +/** + * @since 3.3 + * + */ +public class StyledTextCellLabelProvider extends OwnerDrawLabelProvider implements ILabelProvider, IFontProvider, IColorProvider { + private ColumnViewer viewer; + + private StyledTextSupport support; + + /** + * @param viewer + * @param support + */ + public StyledTextCellLabelProvider(ColumnViewer viewer, StyledTextSupport support) { + super(); + this.viewer = viewer; + this.support = support; + } + + protected void measure(Event event, Object element) { + ViewerCell cell = viewer.getViewerRowFromItem(event.item).getCell(event.index); + + ViewerLabel viewerLabel = new ViewerLabel(cell.getText(), cell.getImage()); + viewerLabel.setImage(getImage(element)); + viewerLabel.setText(getText(element)); + viewerLabel.setFont(getFont(element)); + viewerLabel.setBackground(getBackground(element)); + viewerLabel.setForeground(getForeground(element)); + support.measure(event, element, viewerLabel); + } + + protected void paint(Event event, Object element) { + ViewerCell cell = viewer.getViewerRowFromItem(event.item).getCell(event.index); + + ViewerLabel viewerLabel = new ViewerLabel(cell.getText(), cell.getImage()); + viewerLabel.setImage(getImage(element)); + viewerLabel.setText(getText(element)); + viewerLabel.setFont(getFont(element)); + viewerLabel.setBackground(getBackground(element)); + viewerLabel.setForeground(getForeground(element)); + + support.paint(event, element, viewerLabel); + } + + public Image getImage(Object element) { + return null; + } + + public String getText(Object element) { + return ""; //$NON-NLS-1$ + } + + public Font getFont(Object element) { + return null; + } + + public Color getBackground(Object element) { + return null; + } + + public Color getForeground(Object element) { + return null; + } + +}