diff options
| -rw-r--r-- | option_set/option_set_list.gd | 112 |
1 files changed, 36 insertions, 76 deletions
diff --git a/option_set/option_set_list.gd b/option_set/option_set_list.gd index d2179b1..7efb162 100644 --- a/option_set/option_set_list.gd +++ b/option_set/option_set_list.gd @@ -1,10 +1,11 @@ extends Control var vscrollbar: VScrollBar -var labels: Array +var labels: Control var labels_positions: Array var labels_sizes: Array -var sizes: Array +var font: Font + var items: Array = [ "item 1", "item 22", @@ -38,12 +39,16 @@ var items: Array = [ "This is the longest item of all, but eventually stops.", ] -var limit := 60 -var labels_pool: Array - -onready var font: Font = get_font("font") func _init(): + font = get_font("font") + connect("resized", self, "build_labels") + + labels = Control.new() + labels.anchor_right = 1.0 + labels.anchor_bottom = 1.0 + add_child(labels) + vscrollbar = VScrollBar.new() vscrollbar.anchor_left = 1.0 vscrollbar.anchor_bottom = 1.0 @@ -51,35 +56,30 @@ func _init(): vscrollbar.name = "vscrollbar" add_child(vscrollbar) +# @DAM This is only used once so, why not inline it? +func max_required_labels() -> int: + var max_labels := ceil(rect_size.y / font.get_height()) + 1 + return int(min(items.size(), max_labels)) + + +func build_labels(): + var new_max_required_labels := max_required_labels() + var delta := new_max_required_labels - labels.get_child_count() -func _ready(): - var num_labels := max_required_labels() - var labels_pool_size = int(ceil(num_labels * 1.10)) - for idx in range(labels_pool_size): + while delta > 0: var label := Label.new() label.autowrap = true label.anchor_left = 0.0 label.anchor_right = 1.0 label.valign = Label.VALIGN_TOP - labels_pool.push_back(label) - - for idx in range(min(num_labels, items.size())): - var label = labels_pool.pop_back() - label.text = items[idx] - labels.append(label) - add_child(label) - -# for it in items: -# var label := Label.new() -# label.text = it -# label.autowrap = true -# label.anchor_left = 0.0 -# label.anchor_right = 1.0 -# label.valign = Label.VALIGN_CENTER -# labels.push_back(label) -# add_child(label) + labels.add_child(label) + delta -= 1 - process_labels() + while delta < 0: + var label := labels.get_child(0) as Label + labels.remove_child(label) + label.free() + delta += 1 func process_labels(): @@ -87,6 +87,7 @@ func process_labels(): labels_sizes.clear() var position := 0.0 var limit := rect_size.x + limit = labels.rect_size.x # labels_positions.append(0) for it in items: var size := font.get_wordwrap_string_size(it, limit).y @@ -95,25 +96,13 @@ func process_labels(): position += height labels_positions.append(position) labels_sizes.append(height) + vscrollbar.raise() func _process(delta): - var num_labels = max_required_labels() - var difference = num_labels - labels.size() - if difference > 0: - for idx in range(difference): - var label = labels_pool.pop_back() - labels.append(label) - add_child(label) - elif difference < 0: - for idx in range(abs(difference)): - var label = labels.pop_back() - labels_pool.append(label) - remove_child(label) - - # @DAM Since the items may have different heights, we must look at the edge items - # in order to update the offsets. + # @DAM We are recalculating the labels size and position on every update. + # This only has to be done on resize or when items change. process_labels() vscrollbar.min_value = 0 @@ -127,46 +116,17 @@ func _process(delta): var offset_idx := labels_positions.bsearch(bs_value) # offset_idx = 0 - for idx in range(min(num_labels, items.size())): - var label = labels[idx] + var idx := 0 + for label in labels.get_children(): if idx + offset_idx >= items.size(): label.text = "" break # @DAM Or should we use continue? label.text = items[idx + offset_idx] label.rect_position.y = labels_positions[idx + offset_idx] - labels_sizes[idx + offset_idx] - bs_value - # This was initially used to bring back down the height of the labels that grow due to text - # wrap because they were vertically aligned to CENTER without a good reason to do so. - # Since the labels are now aligned to TOP, we may just forget about their height. -# label.rect_size.y = 0.0 - - -# if difference != 0: -# for idx in range(min(num_labels, items.size())): -# labels[idx].text = items[idx] + idx += 1 # if Engine.get_idle_frames() % 30 == 1: # print_debug("> %s | %5.3f > %s > %d | lastPos: %s" % [labels.size(), offset, bs_value, offset_idx, labels_positions[-1]]) - - # Adapt scrollbar according to options and drawable size. - # @DAM This does not take into consideration the items that are wrapped. - - - - - - -func max_required_labels() -> int: - var max_labels := ceil(rect_size.y / font.get_height()) + 1 - return int(min(items.size(), max_labels)) - -#func _draw(): -# var position := Vector2(0.0, font.get_height()) -# for it in items: -# var p = font.get_wordwrap_string_size(it, limit) -# print_debug("> %s : %s" % [p, it]) -# draw_string(font, position, it, Color.white, limit) -# font.get_string_size(it) -# position.y += p.y - + labels.margin_right = -vscrollbar.rect_size.x if vscrollbar.visible else 0.0 |
