docs: fix docking spec issues from review

- Add panel name registry (names Vec)
- Cache layout results for draw_chrome
- Track prev_mouse_down for click detection
- Add invariants (non-empty tabs, active clamping, resize priority)
- Add LeafLayout and ResizeState structs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 09:37:18 +09:00
parent eb454800a9
commit 867f8a0aa0

View File

@@ -34,6 +34,25 @@ pub enum DockNode {
pub struct DockTree { pub struct DockTree {
root: DockNode, root: DockNode,
names: Vec<&'static str>, // panel_id → 표시 이름 (인덱스 = panel_id)
cached_layouts: Vec<LeafLayout>, // layout() 결과 캐시 (draw_chrome에서 사용)
resizing: Option<ResizeState>, // 현재 리사이즈 중인 Split
prev_mouse_down: bool, // 이전 프레임 마우스 상태 (클릭 감지용)
}
struct ResizeState {
node_path: Vec<usize>, // 루트에서 해당 Split까지의 child 인덱스 경로
axis: Axis,
origin: f32, // 분할 영역의 시작 좌표
size: f32, // 분할 영역의 전체 크기
}
pub struct LeafLayout {
pub tabs: Vec<u32>,
pub names: Vec<&'static str>,
pub active: usize,
pub tab_bar_rect: Rect,
pub content_rect: Rect,
} }
``` ```
@@ -58,6 +77,7 @@ pub struct Rect {
- Horizontal: 좌(w * ratio) / 우(w * (1 - ratio)) - Horizontal: 좌(w * ratio) / 우(w * (1 - ratio))
- Vertical: 상(h * ratio) / 하(h * (1 - ratio)) - Vertical: 상(h * ratio) / 하(h * (1 - ratio))
- **Leaf 노드**: 탭 바 높이(20px)를 빼고 나머지가 컨텐츠 영역 - **Leaf 노드**: 탭 바 높이(20px)를 빼고 나머지가 컨텐츠 영역
- 결과를 `cached_layouts`에 저장 (`draw_chrome`에서 사용)
- 반환: `Vec<(u32, Rect)>` — (활성 탭의 panel_id, 컨텐츠 rect) - 반환: `Vec<(u32, Rect)>` — (활성 탭의 panel_id, 컨텐츠 rect)
## Resize ## Resize
@@ -65,6 +85,7 @@ pub struct Rect {
Split 경계선 ±3px 영역에서 마우스 드래그를 감지한다. Split 경계선 ±3px 영역에서 마우스 드래그를 감지한다.
- `update(mouse_x, mouse_y, mouse_down)` 매 프레임 호출 - `update(mouse_x, mouse_y, mouse_down)` 매 프레임 호출
- 클릭 감지: `mouse_down && !prev_mouse_down`으로 just-clicked 판별 (prev_mouse_down 내부 추적)
- 마우스 다운 시 경계선 위에 있으면 해당 Split 노드를 "active resize" 상태로 설정 - 마우스 다운 시 경계선 위에 있으면 해당 Split 노드를 "active resize" 상태로 설정
- 드래그 중: 마우스 위치에 따라 ratio 업데이트 - 드래그 중: 마우스 위치에 따라 ratio 업데이트
- 마우스 릴리즈 시 해제 - 마우스 릴리즈 시 해제
@@ -95,20 +116,26 @@ Split 경계선 ±3px 영역에서 마우스 드래그를 감지한다.
- 리사이즈 중 경계선: 밝은 라인 (100, 100, 200)으로 하이라이트 - 리사이즈 중 경계선: 밝은 라인 (100, 100, 200)으로 하이라이트
- 탭 바 하단: 1px 구분선 - 탭 바 하단: 1px 구분선
## Invariants
- `tabs`는 반드시 1개 이상의 요소를 가져야 한다
- `active`는 항상 `tabs.len() - 1` 이하로 클램프한다 (out of bounds 방지)
- 리사이즈 핸들은 탭 바보다 우선한다 (겹치는 영역에서 리사이즈 우선)
## API ## API
```rust ```rust
impl DockTree { impl DockTree {
/// 트리 생성 /// 트리 생성. names: panel_id → 표시 이름 매핑 (인덱스 = panel_id)
pub fn new(root: DockNode) -> Self; pub fn new(root: DockNode, names: Vec<&'static str>) -> Self;
/// 레이아웃 계산 — 각 활성 패널의 컨텐츠 영역 반환 /// 레이아웃 계산 — 결과를 내부에 캐시하고, 활성 패널의 (panel_id, content_rect) 반환
pub fn layout(&self, rect: Rect) -> Vec<(u32, Rect)>; pub fn layout(&mut self, rect: Rect) -> Vec<(u32, Rect)>;
/// 리사이즈 + 탭 클릭 처리 /// 리사이즈 + 탭 클릭 처리 (내부에서 prev_mouse_down 추적)
pub fn update(&mut self, mouse_x: f32, mouse_y: f32, mouse_down: bool); pub fn update(&mut self, mouse_x: f32, mouse_y: f32, mouse_down: bool);
/// 탭 바 + 경계선 렌더링 /// 탭 바 + 경계선 렌더링 (cached_layouts 사용)
pub fn draw_chrome(&self, ui: &mut UiContext); pub fn draw_chrome(&self, ui: &mut UiContext);
} }
``` ```
@@ -116,6 +143,7 @@ impl DockTree {
## Usage Example ## Usage Example
```rust ```rust
let names = vec!["Hierarchy", "Viewport", "Inspector", "Console"];
let mut dock = DockTree::new(DockNode::Split { let mut dock = DockTree::new(DockNode::Split {
axis: Axis::Horizontal, axis: Axis::Horizontal,
ratio: 0.25, ratio: 0.25,
@@ -130,7 +158,7 @@ let mut dock = DockTree::new(DockNode::Split {
], ],
}), }),
], ],
}); }, names);
// frame loop // frame loop
let areas = dock.layout(Rect { x: 0.0, y: 0.0, w: 1280.0, h: 720.0 }); let areas = dock.layout(Rect { x: 0.0, y: 0.0, w: 1280.0, h: 720.0 });