summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-06-03 16:23:35 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-06-03 16:23:35 -0600
commitf007593abc9a666df85120e08c7f1d327d9215da (patch)
tree541937c798ca148ed63835a7ab93f9db9353e1f0
parent903df67b153ca4af877ba0b534d4802d74cf34df (diff)
Add center-zone move (swap); restore center drop zone
- Edge zones (left/right/top/bottom): split target tile equally - Center zone: swap dragged and target tile positions in BSP tree (tree structure preserved, only leaf pane values exchanged) - Center overlay: green highlight (vs blue for split zones) - _tree_swap: immutable swap of two leaf pane values Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--ui/windows/plot_window.py41
1 files changed, 30 insertions, 11 deletions
diff --git a/ui/windows/plot_window.py b/ui/windows/plot_window.py
index 80a1624..615b7ca 100644
--- a/ui/windows/plot_window.py
+++ b/ui/windows/plot_window.py
@@ -189,6 +189,17 @@ def _tree_reindex(node: dict, removed_idx: int) -> dict:
"second": _tree_reindex(node["second"], removed_idx)}
+def _tree_swap(node: dict, idx_a: int, idx_b: int) -> dict:
+ """Swap two leaf pane values in-place (preserves tree structure)."""
+ if node["kind"] == "leaf":
+ if node["pane"] == idx_a: return {**node, "pane": idx_b}
+ if node["pane"] == idx_b: return {**node, "pane": idx_a}
+ return node
+ return {**node,
+ "first": _tree_swap(node["first"], idx_a, idx_b),
+ "second": _tree_swap(node["second"], idx_a, idx_b)}
+
+
def _tree_leaf_count(node: dict) -> int:
if node["kind"] == "leaf":
return 1
@@ -455,8 +466,10 @@ def _zone_overlay_rect(r: QRect, zone: str) -> QRect:
return QRect(r.x() + r.width() // 2, r.y(), r.width() - r.width() // 2, r.height())
if zone == "top":
return QRect(r.x(), r.y(), r.width(), r.height() // 2)
- # bottom
- return QRect(r.x(), r.y() + r.height() // 2, r.width(), r.height() - r.height() // 2)
+ if zone == "bottom":
+ return QRect(r.x(), r.y() + r.height() // 2, r.width(), r.height() - r.height() // 2)
+ # center (move)
+ return r
class PaneTile(QFrame):
@@ -592,7 +605,7 @@ class LayoutCanvas(QFrame):
return (pane_idx, "top")
if rel_y > h - zone_h:
return (pane_idx, "bottom")
- return None # center — no drop zone
+ return (pane_idx, "center") # center — move/swap
return None
# ── Drag ─────────────────────────────────────────────────────────────────
@@ -638,12 +651,14 @@ class LayoutCanvas(QFrame):
if dragged_idx == target_idx or self._tree is None:
self._reposition_tiles()
return
- new_tree = _tree_remove(self._tree, dragged_idx)
- if new_tree is None:
- # Only one pane
- self._reposition_tiles()
- return
- new_tree = _tree_equalize_ratios(_tree_insert(new_tree, target_idx, dragged_idx, zone))
+ if zone == "center":
+ new_tree = _tree_swap(self._tree, dragged_idx, target_idx)
+ else:
+ new_tree = _tree_remove(self._tree, dragged_idx)
+ if new_tree is None:
+ self._reposition_tiles()
+ return
+ new_tree = _tree_equalize_ratios(_tree_insert(new_tree, target_idx, dragged_idx, zone))
self._tree = new_tree
if self._cfg_ref is not None:
self._cfg_ref.tree = new_tree
@@ -663,8 +678,12 @@ class LayoutCanvas(QFrame):
overlay = _zone_overlay_rect(r, zone)
painter = QPainter(self)
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
- painter.setPen(QPen(QColor("#3b82f6"), 2))
- painter.setBrush(QColor(59, 130, 246, 70))
+ if zone == "center":
+ painter.setPen(QPen(QColor("#22c55e"), 2))
+ painter.setBrush(QColor(34, 197, 94, 60))
+ else:
+ painter.setPen(QPen(QColor("#3b82f6"), 2))
+ painter.setBrush(QColor(59, 130, 246, 70))
painter.drawRoundedRect(overlay, 4, 4)