Visualize a selected part of the UI - similar to the ItemList, but without using it

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Toothgapsy

I am currently working on a project where I use a layer-based system (similar to e.g. photoshop). For this purpose I set up a UI representing those layers. I figured that using an ItemList, this job would be relatively easy. However when initially designing this part, I felt that the ItemList offers very narrow functionality compared to simply working with V/HBoxContainers.
For instance, it is not possible to have more than one icon in an ItemList. So instead of refactoring to use such a list, I wanted to ask if their is any elegant, or maybe even engine-built-in way to visualize a currently selected part of the UI.
More specifically, I am aware that there is information about which part of the UI is currently focussed; is there a possibility to visualize this focus?

How it currently looks like:
This is what it looks like ingame
This is what the node-structure looks like:
This is what the node-structure looks like
Searching for similar visualization like:

:bust_in_silhouette: Reply From: tripod

A simple hack is probably to use a control that has a explicit stylebox for the focused state, for example a button. here’s an example using a LinkButton

The cleanest solution is probably to attach a script to your item and add a custom StyleBox for focus to a theme. and then in the _draw() method, check for focus and render the focus box.

similar to what godot does, for example in the button:

https://github.com/godotengine/godot/blob/cdfd3ffe15dbf6f41bdade308d69a75f3d4eb3a7/scene/gui/link_button.cpp#L187-L190

		if (has_focus()) {
			Ref<StyleBox> style = get_theme_stylebox("focus");
			style->draw(ci, Rect2(Point2(), size));
		}

tripod | 2021-03-08 08:18

Thank you so much for your response. After working around trying out some things for a while, I finally got there.

Gonna post the solution for my own answer, since I stumbled into a few confusions and maybe other persons might stumble across the same. Credits to you though!

Toothgapsy | 2021-03-08 10:14

:bust_in_silhouette: Reply From: Toothgapsy

As @tripod mentioned, there is a rather simple workaround, however I disliked another hacky approach like things I did before. So i decided to use his second idea which (after some trial and error) worked perfectly: Using themes themselves.

First off, I had to create a new special theme for one of the entries in the LayerContainer. Note here that an inherited theme (from a node aboce) could not be found here. Explicitly set the a theme into this entry-node.

In this theme, as stated by tripod “add a custom StyleBox for focus”, in my case i called it “FocusedBox”. Then “in the _draw() method, check for focus and render the focus box” like this:

func _draw():
         if has_focus():
		var focussed = theme.get_stylebox("FocusedBox", "BoxContainer")
		draw_style_box(focussed, Rect2(Vector2(0,0), rect_size))