Customize TreeItem with RichTextLabel Non-game App

Godot Version

4.2.1

Question

Hello everybody!
I´m creating a non-game App, for robotic purpose, and use Tree Node like a code editor.
I would like to create a custom TreeItem , with a RichTextLabel instead of Label in Godot 4, in order to be able to color params of my instructions as you could see in attached file, but actually TreeItem has simple text and I cannot use bbcode. Please, could you give me some guidance? Or simple example? Thank you very much!

It’s not possible by default.

You can hi-jack some of the functionality to add a RichTextLabel and position it correctly though. It’s quite the hack.

extends Tree


func _ready() -> void:
	# Connect the item_collapsed signal
	item_collapsed.connect(_on_item_collapsed)

	# Create the root item
	var root = create_item()
	root.set_text(0, "ROOT")

	# Create 100 items and set them as custom
	for i in 100:
		var item = create_item(root)
		# Set the cell mode to custom
		item.set_cell_mode(0, TreeItem.CELL_MODE_CUSTOM)
		# Set the custom draw callback
		item.set_custom_draw(0, self, "_custom_draw")
		# Set selectable to true
		item.set_selectable(0, true)
		# Create a RichTextLabel
		var rtl = RichTextLabel.new()
		# Enable its bbcode
		rtl.bbcode_enabled = true
		# The text
		rtl.text = "Hello [b]world[/b] I'm [i]number %s[/i]" % i
		# Ignore the mouse
		rtl.mouse_filter = Control.MOUSE_FILTER_IGNORE
		# Add it to the tree
		add_child(rtl)
		# Set the metadata of the 0 cell to the RichTextLabel node
		item.set_metadata(0, rtl)
		# This just creates some other child items
		for j in randi_range(0, 4):
			var child =create_item(item)
			child.set_text(0, "child %s" % j)


# Our custom_draw callback
func _custom_draw(item:TreeItem, rect:Rect2) -> void:
	# Get the RichTextLabel from the metadata of the item
	var rtl = item.get_metadata(0)
	# If there's metadata and it's a RichTextLabel
	if rtl and rtl is RichTextLabel:
		if item.get_parent().collapsed or not item.visible:
			# Hide it if the parent is collapsed or the item is not visible
			rtl.hide()
		else:
			# Show it and position it correctly otherwise
			rtl.show()
			rtl.position = rect.position + Vector2(0, 4)
			rtl.size = rect.size


func _on_item_collapsed(item: TreeItem) -> void:
	for c in item.get_children():
	# For all the children that have the cell mode to custom
		if c.get_cell_mode(0) == TreeItem.CELL_MODE_CUSTOM:
			# call our callback to hide or show the RichTextLabel if needed
			_custom_draw(c, Rect2())

You’ll also need to disable the Tree scroll functionality and add it into a ScrollContainer to manage scrolling because the _custom_draw() callback is only called for the items that need to be drawn and the RichTextLabels will stick to the top or the bottom when scrolling.

It’s also buggy af so you’ll need to fix the bugs that it adds.

Result:

Honestly, the Tree node is a bit of a mess and working with it is hard and not fun. I find it better to re-do it from scratch myself whenever I need a similar Control with extra functionality.

1 Like

Thank you very much! It works perfectly well, I need to extend same behaviour to drag and drop and will be perfect :slight_smile:
Best regards!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.