clat_gui 0.1.3

High-performance, cross-platform Rust desktop GUI framework.
Documentation
use super::layout_manager::{LayoutStrategy, LayoutConstraints, LayoutResult, ComponentId};
use std::collections::HashMap;

// 水平布局容器
pub struct HorizontalLayout {
    children: HashMap<ComponentId, f32>, // 子组件ID -> 权重
    spacing: f32,
    padding: f32,
}

impl HorizontalLayout {
    pub fn new(spacing: f32, padding: f32) -> Self {
        Self {
            children: HashMap::new(),
            spacing,
            padding,
        }
    }
}

impl LayoutStrategy for HorizontalLayout {
    fn calculate_layout(&self, constraints: LayoutConstraints) -> LayoutResult {
        // 计算总权重
        let total_weight: f32 = self.children.values().sum();
        let child_count = self.children.len() as f32;
        
        // 计算可用空间
        let available_width = constraints.max_width - (self.padding * 2.0) - 
                             (self.spacing * (child_count - 1.0)).max(0.0);
        
        // 计算最终尺寸
        let width = constraints.max_width.min(constraints.min_width.max(
            self.padding * 2.0 + 
            (if total_weight > 0.0 { available_width } else { 0.0 }) + 
            (self.spacing * (child_count - 1.0)).max(0.0)
        ));
        
        LayoutResult {
            x: 0.0,
            y: 0.0,
            width,
            height: constraints.max_height,
        }
    }
    
    fn add_child(&mut self, child_id: ComponentId, weight: f32) {
        self.children.insert(child_id, weight.max(0.01));
    }
    
    fn remove_child(&mut self, child_id: ComponentId) {
        self.children.remove(&child_id);
    }
    
    fn update_child_constraints(&self, 
                               child_id: ComponentId, 
                               parent_constraints: LayoutConstraints) -> LayoutConstraints {
        if let Some(weight) = self.children.get(&child_id) {
            let total_weight: f32 = self.children.values().sum();
            let child_count = self.children.len() as f32;
            
            let available_width = parent_constraints.max_width - (self.padding * 2.0) - 
                                 (self.spacing * (child_count - 1.0)).max(0.0);
            
            // 计算子组件的宽度
            let child_width = if total_weight > 0.0 {
                (available_width * weight / total_weight).max(0.0)
            } else {
                0.0
            };
            
            LayoutConstraints {
                min_width: child_width,
                max_width: child_width,
                min_height: 0.0,
                max_height: parent_constraints.max_height - (self.padding * 2.0),
            }
        } else {
            parent_constraints
        }
    }
}

// 垂直布局容器
pub struct VerticalLayout {
    children: HashMap<ComponentId, f32>, // 子组件ID -> 权重
    spacing: f32,
    padding: f32,
}

impl VerticalLayout {
    pub fn new(spacing: f32, padding: f32) -> Self {
        Self {
            children: HashMap::new(),
            spacing,
            padding,
        }
    }
}

impl LayoutStrategy for VerticalLayout {
    fn calculate_layout(&self, constraints: LayoutConstraints) -> LayoutResult {
        // 计算总权重
        let total_weight: f32 = self.children.values().sum();
        let child_count = self.children.len() as f32;
        
        // 计算可用空间
        let available_height = constraints.max_height - (self.padding * 2.0) - 
                              (self.spacing * (child_count - 1.0)).max(0.0);
        
        // 计算最终尺寸
        let height = constraints.max_height.min(constraints.min_height.max(
            self.padding * 2.0 + 
            (if total_weight > 0.0 { available_height } else { 0.0 }) + 
            (self.spacing * (child_count - 1.0)).max(0.0)
        ));
        
        LayoutResult {
            x: 0.0,
            y: 0.0,
            width: constraints.max_width,
            height,
        }
    }
    
    fn add_child(&mut self, child_id: ComponentId, weight: f32) {
        self.children.insert(child_id, weight.max(0.01));
    }
    
