add long-press gesture for touch-friendly preset popup
- replace instant drag-on-press with 500ms long-press timer - cancel long-press on early release or movement past 10px threshold - preserve double-click for mouse users (backward compatible) - resize edge detection still instant (no long-press) - cancel long-press on mouse_exit and grid rebuild - fix: ConfigFile reserved word 'default' removed from config
This commit is contained in:
parent
825598f1a9
commit
96c4d39946
4 changed files with 96 additions and 17 deletions
|
|
@ -12,8 +12,8 @@ signal layout_loaded(layout_name: String)
|
||||||
|
|
||||||
const LAYOUT_DIR: String = "res://config/layouts/"
|
const LAYOUT_DIR: String = "res://config/layouts/"
|
||||||
|
|
||||||
## Current layout name (e.g. "default").
|
## Current layout name (e.g. "Main").
|
||||||
var current_layout_name: String = "default"
|
var current_layout_name: String = "Main"
|
||||||
|
|
||||||
## The active layout data: tile_id -> {col, row, w, h}
|
## The active layout data: tile_id -> {col, row, w, h}
|
||||||
var _layout: Dictionary = {}
|
var _layout: Dictionary = {}
|
||||||
|
|
@ -28,7 +28,7 @@ func _ready() -> void:
|
||||||
current_layout_name = configured_name
|
current_layout_name = configured_name
|
||||||
|
|
||||||
if not load_layout(current_layout_name):
|
if not load_layout(current_layout_name):
|
||||||
current_layout_name = "default"
|
current_layout_name = "Main"
|
||||||
_layout.clear()
|
_layout.clear()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,3 @@ show_disk=true
|
||||||
|
|
||||||
[performance]
|
[performance]
|
||||||
refresh_interval=1.0
|
refresh_interval=1.0
|
||||||
|
|
||||||
[general]
|
|
||||||
theme=default
|
|
||||||
|
|
||||||
[layout]
|
|
||||||
current="default"
|
|
||||||
|
|
|
||||||
32
config/layouts/default.cfg
Normal file
32
config/layouts/default.cfg
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
[layout]
|
||||||
|
|
||||||
|
name="default"
|
||||||
|
saved_at="2026-05-21T08:50:03"
|
||||||
|
|
||||||
|
[tiles]
|
||||||
|
|
||||||
|
count=3
|
||||||
|
|
||||||
|
[tile_0]
|
||||||
|
|
||||||
|
id="system_monitor/cpu"
|
||||||
|
col=0
|
||||||
|
row=0
|
||||||
|
w=1
|
||||||
|
h=1
|
||||||
|
|
||||||
|
[tile_1]
|
||||||
|
|
||||||
|
id="system_monitor/testing"
|
||||||
|
col=1
|
||||||
|
row=0
|
||||||
|
w=1
|
||||||
|
h=1
|
||||||
|
|
||||||
|
[tile_2]
|
||||||
|
|
||||||
|
id="system_monitor/memory"
|
||||||
|
col=2
|
||||||
|
row=0
|
||||||
|
w=1
|
||||||
|
h=1
|
||||||
|
|
@ -56,6 +56,14 @@ const EDGE_RIGHT: int = 2
|
||||||
const EDGE_TOP: int = 4
|
const EDGE_TOP: int = 4
|
||||||
const EDGE_BOTTOM: int = 8
|
const EDGE_BOTTOM: int = 8
|
||||||
|
|
||||||
|
# Long-press gesture — used as a touch-friendly alternative to double-click
|
||||||
|
const LONG_PRESS_TIME: float = 0.5
|
||||||
|
const LONG_PRESS_DRAG_THRESHOLD: float = 10.0
|
||||||
|
|
||||||
|
var _long_press_timer: Timer = null
|
||||||
|
var _long_press_pos: Vector2 = Vector2.ZERO
|
||||||
|
var _long_press_active: bool = false
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
mouse_filter = Control.MOUSE_FILTER_STOP
|
mouse_filter = Control.MOUSE_FILTER_STOP
|
||||||
|
|
@ -66,6 +74,8 @@ func _ready() -> void:
|
||||||
|
|
||||||
|
|
||||||
func _on_mouse_exited() -> void:
|
func _on_mouse_exited() -> void:
|
||||||
|
if _long_press_active:
|
||||||
|
_cancel_long_press()
|
||||||
if _is_dragging:
|
if _is_dragging:
|
||||||
if _drag_module != null:
|
if _drag_module != null:
|
||||||
_drag_module.modulate = Color(1, 1, 1, 1)
|
_drag_module.modulate = Color(1, 1, 1, 1)
|
||||||
|
|
@ -81,23 +91,33 @@ func _on_gui_input(event: InputEvent) -> void:
|
||||||
if event is InputEventMouseButton:
|
if event is InputEventMouseButton:
|
||||||
var mb: InputEventMouseButton = event
|
var mb: InputEventMouseButton = event
|
||||||
if mb.button_index == MOUSE_BUTTON_LEFT and mb.double_click and mb.pressed:
|
if mb.button_index == MOUSE_BUTTON_LEFT and mb.double_click and mb.pressed:
|
||||||
|
# Double-click still works for mouse users
|
||||||
_show_preset_popup(mb.position)
|
_show_preset_popup(mb.position)
|
||||||
elif mb.button_index == MOUSE_BUTTON_LEFT and not mb.double_click:
|
elif mb.button_index == MOUSE_BUTTON_LEFT and not mb.double_click:
|
||||||
if mb.pressed:
|
if mb.pressed:
|
||||||
|
# Try resize edge first (instant, no long-press)
|
||||||
if not _try_begin_resize(mb.position):
|
if not _try_begin_resize(mb.position):
|
||||||
_begin_drag(mb.position)
|
# Not on an edge — start long-press gesture
|
||||||
elif _is_resizing:
|
_start_long_press(mb.position)
|
||||||
|
else:
|
||||||
|
_cancel_long_press()
|
||||||
|
if _is_resizing:
|
||||||
_end_resize(mb.position)
|
_end_resize(mb.position)
|
||||||
elif _is_dragging:
|
elif _is_dragging:
|
||||||
_end_drag(mb.position)
|
_end_drag(mb.position)
|
||||||
|
|
||||||
elif event is InputEventMouseMotion:
|
elif event is InputEventMouseMotion:
|
||||||
|
var mm: InputEventMouseMotion = event
|
||||||
if _is_resizing:
|
if _is_resizing:
|
||||||
_update_resize(event.position)
|
_update_resize(mm.position)
|
||||||
elif _is_dragging:
|
elif _is_dragging:
|
||||||
_update_drag(event.position)
|
_update_drag(mm.position)
|
||||||
|
elif _long_press_active:
|
||||||
|
if (mm.position - _long_press_pos).length_squared() > LONG_PRESS_DRAG_THRESHOLD * LONG_PRESS_DRAG_THRESHOLD:
|
||||||
|
_cancel_long_press()
|
||||||
|
_begin_drag(mm.position)
|
||||||
else:
|
else:
|
||||||
_update_hover_cursor(event.position)
|
_update_hover_cursor(mm.position)
|
||||||
|
|
||||||
|
|
||||||
func _show_preset_popup(mouse_pos: Vector2) -> void:
|
func _show_preset_popup(mouse_pos: Vector2) -> void:
|
||||||
|
|
@ -129,6 +149,37 @@ func _show_preset_popup(mouse_pos: Vector2) -> void:
|
||||||
popup.id_pressed.connect(on_select)
|
popup.id_pressed.connect(on_select)
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Long-press gesture (touch-friendly popup trigger)
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func _start_long_press(pos: Vector2) -> void:
|
||||||
|
_cancel_long_press()
|
||||||
|
_long_press_pos = pos
|
||||||
|
_long_press_active = true
|
||||||
|
_long_press_timer = Timer.new()
|
||||||
|
_long_press_timer.name = "LongPressTimer"
|
||||||
|
_long_press_timer.one_shot = true
|
||||||
|
_long_press_timer.wait_time = LONG_PRESS_TIME
|
||||||
|
_long_press_timer.timeout.connect(_on_long_press_timeout)
|
||||||
|
add_child(_long_press_timer)
|
||||||
|
_long_press_timer.start()
|
||||||
|
|
||||||
|
|
||||||
|
func _cancel_long_press() -> void:
|
||||||
|
_long_press_active = false
|
||||||
|
if _long_press_timer != null:
|
||||||
|
if _long_press_timer.is_inside_tree():
|
||||||
|
_long_press_timer.queue_free()
|
||||||
|
_long_press_timer = null
|
||||||
|
|
||||||
|
|
||||||
|
func _on_long_press_timeout() -> void:
|
||||||
|
_long_press_active = false
|
||||||
|
_long_press_timer = null
|
||||||
|
_show_preset_popup(_long_press_pos)
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# Public API
|
# Public API
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
|
@ -603,6 +654,8 @@ func _highlight_cell(col: int, row: int, highlighted: bool) -> void:
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
func _rebuild_grid() -> void:
|
func _rebuild_grid() -> void:
|
||||||
|
if _long_press_active:
|
||||||
|
_cancel_long_press()
|
||||||
if _is_dragging:
|
if _is_dragging:
|
||||||
_cancel_drag()
|
_cancel_drag()
|
||||||
if _is_resizing:
|
if _is_resizing:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue