Гррр так близко, но все еще терпит неудачу ...
Я отображаю это дерево во Flex, которое содержит два типа узлов:
- Обычные узлы, которые обычно отображаются как текст (потому что они есть!)
- Богатые (HTML) узлы - вот где все искажается
Обратите внимание, что моя проблема в том, что когда я динамически добавляю новый (HTML) узел к моему дереву.
Итак ... Как отобразить узлы HTML?
- Я подкласс TreeItemRenderer
- В этом подклассе я переопределяю set data () и добавляю текстовый дочерний элемент для моего рендерера
Поэтому у меня теперь есть:
[иконка] [метка]
[текстовый компонент]
Почему?
Метка по умолчанию - это чистый текстовый компонент, не поддерживающий HTML, поэтому дополнительный компонент: я хочу отобразить нового парня и забыть метку по умолчанию.
- (продолжение) Я переопределяю
updateDisplayList()
и, если узел богатый, я устанавливаю высоту метки на ноль, устанавливаю x и y моего компонента на label'x и и y.
Так ... что мне не хватает? Ах, да: мне нужно установить высоту моего узла, поскольку текст HTML может быть больше или меньше, чем его текстовый аналог.
- (продолжение) Я переопределяю
measure()
- Если мой узел не богатый, я просто вызываю super.measure () и возвращаю
- Если оно равно , то я задаю ширину моего html-компонента (htmlComponent.width =licitWidth - super.label.x;) и его высота должна автоматически вычисляться.
Это дает мне довольно надежный ненадежный результат!
Когда я складываю / разворачиваю свое дерево, каждый раз, кажется, я получаю правильную высоту для моего HTML-узла. В другой раз я получаю высоту '4', которая является только заполнением компонента HTML без содержимого.
Я знаю, что я должен делать что-то довольно глупое здесь ... но я не уверен, что. Я опубликую свой код, если мой бессвязный текст слишком бессвязен, чтобы что-то понимать ...
**** РЕДАКТИРОВАТЬ: вот исходный код моего рендерера
Как видите, только узлы 'notes' используют HTML.
Я добавляю дочерний элемент htmlComponent, который будет отображать форматированный текст, в то время как метка по умолчанию имеет нулевой размер и исчезает.
Это определенно очень сырой код, так как он в процессе!
package com.voilaweb.tfd
{
import mx.collections.*;
import mx.controls.Text;
import mx.controls.treeClasses.*;
import mx.core.UITextField;
import mx.core.UIComponent;
import flash.text.TextLineMetrics;
public class OutlinerRenderer extends TreeItemRenderer
{
private function get is_note():Boolean
{
return ('outlinerNodeNote' == XML(super.data).name().localName);
}
override public function set data(value:Object):void
{
super.data = value;
var htmlComponent:Text = super.getChildByName("htmlComponent") as Text;
if(!htmlComponent)
{
htmlComponent = new Text();
htmlComponent.name = "htmlComponent";
addChild(htmlComponent);
}
if(is_note)
htmlComponent.htmlText = XML(super.data).attribute('nodeText');
else
htmlComponent.htmlText = null;
setStyle('verticalAlign', 'top');
}
/*
* Today we've learnt a valuable lesson: there is no guarantee of when createChildren() will be invoked.
* Better be dirty and add children in set data()
override protected function createChildren():void
{
super.createChildren();
var htmlComponent:Text = new Text();
htmlComponent.name = "htmlComponent";
addChild(htmlComponent);
}
*/
override protected function measure():void
{
if(is_note)
{
super.measure();
var htmlComponent:Text = super.getChildByName("htmlComponent") as Text;
//Setting the width of the description field
//causes the height calculation to happen
htmlComponent.width = explicitWidth - super.label.x;
//We add the measuredHeight to the renderers measured height
//measuredHeight += (htmlComponent.measuredHeight - label.measuredHeight);
// Note the silly trick here...hopefully in the future I figure out how to avoid it
//
// Here is what happens: we check if measuredHeight is equal to decoration such as margin, insets...rather than that + some height
// If so, then we need to come up with an actual height which we do by adding textHeight to this height
// Note that I care about text being equal to margin etc but do not have proper access to these
// For instance UITextField.TEXT_HEIGHT_PADDING == 4 but is not accessible
// I am going to check if "<10" that will cover this case...
trace("For text " + htmlComponent.htmlText);
trace("width = " + htmlComponent.getExplicitOrMeasuredWidth()+" x height = " + htmlComponent.getExplicitOrMeasuredHeight());
var m:TextLineMetrics = htmlComponent.measureHTMLText(htmlComponent.htmlText);
//if(10 > htmlComponent.measuredHeight && !isNaN(htmlComponent.explicitHeight))
//htmlComponent.explicitHeight = m.height + htmlComponent.measuredHeight;
//if(htmlComponent.measuredHeight < 10) htmlComponent.explicitHeight = 50;
//measuredHeight += (htmlComponent.getExplicitOrMeasuredHeight() - super.label.getExplicitOrMeasuredHeight());
measuredHeight += (htmlComponent.getExplicitOrMeasuredHeight() - label.getExplicitOrMeasuredHeight());
trace("m:"+m.height+" Height: " + htmlComponent.getExplicitOrMeasuredHeight());
}
else
{
super.measure();
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
label.height = label.getExplicitOrMeasuredHeight(); // If you tell me my height, then I shall use my variable height!
graphics.clear();
if(is_note)
{
label.height = 0;
var htmlComponent:Text = super.getChildByName("htmlComponent") as Text;
htmlComponent.x = label.x;
htmlComponent.y = label.y;
htmlComponent.height = htmlComponent.getExplicitOrMeasuredHeight();
graphics.beginFill(0x555555);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
}
var complete:XMLList = XML(super.data).attribute('complete');
if(complete.length() > 0 && true == complete[0])
{
var startx:Number = data ? TreeListData(listData).indent : 0;
if(disclosureIcon)
startx += disclosureIcon.measuredWidth;
if(icon)
startx += icon.measuredWidth;
graphics.lineStyle(3, getStyle("color"));
var y:Number = label.y + label.getExplicitOrMeasuredHeight() / 2;
graphics.moveTo(startx, y);
graphics.lineTo(startx + label.getExplicitOrMeasuredWidth(), y);
}
}
}
}