use crate::app_context::ContextManager;
use crate::docking::panels::DockPanel;
use crate::input::core::coordinator::LayerId;
use crate::input::{InputCoordinator, Sense, WidgetKind};
use crate::layout::{LayoutManager, LayoutNodeId, WidgetNode};
use crate::render::RenderContext;
use crate::types::{Rect, WidgetId};
use super::render::{draw_separator, SeparatorView};
use super::settings::SeparatorSettings;
use super::state::SeparatorDragState;
use super::types::SeparatorType;
pub enum SeparatorKind {
Divider,
ResizeHandle,
}
pub fn register_separator(
coord: &mut InputCoordinator,
id: impl Into<WidgetId>,
rect: Rect,
kind: SeparatorKind,
layer: &LayerId,
) {
let sense = match kind {
SeparatorKind::Divider => Sense::NONE,
SeparatorKind::ResizeHandle => Sense::DRAG,
};
coord.register_atomic(id, WidgetKind::Separator, rect, sense, layer);
}
pub fn register(
coord: &mut InputCoordinator,
id: impl Into<WidgetId>,
rect: Rect,
kind: &SeparatorType,
layer: &LayerId,
) {
let sense = if kind.is_interactive() {
Sense::DRAG
} else {
Sense::NONE
};
coord.register_atomic(id, WidgetKind::Separator, rect, sense, layer);
}
pub fn start_separator_drag(
state: &mut SeparatorDragState,
widget_id: WidgetId,
cursor_pos: f64,
current_value: f64,
target_pane_id: Option<u64>,
min_size: f64,
max_size: Option<f64>,
) {
state.field_id = Some(widget_id);
state.start_pos = cursor_pos;
state.start_value = current_value;
state.target_pane_id = target_pane_id;
state.min_size_constraint = min_size;
state.max_size_constraint = max_size;
}
pub fn update_separator_drag(state: &SeparatorDragState, cursor_pos: f64) -> Option<f64> {
state.field_id.as_ref()?;
let new_value = state.start_value + (cursor_pos - state.start_pos);
let clamped = new_value.max(state.min_size_constraint);
let clamped = match state.max_size_constraint {
Some(max) => clamped.min(max),
None => clamped,
};
Some(clamped)
}
pub fn end_separator_drag(
state: &mut SeparatorDragState,
cursor_pos: f64,
) -> Option<(WidgetId, f64)> {
let id = state.field_id.clone()?;
let value = update_separator_drag(state, cursor_pos).unwrap_or(state.start_value);
state.clear();
Some((id, value))
}
pub fn register_input_coordinator_separator(
coord: &mut InputCoordinator,
id: impl Into<WidgetId>,
rect: Rect,
kind: SeparatorKind,
layer: &LayerId,
state: &mut SeparatorDragState,
) {
let _ = state; register_separator(coord, id, rect, kind, layer);
}
pub fn register_context_manager_separator(
ctx: &mut ContextManager,
render: &mut dyn RenderContext,
id: impl Into<WidgetId>,
rect: Rect,
kind: SeparatorKind,
layer: &LayerId,
view: &SeparatorView,
settings: &SeparatorSettings,
) {
let id: WidgetId = id.into();
let state = ctx.registry.get_or_insert_with(id.clone(), SeparatorDragState::default);
register_input_coordinator_separator(&mut ctx.input, id, rect, kind, layer, state);
draw_separator(render, rect, view, settings);
}
pub fn register_layout_manager_separator<P: DockPanel>(
layout: &mut LayoutManager<P>,
render: &mut dyn RenderContext,
parent: LayoutNodeId,
id: impl Into<WidgetId>,
rect: Rect,
kind: SeparatorKind,
view: &SeparatorView,
settings: &SeparatorSettings,
) {
let id: WidgetId = id.into();
let sense = match kind { SeparatorKind::Divider => Sense::NONE, SeparatorKind::ResizeHandle => Sense::DRAG };
let layer = layout.compute_layer_for(parent);
layout.tree_mut().add_widget(parent, WidgetNode { id: id.clone(), kind: WidgetKind::Separator, rect, sense });
register_context_manager_separator(
layout.ctx_mut(), render, id, rect, kind, &layer, view, settings,
);
}