[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[platform-swt-dev] [Fwd: [Fwd: SWT Tree and Eclipse 3.2 Milestone M6]]

I was hoping someone on this list could help me solve a problem I'm having with the SWT Tree widget. I need to support multi-line display and editing for long lines of text in a TreeItem -- meaning, I need word-wrap in both display and edit and resizing of the tree is preferable at times. Ideally, one could supply the SWT.WRAP bit to the appropriate components. Here is the reference material I've found to-date:

1. Eclipse 3.2 Milestone 6: Custom Draw Tree

2. "Multiple lines in a TreeItem" code snippet

3. [Cell Editors] Support for multiline text cell editor, opened in October 2002 (still unresolved?)

I've attached a modified version of Snippet227 that includes some support for images, word wrap and resizing events -- note Milestone M6 in 3.2 did not include image support. I've only run the code on Windows and I'm having two problems:

1) For each row in the tree, the allotted row height equals the tallest row (e.g., if the tallest row is three text lines tall, then rows with only one line of text will have the same height). Ideally, each row only requires the height reported by the MeasureItem event handler.

2) The height of a row will increase during resizing events that reduce the components width -- to accommodate the additional rows added by word wrap -- but the height of the rows will *not* decrease when the components width decreases -- when word wrap contracts the text into fewer lines. Ideally, the row height would decrease when the component's width also decreases.

I'd like to solve at least one of the two problems; preferably the first. I traced the code with the Eclipse debugger and it appears the 'y' attribute in the 'event' object (responsible for placing the image and text in the custom listener) is being set in some platform-specific SWT API code. I can give references to that platform specific code, if necessary.

Any ideas? Cheers! Travis

 * Copyright (c) 2000, 2006 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.snippets;
 * Tree example snippet: Multiple lines in a TreeItem
 * For a list of all SWT example snippets see
 * http://www.eclipse.org/swt/snippets/
 * @since 3.2

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.FillLayout;
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;

public class Snippet227B {	
	public static void main(String [] args) {
		Display display = new Display();
		Shell shell = new Shell (display);
		shell.setText("Multiple lines in a TreeItem");
		shell.setLayout (new FillLayout());
		final Tree tree = new Tree(shell, SWT.MULTI);

		PaletteData paletteData = new PaletteData(new RGB[] {new RGB(255,0,0)});
		ImageData imageData = new ImageData(16,16,1,paletteData);
		Image image = new Image(display, imageData);

		TreeItem item1 = new TreeItem(tree, SWT.NONE);
		TreeItem item2 = new TreeItem(tree, SWT.NONE);
		TreeItem item3 = new TreeItem(tree, SWT.NONE);
		item3.setText("Three is the successor to two, a crowd and not company, and the first word in a rather long line of text.");
		 * NOTE: MeasureItem, PaintItem and EraseItem are called repeatedly.
		 * Therefore, it is critical for performance that these methods be
		 * as efficient as possible.
		Listener paintListener = new Listener() {
			public void handleEvent(Event event) {
				switch(event.type) {		
					case SWT.MeasureItem: {
						TreeItem item = (TreeItem)event.item;
						String text = getText(item, event.index, event.gc);
						Point size = event.gc.textExtent(text);
						Image image = item.getImage(event.index);
						event.width = size.x + image.getBounds().x + 5;
						event.height = Math.max(image.getBounds().y, Math.max(event.height, size.y));
					case SWT.PaintItem: {
						TreeItem item = (TreeItem)event.item;
						String text = getText(item, event.index, event.gc);
						Point size = event.gc.textExtent(text);
						Image image = item.getImage(event.index);
						int offset1 = image.getBounds().width + 5;
						int offset2 = event.index == 0 ? Math.max(0, (event.height - size.y) / 2) : 0;
						int offset3 = event.index == 0 ? Math.max(0, (event.height - image.getBounds().height) / 2) : 0;
						event.gc.drawImage(image, event.x, event.y + offset3);
						event.gc.drawText(text, event.x + offset1, event.y + offset2, true);
					case SWT.EraseItem: {	
						event.detail &= ~SWT.FOREGROUND;
					case SWT.Resize: {
						Tree tree = (Tree) event.widget;
			String getText(TreeItem item, int column, GC gc) {
				String text = item.getText(column);
				if (column == 0) {
					String[] word = text.split("\\s+");
					int maxWidth = tree.getBounds().width - 5
						// Adjust for the image width.
						- item.getImageBounds(column).width
						// Adjust for the vertical scrollbar width.
						- (item.getParent().getVerticalBar().isVisible() ? 20 : 0);
					text = "";
					for (int i = 0, j = 0, k; i < word.length; i++) {
						k = gc.textExtent(word[i] + " ").x;
						if (j + k >= maxWidth) {
							j = k;
							text += "\n";
						} else {
							j += k;
						text += word[i] + " ";
				return text;
		tree.addListener(SWT.MeasureItem, paintListener);
		tree.addListener(SWT.PaintItem, paintListener);
		tree.addListener(SWT.EraseItem, paintListener);
		tree.addListener(SWT.Resize, paintListener);
		shell.setSize(300, 300);
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) display.sleep();