130 lines
4.1 KiB
GDScript
130 lines
4.1 KiB
GDScript
class_name ABGPageView
|
|
extends Control
|
|
|
|
const EntryChrome = preload("res://entry/entry_chrome.gd")
|
|
const UI_FONT = preload("res://assets/fonts/NotoSansSC.ttf")
|
|
const PageContext = preload("res://foundation/page_context.gd")
|
|
const UIFactory = preload("res://ui/shared/ui_factory.gd")
|
|
|
|
## Passive View base for the new Entry page boundary.
|
|
##
|
|
## A PageView owns Godot nodes, layout, focus and local visual state. It
|
|
## receives a copied ViewData snapshot and emits named intents; it does not
|
|
## resolve services, read Save or make route/economy decisions.
|
|
|
|
signal intent_emitted(intent_id: String, payload: Dictionary)
|
|
|
|
var context: ABGPageContext
|
|
var view_data: Dictionary = {}
|
|
var presentation: Dictionary = {
|
|
"safe_area": 24,
|
|
"text_scale": 1.0,
|
|
}
|
|
|
|
|
|
func mount(next_context) -> ABGPageView:
|
|
if next_context is ABGPageContext:
|
|
context = next_context.duplicate_context()
|
|
elif next_context is Dictionary:
|
|
context = PageContext.new(next_context)
|
|
else:
|
|
context = PageContext.new()
|
|
return self
|
|
|
|
|
|
func configure_presentation(values: Dictionary = {}) -> ABGPageView:
|
|
for key in values.keys():
|
|
presentation[String(key)] = values[key]
|
|
return self
|
|
|
|
|
|
func render(next_view_data: Dictionary = {}) -> void:
|
|
view_data = next_view_data.duplicate(true)
|
|
_render_view(view_data)
|
|
|
|
|
|
func emit_intent(intent_id: String, payload: Dictionary = {}) -> void:
|
|
intent_emitted.emit(String(intent_id), payload.duplicate(true))
|
|
|
|
|
|
func _render_view(_data: Dictionary) -> void:
|
|
# Concrete Views own their node tree and override this method.
|
|
pass
|
|
|
|
|
|
func clear_view_children() -> void:
|
|
for child in get_children():
|
|
child.free()
|
|
|
|
|
|
func page_locale(data: Dictionary = view_data) -> String:
|
|
return String(data.get("locale", presentation.get("locale", "zh_CN")))
|
|
|
|
|
|
func localize(zh: String, en: String, data: Dictionary = view_data) -> String:
|
|
return zh if page_locale(data) == "zh_CN" else en
|
|
|
|
|
|
func scaled(value: int) -> int:
|
|
return int(round(float(value) * float(presentation.get("text_scale", 1.0))))
|
|
|
|
|
|
func make_label(value: String, font_size: int, color: Color) -> Label:
|
|
var label := UIFactory.label(value, "body", 1.0, color)
|
|
label.add_theme_font_size_override("font_size", font_size)
|
|
return label
|
|
|
|
|
|
func make_entry_chrome(node_name: String, variant: String, icon := "") -> Control:
|
|
var chrome := EntryChrome.new().configure(variant, icon)
|
|
chrome.name = node_name
|
|
chrome.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
return chrome
|
|
|
|
|
|
func make_company_button(node_name: String, text_value: String, intent_id: String, variant: String, icon: String, intent_payload: Dictionary = {}) -> Button:
|
|
var button := UIFactory.command_button(
|
|
node_name,
|
|
text_value,
|
|
variant,
|
|
icon,
|
|
"angular",
|
|
"content" if variant.begins_with("content_") else "company",
|
|
Vector2(190, 52),
|
|
false,
|
|
text_value,
|
|
Callable(),
|
|
scaled(16)
|
|
)
|
|
button.pressed.connect(func(): emit_intent(intent_id, intent_payload), CONNECT_DEFERRED)
|
|
return button
|
|
|
|
|
|
func make_framed_page_safe(prefix: String) -> MarginContainer:
|
|
var safe := MarginContainer.new()
|
|
safe.name = "%sFrameSafeArea" % prefix
|
|
safe.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
safe.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
var margin := maxi(12, int(presentation.get("safe_area", 24)))
|
|
var vertical_margin := 12 if size.y < 500.0 else margin
|
|
safe.add_theme_constant_override("margin_left", margin)
|
|
safe.add_theme_constant_override("margin_right", margin)
|
|
safe.add_theme_constant_override("margin_top", vertical_margin)
|
|
safe.add_theme_constant_override("margin_bottom", vertical_margin)
|
|
add_child(safe)
|
|
return safe
|
|
|
|
|
|
func make_content_page_safe(prefix: String) -> MarginContainer:
|
|
var safe := MarginContainer.new()
|
|
safe.name = "%sSafeArea" % prefix
|
|
safe.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
var margin := maxi(12, int(presentation.get("safe_area", 24)))
|
|
var vertical_margin := 12 if size.y < 500.0 else margin
|
|
safe.add_theme_constant_override("margin_left", margin + 12)
|
|
safe.add_theme_constant_override("margin_right", margin + 12)
|
|
safe.add_theme_constant_override("margin_top", vertical_margin + 8)
|
|
safe.add_theme_constant_override("margin_bottom", vertical_margin + 8)
|
|
add_child(safe)
|
|
return safe
|