implement list-reflow insert for drag-and-drop: dropping on empty cell now inserts and reflows all modules row-major; _rebuild_grid calculates rows from module count; _restore_modules uses reflow
This commit is contained in:
parent
0f11343c05
commit
f33cf3d7f8
1 changed files with 115 additions and 27 deletions
|
|
@ -168,6 +168,7 @@ func _end_drag(mouse_pos: Vector2) -> void:
|
|||
return
|
||||
|
||||
_clear_hover()
|
||||
_drag_module.modulate = Color(1, 1, 1, 1)
|
||||
|
||||
var cell_pos := _cell_at_position(mouse_pos)
|
||||
var target_col := cell_pos.x
|
||||
|
|
@ -175,22 +176,18 @@ func _end_drag(mouse_pos: Vector2) -> void:
|
|||
|
||||
# Dropped on the same cell — just put it back
|
||||
if target_col == _drag_source_col and target_row == _drag_source_row:
|
||||
_drag_module.modulate = Color(1, 1, 1, 1)
|
||||
_place_module_in_cell(_drag_module, target_col, target_row)
|
||||
module_placed.emit(_drag_module, target_col, target_row)
|
||||
_drag_module = null
|
||||
_is_dragging = false
|
||||
_drag_source_col = -1
|
||||
_drag_source_row = -1
|
||||
_finish_drag()
|
||||
return
|
||||
|
||||
# Remove the module from the grid (we'll reparent it below)
|
||||
# Remove the module from its temporary home (the grid itself)
|
||||
_drag_module.get_parent().remove_child(_drag_module)
|
||||
|
||||
if _is_valid_cell(target_col, target_row):
|
||||
var existing := _get_cell_module(target_col, target_row)
|
||||
if existing != null:
|
||||
# Swap: put existing module in source cell, drag module in target
|
||||
# SWAP: put existing module in source cell, drag module in target
|
||||
existing.get_parent().remove_child(existing)
|
||||
var was_source_valid := _is_valid_cell(_drag_source_col, _drag_source_row)
|
||||
if was_source_valid:
|
||||
|
|
@ -199,19 +196,29 @@ func _end_drag(mouse_pos: Vector2) -> void:
|
|||
else:
|
||||
existing.queue_free()
|
||||
|
||||
# Place dragged module in target cell
|
||||
_drag_module.modulate = Color(1, 1, 1, 1)
|
||||
_place_module_in_cell(_drag_module, target_col, target_row)
|
||||
module_placed.emit(_drag_module, target_col, target_row)
|
||||
else:
|
||||
# INSERT: flatten all modules, insert dragged one at target, reflow
|
||||
var all_modules := _collect_all_modules()
|
||||
|
||||
var insert_index := target_row * columns + target_col
|
||||
insert_index = clampi(insert_index, 0, all_modules.size())
|
||||
all_modules.insert(insert_index, _drag_module)
|
||||
|
||||
_reflow_modules(all_modules)
|
||||
else:
|
||||
# Dropped outside the grid — return to source if still valid
|
||||
if _is_valid_cell(_drag_source_col, _drag_source_row):
|
||||
_drag_module.modulate = Color(1, 1, 1, 1)
|
||||
_place_module_in_cell(_drag_module, _drag_source_col, _drag_source_row)
|
||||
module_placed.emit(_drag_module, _drag_source_col, _drag_source_row)
|
||||
else:
|
||||
_drag_module.queue_free()
|
||||
|
||||
_finish_drag()
|
||||
|
||||
|
||||
func _finish_drag() -> void:
|
||||
_drag_module = null
|
||||
_is_dragging = false
|
||||
_drag_source_col = -1
|
||||
|
|
@ -281,6 +288,69 @@ func _set_cell_child(cell: PanelContainer, child: Control) -> void:
|
|||
cell.add_child(child)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# List-reflow helpers
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
# Returns all modules in the grid, in row-major order (left-to-right, top-to-bottom).
|
||||
func _collect_all_modules() -> Array[Control]:
|
||||
var result: Array[Control] = []
|
||||
for r in range(rows):
|
||||
for c in range(columns):
|
||||
var mod := _get_cell_module(c, r)
|
||||
if mod != null:
|
||||
result.append(mod)
|
||||
return result
|
||||
|
||||
|
||||
# Clears every cell, then places the given modules in row-major order,
|
||||
# adding extra rows as needed to fit them all.
|
||||
func _reflow_modules(modules: Array[Control]) -> void:
|
||||
# Remove all modules from cells
|
||||
for r in range(rows):
|
||||
for c in range(columns):
|
||||
_take_module_from_cell(c, r)
|
||||
|
||||
if columns == 0:
|
||||
return
|
||||
|
||||
# Ensure enough rows exist
|
||||
var needed := maxi(rows, ceili(float(modules.size()) / float(columns)))
|
||||
while _cells.size() < needed:
|
||||
_add_row()
|
||||
rows = _cells.size()
|
||||
|
||||
# Place modules sequentially
|
||||
for i in range(modules.size()):
|
||||
var c := i % columns
|
||||
var r := floori(i / columns)
|
||||
_place_module_in_cell(modules[i], c, r)
|
||||
module_placed.emit(modules[i], c, r)
|
||||
|
||||
|
||||
func _add_row() -> void:
|
||||
var new_row := _cells.size()
|
||||
_cells.append([])
|
||||
for col in range(columns):
|
||||
var cell := PanelContainer.new()
|
||||
cell.name = "Cell_%d_%d" % [col, new_row]
|
||||
cell.mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
_style_cell(cell, col, new_row)
|
||||
add_child(cell)
|
||||
_cells[new_row].append(cell)
|
||||
rows = _cells.size()
|
||||
_layout_cells()
|
||||
|
||||
|
||||
func _count_modules_in_grid() -> int:
|
||||
var count := 0
|
||||
for r in range(rows):
|
||||
for c in range(columns):
|
||||
if _get_cell_module(c, r) != null:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Grid rebuild
|
||||
# --------------------------------------------------------------------------
|
||||
|
|
@ -313,7 +383,12 @@ func _rebuild_grid() -> void:
|
|||
return
|
||||
|
||||
var new_cols := maxi(1, int(avail.x / (cell_min_size.x + cell_spacing)))
|
||||
var new_rows := maxi(1, int(avail.y / (cell_min_size.y + cell_spacing)))
|
||||
|
||||
# Ensure enough rows for all current modules after column change
|
||||
var module_count := _count_modules_in_grid()
|
||||
var min_rows := maxi(1, ceili(float(module_count) / float(new_cols)))
|
||||
var avail_rows := maxi(1, int(avail.y / (cell_min_size.y + cell_spacing)))
|
||||
var new_rows := maxi(avail_rows, min_rows)
|
||||
|
||||
if new_cols == columns and new_rows == rows and _cells.size() > 0:
|
||||
_layout_cells()
|
||||
|
|
@ -419,20 +494,33 @@ func _save_modules() -> void:
|
|||
|
||||
|
||||
func _restore_modules() -> void:
|
||||
# Collect modules in insertion order (row-major from _save_modules)
|
||||
var module_list: Array[Control] = []
|
||||
for key in _module_positions:
|
||||
var parts: PackedStringArray = key.split(",")
|
||||
var col: int = int(parts[0])
|
||||
var row := int(parts[1])
|
||||
var module: Control = _module_positions[key]
|
||||
|
||||
if _is_valid_cell(col, row):
|
||||
_place_module_in_cell(module, col, row)
|
||||
else:
|
||||
if _cells.size() > 0 and _cells[0].size() > 0:
|
||||
var last_row := _cells.size() - 1
|
||||
var last_col: int = _cells[last_row].size() - 1
|
||||
_place_module_in_cell(module, last_col, last_row)
|
||||
else:
|
||||
module.queue_free()
|
||||
module_list.append(_module_positions[key])
|
||||
|
||||
_module_positions.clear()
|
||||
|
||||
if module_list.is_empty():
|
||||
return
|
||||
|
||||
# Reflow onto the new grid dimensions
|
||||
var module_count := module_list.size()
|
||||
var needed := maxi(rows, ceili(float(module_count) / float(columns)))
|
||||
while _cells.size() < needed:
|
||||
var new_row := _cells.size()
|
||||
_cells.append([])
|
||||
for col in range(columns):
|
||||
var cell := PanelContainer.new()
|
||||
cell.name = "Cell_%d_%d" % [col, new_row]
|
||||
cell.mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
_style_cell(cell, col, new_row)
|
||||
add_child(cell)
|
||||
_cells[new_row].append(cell)
|
||||
rows = _cells.size()
|
||||
|
||||
for i in range(module_list.size()):
|
||||
var c := i % columns
|
||||
var r := floori(i / columns)
|
||||
if _is_valid_cell(c, r):
|
||||
_place_module_in_cell(module_list[i], c, r)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue