Wrapping HTML text in a StreamResource for Tree nodes not working as hoped

Hi,

I am using ITMill 5.3.0-rc12 under Ubuntu 8.04, with FireFox 3.05.

I am trying to use the Tree function:

setItemIcon(Object itemId, Resource icon);

as a way of rendering HTML in a Tree node. I tried to wrap the HTML text inside a Resource via the following class: HtmlResource, and tried it in the test application, TestHtmlResourceTree (see below). Nothing is rendered in FireFox. In IE7, I only get a red cross in a box, indicating the resource cannot be found. Can you provide any advice/help on where I might be going wrong ?

Thanks
Andrew

HtmlResource.java


package itmill.testcases;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import com.itmill.toolkit.Application;
import com.itmill.toolkit.terminal.StreamResource;

/**
 * Map HTML text to a Resource.
 */
public class HtmlResource extends StreamResource
{
	public HtmlResource(final String htmlText, final Application application)
			throws IOException
	{
		// Use hashCode as a the cache key
		super(make(htmlText, application), "HtmlResource-"
				+ htmlText.hashCode(), application);
	}

	@Override
	public String getMIMEType()
	{
		return "text/html";
	}

	private static HtmlTextStream make(String htmlText, Application application)
			throws IOException
	{
		final ByteArrayOutputStream out = new ByteArrayOutputStream();
		out.write(htmlText.getBytes());
		final ByteArrayInputStream inputStream = new ByteArrayInputStream(out
				.toByteArray());
		final HtmlTextStream stream = new HtmlTextStream(inputStream);
		return stream;
	}

	/**
	 * Helper class to map an InputStream to a StreamResource.StreamSource.
	 */
	private static class HtmlTextStream implements StreamResource.StreamSource
	{
		private InputStream inputStream;

		public HtmlTextStream(InputStream inputStream)
		{
			super();
			this.inputStream = inputStream;
		}

		public InputStream getStream()
		{
			return inputStream;
		}
	}
}

TestHtmlResourceTree.java



package itmill.testcases;

import java.io.IOException;

import com.itmill.toolkit.Application;
import com.itmill.toolkit.ui.AbstractSelect;
import com.itmill.toolkit.ui.Component;
import com.itmill.toolkit.ui.Panel;
import com.itmill.toolkit.ui.SplitPanel;
import com.itmill.toolkit.ui.TextField;
import com.itmill.toolkit.ui.Tree;
import com.itmill.toolkit.ui.VerticalLayout;
import com.itmill.toolkit.ui.Window;

public class TestHtmlResourceTree extends Application
{
	private static final String NODE_CAPTION = "CaptionText";

	private Window rootWindow = new Window("Main Test Window");

	public final void init()
	{
		setMainWindow(rootWindow);
		initializeComponents();
	}

	private void initializeComponents()
	{
		rootWindow.removeAllComponents();
		rootWindow.getLayout().setHeight("100%");

		rootWindow.setStyleName(Panel.STYLE_LIGHT);

		SplitPanel splitPanel = new SplitPanel(
				SplitPanel.ORIENTATION_HORIZONTAL);

		splitPanel.setFirstComponent(addLeftPanel());
		splitPanel.setSecondComponent(addRightPanel());
		// Left pane uses 20%
		splitPanel.setSplitPosition(20);
		rootWindow.addComponent(splitPanel);
		splitPanel.setSizeFull();
	}

	private Component addLeftPanel()
	{
		// Tree with a few items
		Tree tree = new Tree();
		tree.setDebugId("mytree");
		tree.setImmediate(true);
		tree.setItemCaptionMode(AbstractSelect.ITEM_CAPTION_MODE_EXPLICIT);

		addCaptionedItem(tree, "root", null, 0);
		tree.addItem();
		for (int i = 1; i < 7; i++)
		{
			addCaptionedItem(tree, NODE_CAPTION + "-1-" + i, 0, i);
			for (int j = i * 10; j < i * 10 + 3; j++)
			{
				addCaptionedItem(tree, NODE_CAPTION + "-2-" + j, i, j);
				for (int k = j * 10; k < j * 10 + 3; k++)
				{
					addCaptionedItem(tree, NODE_CAPTION + "-3-" + k, j, k);
					for (int m = k * 10; m < k * 10 + 3; m++)
					{
						addCaptionedItem(tree, NODE_CAPTION + "-4-" + m, k, m);
					}
				}
			}
		}
		tree.expandItemsRecursively(0);

		Panel treePanel = makePanel();
		VerticalLayout layout = new VerticalLayout();
		treePanel.setSizeFull();
		treePanel.getLayout().setSizeUndefined();
		treePanel.setStyleName(Panel.STYLE_LIGHT);
		treePanel.addComponent(tree);
		layout.addComponent(treePanel);
		layout.setExpandRatio(treePanel, 1);

		return treePanel;
	}

	private void addCaptionedItem(Tree tree, String caption, Integer parentKey,
			Integer key)
	{
		tree.addItem(key);
		tree.setChildrenAllowed(key, true);
		tree.setItemCaption(key, caption);
		try
		{
//			tree.setItemIcon(key, new HtmlResource("<ul>Underlined</ul>",
//					this));
			tree.setItemIcon(key, new HtmlResource("<html><body><ul>Underlined</ul></body></html>",
					this));
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		if (null != parentKey)
		{
			tree.setParent(key, parentKey);
		}
	}

	private Component addRightPanel()
	{
		Panel panel1 = makePanel();

		TextField tf = new TextField("Write some text ...");
		tf.setDebugId("AreaTextField");
		tf.setColumns(15);
		tf.setRows(5);
		tf.setImmediate(true);
		panel1.addComponent(tf);

		return panel1;
	}

	private Panel makePanel()
	{
		Panel panel = new Panel();
		panel.setStyleName(Panel.STYLE_LIGHT);
		return panel;
	}
}

Hi,

I think that you cannot put HTML content as an icon in a tree at all. You can only provide content (with proper content type) that browsers understand to be an image. That is png, jpeg, gif, etc…

Sami,

Thanks for the quick response (even if it wasn’t quite what I was hoping for !).

I had one other related problem which I hope you may know the answer to - if I do put an normal Icon Image on a tree node, a long caption text following the Icon causes a line break between the icon and caption text, so that the caption appears on the next line down in the node - like wrapping after the icon. This happens even if i have a horizontal scrollbar enabled - as in my example code.

Is there any way you know of (for example some style setting), to force the caption text following the icon, to remain on the same line as the icon, and the scrollbar to be activated instead ?

Thanks
Andrew

I’m not entirely sure whether this fixes your problem, but you could try as a first remedy to use the following CSS in your custom theme:

.i-tree-node {
  white-space: nowrap;
}

This would work, if it’s just a normal text-wrap problem. If it’s a problem with the
entire
text being wrapped due to one/both of either icon or node text being a div, you might need to make the div(s) be rendered as inline. But that would sound like a bug to me, if this is the case.

Hi,

I fixed the “line break”, by modifying ITree.java, so that the Tree caption is placed in a single DIV - the caption was in a DIV of its’ own, causing the browser to think it was ok to wrap it after the icon.

I also changed ITree.java to swap the order of the caption icon and text (text is now to the left, icon is now to the right).

Thanks
Andrew