multi-tabs
This commit is contained in:
@@ -9,6 +9,7 @@ signal tab_closed
|
||||
@onready var close_button: Button = %CloseButton
|
||||
@onready var icon: TextureRect = %Icon
|
||||
@onready var animation: AnimationPlayer = $AnimationPlayer
|
||||
var appear_tween: Tween
|
||||
|
||||
const TAB_GRADIENT: GradientTexture2D = preload("res://Scenes/Styles/TabGradient.tres")
|
||||
const TAB_GRADIENT_DEFAULT: GradientTexture2D = preload("res://Scenes/Styles/TabGradientDefault.tres")
|
||||
@@ -19,10 +20,25 @@ const TAB_DEFAULT: StyleBoxFlat = preload("res://Scenes/Styles/TabDefault.tres")
|
||||
const CLOSE_BUTTON_HOVER: StyleBoxFlat = preload("res://Scenes/Styles/CloseButtonHover.tres")
|
||||
const CLOSE_BUTTON_NORMAL: StyleBoxFlat = preload("res://Scenes/Styles/CloseButtonNormal.tres")
|
||||
|
||||
const CLOSE_BUTTON_HIDE_THRESHOLD := 100
|
||||
const TEXT_HIDE_THRESHOLD := 50
|
||||
const GRADIENT_WIDTH := 64
|
||||
const GRADIENT_OFFSET := 72
|
||||
const CLOSE_BUTTON_OFFSET := 34
|
||||
const ICON_OFFSET := 8
|
||||
const APPEAR_ANIMATION_DURATION := 0.25
|
||||
|
||||
var is_active := false
|
||||
var mouse_over_tab := false
|
||||
var loading_tween: Tween
|
||||
|
||||
var scroll_container: ScrollContainer = null
|
||||
var website_container: VBoxContainer = null
|
||||
var background_panel: PanelContainer = null
|
||||
var lua_apis: Array[LuaAPI] = []
|
||||
var current_url: String = ""
|
||||
var has_content: bool = false
|
||||
|
||||
func _ready():
|
||||
add_to_group("tabs")
|
||||
gradient_texture.texture = gradient_texture.texture.duplicate()
|
||||
@@ -41,6 +57,7 @@ func _process(_delta):
|
||||
|
||||
func set_title(title: String) -> void:
|
||||
button.text = title
|
||||
button.set_meta("original_text", title)
|
||||
|
||||
func set_icon(new_icon: Texture) -> void:
|
||||
icon.texture = new_icon
|
||||
@@ -52,7 +69,6 @@ func update_icon_from_url(icon_url: String) -> void:
|
||||
set_icon(GLOBE_ICON)
|
||||
return
|
||||
|
||||
# Load the icon in the background
|
||||
var icon_resource = await Network.fetch_image(icon_url)
|
||||
|
||||
if is_instance_valid(self) and icon_resource:
|
||||
@@ -98,24 +114,104 @@ func _exit_tree():
|
||||
if loading_tween:
|
||||
loading_tween.kill()
|
||||
loading_tween = null
|
||||
|
||||
for lua_api in lua_apis:
|
||||
if is_instance_valid(lua_api):
|
||||
lua_api.kill_script_execution()
|
||||
lua_api.queue_free()
|
||||
lua_apis.clear()
|
||||
|
||||
if scroll_container and is_instance_valid(scroll_container):
|
||||
if scroll_container.get_parent():
|
||||
scroll_container.get_parent().remove_child(scroll_container)
|
||||
scroll_container.queue_free()
|
||||
|
||||
if background_panel and is_instance_valid(background_panel):
|
||||
if background_panel.get_parent():
|
||||
background_panel.get_parent().remove_child(background_panel)
|
||||
background_panel.queue_free()
|
||||
|
||||
remove_from_group("tabs")
|
||||
|
||||
func _enter_tree() -> void:
|
||||
$AnimationPlayer.play("appear")
|
||||
func init_scene(parent_container: Control) -> void:
|
||||
if not scroll_container:
|
||||
background_panel = PanelContainer.new()
|
||||
background_panel.name = "Tab_Background_" + str(get_instance_id())
|
||||
background_panel.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
background_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
var style_box = StyleBoxFlat.new()
|
||||
style_box.bg_color = Color(1, 1, 1, 1) # White background
|
||||
background_panel.add_theme_stylebox_override("panel", style_box)
|
||||
|
||||
scroll_container = ScrollContainer.new()
|
||||
scroll_container.name = "Tab_ScrollContainer_" + str(get_instance_id())
|
||||
scroll_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
|
||||
website_container = VBoxContainer.new()
|
||||
website_container.name = "Tab_WebsiteContainer_" + str(get_instance_id())
|
||||
website_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
website_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
website_container.add_theme_constant_override("separation", 22)
|
||||
|
||||
parent_container.call_deferred("add_child", background_panel)
|
||||
background_panel.call_deferred("add_child", scroll_container)
|
||||
scroll_container.call_deferred("add_child", website_container)
|
||||
|
||||
background_panel.visible = is_active
|
||||
|
||||
func show_content() -> void:
|
||||
if background_panel:
|
||||
background_panel.visible = true
|
||||
|
||||
func play_appear_animation(target_width: float) -> void:
|
||||
var should_hide_close = target_width < CLOSE_BUTTON_HIDE_THRESHOLD
|
||||
var should_hide_text = target_width < TEXT_HIDE_THRESHOLD
|
||||
|
||||
close_button.visible = not should_hide_close
|
||||
button.text = "" if should_hide_text else button.get_meta("original_text", "New Tab")
|
||||
|
||||
var should_show_gradient = not should_hide_text and not should_hide_close
|
||||
gradient_texture.visible = should_show_gradient
|
||||
|
||||
if should_show_gradient:
|
||||
gradient_texture.size.x = GRADIENT_WIDTH
|
||||
gradient_texture.position.x = target_width - GRADIENT_OFFSET
|
||||
|
||||
if not should_hide_close:
|
||||
close_button.position.x = target_width - CLOSE_BUTTON_OFFSET
|
||||
|
||||
icon.position.x = ICON_OFFSET
|
||||
custom_minimum_size.x = 0.0
|
||||
size.x = 0.0
|
||||
button.custom_minimum_size.x = 0.0
|
||||
button.size.x = 0.0
|
||||
|
||||
if appear_tween:
|
||||
appear_tween.kill()
|
||||
|
||||
appear_tween = create_tween()
|
||||
appear_tween.set_ease(Tween.EASE_OUT)
|
||||
appear_tween.set_trans(Tween.TRANS_CUBIC)
|
||||
|
||||
appear_tween.parallel().tween_property(self, "custom_minimum_size:x", target_width, APPEAR_ANIMATION_DURATION)
|
||||
appear_tween.parallel().tween_property(self, "size:x", target_width, APPEAR_ANIMATION_DURATION)
|
||||
appear_tween.parallel().tween_property(button, "custom_minimum_size:x", target_width, APPEAR_ANIMATION_DURATION)
|
||||
appear_tween.parallel().tween_property(button, "size:x", target_width, APPEAR_ANIMATION_DURATION)
|
||||
|
||||
func _on_button_pressed() -> void:
|
||||
# Check if click was on close button area
|
||||
var mouse_pos = get_global_mouse_position()
|
||||
var close_button_rect = Rect2(close_button.global_position, close_button.size * close_button.scale)
|
||||
|
||||
if close_button_rect.has_point(mouse_pos):
|
||||
_on_close_button_pressed()
|
||||
else:
|
||||
# Handle tab button click
|
||||
tab_pressed.emit()
|
||||
tab_pressed.emit()
|
||||
|
||||
func _on_close_button_pressed() -> void:
|
||||
var close_tween = create_tween()
|
||||
close_tween.set_ease(Tween.EASE_IN)
|
||||
close_tween.set_trans(Tween.TRANS_CUBIC)
|
||||
|
||||
close_tween.parallel().tween_property(self, "custom_minimum_size:x", 0.0, 0.15)
|
||||
close_tween.parallel().tween_property(self, "size:x", 0.0, 0.15)
|
||||
close_tween.parallel().tween_property(button, "custom_minimum_size:x", 0.0, 0.15)
|
||||
close_tween.parallel().tween_property(button, "size:x", 0.0, 0.15)
|
||||
|
||||
await close_tween.finished
|
||||
tab_closed.emit()
|
||||
animation.play("appear", -1, -1.0, true)
|
||||
await animation.animation_finished
|
||||
queue_free()
|
||||
|
||||
Reference in New Issue
Block a user