All pastes #995870 Raw Edit

OD

public text v1 · immutable
#995870 ·published 2008-04-24 15:23 UTC
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();
		}
	}
}