rendered paste body/*******************************************************************************
* Copyright (c) 2008 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.swt.example;
import java.text.MessageFormat;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
/**
* Owner draw in table with bold style ranges
*/
public class OwnerDrawTreeWithBoldStyles2 {
public static void main(String[] args) {
Display display= new Display();
Shell shell= new Shell(display);
shell.setLayout(new GridLayout(1, false));
Composite composite= new Composite(shell, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
composite.setLayout(new GridLayout(1, false));
final Tree tree= new Tree(composite, SWT.MULTI);
GridData layoutData= new GridData(SWT.FILL, SWT.FILL, true, true);
layoutData.heightHint= 500;
tree.setLayoutData(layoutData);
tree.setLinesVisible(true);
tree.setHeaderVisible(true);
Color color= display.getSystemColor(SWT.COLOR_DARK_RED);
FontData[] boldFontData= getModifiedFontData(tree.getFont().getFontData(), SWT.BOLD);
Font boldFont = new Font(Display.getCurrent(), boldFontData);
String itemBaseLabel= "MY_BIG_BOLD_ITEM";
for (int i= 0; i < 10000; i++) {
TreeItem item= new TreeItem(tree, SWT.NONE);
item.setText(0, MessageFormat.format("{0} {1}{1}{1}", new Object[] { itemBaseLabel, new Integer(i) }));
StyleRange styleRange= new StyleRange();
styleRange.start= 0;
styleRange.length= itemBaseLabel.length();
styleRange.font= boldFont;
styleRange.foreground= color;
TreeOwnerDrawSupport.storeStyleRanges(item, 0, new StyleRange[] { styleRange });
}
TreeOwnerDrawSupport.install(tree);
Button button= new Button(composite, SWT.PUSH);
button.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
button.setText("Refresh");
button.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
long start= System.currentTimeMillis();
TreeItem[] items= tree.getItems();
for (int i= 0; i < 5000; i++) {
tree.setTopItem(items[i]);
}
long end= System.currentTimeMillis();
System.out.println(end - start);
}
@Override
public void widgetSelected(SelectionEvent e) {
widgetDefaultSelected(e);
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
boldFont.dispose();
}
private static FontData[] getModifiedFontData(FontData[] originalData, int additionalStyle) {
FontData[] styleData = new FontData[originalData.length];
for (int i = 0; i < styleData.length; i++) {
FontData base = originalData[i];
styleData[i] = new FontData(base.getName(), base.getHeight(), base.getStyle() | additionalStyle);
}
return styleData;
}
private static class TreeOwnerDrawSupport implements Listener {
private static final String STYLED_RANGES_KEY= "styled_ranges"; //$NON-NLS-1$
private TextLayout fLayout;
public static void install(Tree table) {
TreeOwnerDrawSupport listener= new TreeOwnerDrawSupport(table);
table.addListener(SWT.Dispose, listener);
table.addListener(SWT.MeasureItem, listener);
table.addListener(SWT.EraseItem, listener);
table.addListener(SWT.PaintItem, listener);
}
/**
* Stores the styled ranges in the given table item.
*
* @param item table item
* @param column the column index
* @param ranges the styled ranges or <code>null</code> to remove them
*/
public static void storeStyleRanges(TreeItem item, int column, StyleRange[] ranges) {
item.setData(STYLED_RANGES_KEY + column, ranges);
}
/**
* Returns the styled ranges which are stored in the given table item.
*
* @param item table item
* @param column the column index
* @return the styled ranges
*/
private static StyleRange[] getStyledRanges(TreeItem item, int column) {
return (StyleRange[])item.getData(STYLED_RANGES_KEY + column);
}
private TreeOwnerDrawSupport(Tree table) {
int orientation= table.getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
fLayout= new TextLayout(table.getDisplay());
fLayout.setOrientation(orientation);
}
/*
* @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
*/
public void handleEvent(Event event) {
switch (event.type) {
case SWT.MeasureItem:
performMeasure(event);
break;
case SWT.EraseItem:
performErase(event);
break;
case SWT.PaintItem:
performPaint(event);
break;
case SWT.Dispose:
widgetDisposed();
break;
}
}
/**
* Performs the measure operation.
*
* @param event the event
*/
private void performMeasure(Event event) {
TreeItem item= (TreeItem) event.item;
fLayout.setFont(item.getFont(event.index));
fLayout.setText(""); //$NON-NLS-1$
fLayout.setText(item.getText(event.index));
int originalTextWidth= fLayout.getBounds().width;
boolean containsOtherFont= false;
StyleRange[] ranges= getStyledRanges(item, event.index);
if (ranges != null) {
for (int i= 0; i < ranges.length; i++) {
StyleRange curr= ranges[i];
if (curr.font != null) {
containsOtherFont= true;
}
fLayout.setStyle(curr, curr.start, curr.start + curr.length - 1);
}
}
if (containsOtherFont) {
int textWidthDelta= fLayout.getBounds().width - originalTextWidth;
event.width += textWidthDelta;
}
}
/**
* Performs the erase operation.
*
* @param event the event
*/
private void performErase(Event event) {
event.detail &= ~SWT.FOREGROUND;
}
/**
* Performs the paint operation.
*
* @param event the event
*/
private void performPaint(Event event) {
TreeItem item= (TreeItem) event.item;
GC gc= event.gc;
boolean isSelected= (event.detail & SWT.SELECTED) != 0;
// remember colors to restore the GC later
Color oldForeground = gc.getForeground();
Color oldBackground = gc.getBackground();
if (!isSelected) {
Color foreground= item.getForeground(event.index);
gc.setForeground(foreground);
Color background= item.getBackground(event.index);
gc.setBackground(background);
}
Image image = item.getImage(event.index);
if (image != null) {
Rectangle imageBounds = item.getImageBounds(event.index);
Rectangle bounds = image.getBounds();
int x = imageBounds.x + Math.max(0, (imageBounds.width - bounds.width) / 2);
int y = imageBounds.y + Math.max(0, (imageBounds.height - bounds.height) / 2);
gc.drawImage(image, x, y);
}
Rectangle textBounds = item.getTextBounds(event.index);
if (textBounds != null) {
// fLayout has already been configured in 'performMeasure()'
if (isSelected) {
StyleRange[] ranges= getStyledRanges(item, event.index);
if (ranges != null) {
for (int i= 0; i < ranges.length; i++) {
StyleRange curr= ranges[i];
if (curr.background != null || curr.foreground != null) {
curr= (StyleRange) curr.clone();
curr.background= null;
curr.foreground= null;
fLayout.setStyle(curr, curr.start, curr.start + curr.length - 1);
}
}
}
}
Rectangle layoutBounds = fLayout.getBounds();
int x = textBounds.x;
int y = textBounds.y + Math.max(0, (textBounds.height - layoutBounds.height) / 2);
fLayout.draw(gc, x, y);
}
if ((event.detail & SWT.FOCUSED) != 0) {
Rectangle focusBounds = item.getBounds();
gc.drawFocus(focusBounds.x, focusBounds.y, focusBounds.width, focusBounds.height);
}
if (!isSelected) {
gc.setForeground(oldForeground);
gc.setBackground(oldBackground);
}
}
private void widgetDisposed() {
fLayout.dispose();
}
}
}