    fn remove_child(&mut self, child_id: ComponentId) {
        self.children.remove(&child_id);
    }
    
    fn update_child_constraints(&self, 
                               child_id: ComponentId, 
                               parent_constraints: LayoutConstraints) -> LayoutConstraints {
        if let Some(weight) = self.children.get(&child_id) {
            let total_weight: f32 = self.children.values().sum();
            let child_count = self.children.len() as f32;
            
            let available_height = parent_constraints.max_height - (self.padding * 2.0) - 
                                 (self.spacing * (child_count - 1.0)).max(0.0);
            
            // 计算子组件的高度
            let child_height = if total_weight > 0.0 {
                (available_height * weight / total_weight).max(0.0)
            } else {
                0.0
            };
            
            LayoutConstraints {
                min_width: 0.0,
                max_width: parent_constraints.max_width - (self.padding * 2.0),
                min_height: child_height,
                max_height: child_height,
            }
        } else {
            parent_constraints
        }
    }
}

// 网格布局容器
pub struct GridLayout {
    rows: u32,
    cols: u32,
    cell_width: f32,
    cell_height: f32,
    spacing: f32,
    padding: f32,
    cell_span: HashMap<ComponentId, (u32, u32, u32, u32)>, // 子组件ID -> (row, col, row_span, col_span)
}

impl GridLayout {
    pub fn new(rows: u32, cols: u32, cell_width: f32, cell_height: f32, spacing: f32, padding: f32) -> Self {
        Self {
            rows,
            cols,
            cell_width,
            cell_height,
            spacing,
            padding,
            cell_span: HashMap::new(),
        }
    }
    
    // 设置单元格跨度
    pub fn set_cell_span(&mut self, child_id: ComponentId, row: u32, col: u32, row_span: u32, col_span: u32) {
        if row < self.rows && col < self.cols {
            self.cell_span.insert(child_id, (row, col, row_span.max(1), col_span.max(1)));
        }
    }
}

impl LayoutStrategy for GridLayout {
    fn calculate_layout(&self, constraints: LayoutConstraints) -> LayoutResult {
        // 计算网格总宽度
        let total_width = (self.cell_width * self.cols as f32) + 
                         (self.spacing * (self.cols - 1) as f32) + 
                         (self.padding * 2.0);
        
        // 计算网格总高度
        let total_height = (self.cell_height * self.rows as f32) + 
                          (self.spacing * (self.rows - 1) as f32) + 
                          (self.padding * 2.0);
        
        LayoutResult {
            x: 0.0,
            y: 0.0,
            width: total_width.min(constraints.max_width),
            height: total_height.min(constraints.max_height),
        }
    }
    
    fn add_child(&mut self, child_id: ComponentId, weight: f32) {
        // 自动分配到下一个可用单元格
        let index = self.cell_span.len();
        let row = (index as u32) / self.cols;
        let col = (index as u32) % self.cols;
        
        if row < self.rows {
            self.set_cell_span(child_id, row, col, 1, 1);
        }
    }
    
    fn remove_child(&mut self, child_id: ComponentId) {
        self.cell_span.remove(&child_id);
    }
    
    fn update_child_constraints(&self, 
                               child_id: ComponentId, 
                               parent_constraints: LayoutConstraints) -> LayoutConstraints {
        if let Some((row, col, row_span, col_span)) = self.cell_span.get(&child_id) {
            let cell_width = self.cell_width;
            let cell_height = self.cell_height;
            
            // 计算子组件的尺寸
            let width = (cell_width * *col_span as f32) + 
                       (self.spacing * (*col_span - 1) as f32);
            let height = (cell_height * *row_span as f32) + 
                        (self.spacing * (*row_span - 1) as f32);
            
            LayoutConstraints {
                min_width: width,
                max_width: width,
                min_height: height,
                max_height: height,
            }
        } else {
            parent_constraints
        }
    }
}