git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

src/widget/layout_helper.rs (3.2K)

  1 use crate::widget::WidgetHost;
  2 
  3 pub struct ColumnLayout {
  4     pub x: f32,
  5     pub y: f32,
  6     pub width: f32,
  7     pub gap: f32,
  8     pub margin: f32,
  9     current_y: f32,
 10 }
 11 
 12 impl ColumnLayout {
 13     pub fn new(x: f32, y: f32, width: f32, gap: f32, margin: f32) -> Self {
 14         Self {
 15             x,
 16             y,
 17             width,
 18             gap,
 19             margin,
 20             current_y: y + margin,
 21         }
 22     }
 23 
 24     /// A column inside a pane plate: the pane rung's padding as the margin
 25     /// and its gap between widgets (`plate_padding` / `plate_gap`).
 26     pub fn pane(x: f32, y: f32, width: f32) -> Self {
 27         Self::new(x, y, width, crate::layout::plate_gap(), crate::layout::plate_padding())
 28     }
 29 
 30     /// A column of controls with the control gap between them and no
 31     /// margin of its own (`control_gap`).
 32     pub fn controls(x: f32, y: f32, width: f32) -> Self {
 33         Self::new(x, y, width, crate::layout::control_gap(), 0.0)
 34     }
 35 
 36     /// `height` is the CONTENT height; the widget's block adds its label strip.
 37     pub fn add_widget(&mut self, widget: &mut dyn WidgetHost, height: f32) {
 38         let total_h = height + widget.label_strip();
 39         widget.set_rect(self.x + self.margin, self.current_y, self.width - 2.0 * self.margin, total_h);
 40         self.current_y += total_h + self.gap;
 41     }
 42 
 43     pub fn add_row(&mut self, widgets: &[*mut dyn WidgetHost], height: f32, gap: f32) {
 44         let count = widgets.len();
 45         if count == 0 {
 46             return;
 47         }
 48         let mut max_label_off = 0.0;
 49         for &widget_ptr in widgets {
 50             unsafe {
 51                 let off = (*widget_ptr).label_strip();
 52                 if off > max_label_off {
 53                     max_label_off = off;
 54                 }
 55             }
 56         }
 57         let total_h = height + max_label_off;
 58         let total_width = self.width - 2.0 * self.margin;
 59         let widget_w = (total_width - (count as f32 - 1.0) * gap) / count as f32;
 60         let mut curr_x = self.x + self.margin;
 61         for &widget_ptr in widgets {
 62             unsafe {
 63                 // Content lines up on one row; a shorter label strip starts lower.
 64                 let off = (*widget_ptr).label_strip();
 65                 (*widget_ptr).set_rect(curr_x, self.current_y + max_label_off - off, widget_w, height + off);
 66             }
 67             curr_x += widget_w + gap;
 68         }
 69         self.current_y += total_h + self.gap;
 70     }
 71 
 72     pub fn current_y(&self) -> f32 {
 73         self.current_y - self.gap + self.margin
 74     }
 75 }
 76 
 77 pub struct RowLayout {
 78     pub x: f32,
 79     pub y: f32,
 80     pub height: f32,
 81     pub gap: f32,
 82     pub margin: f32,
 83     current_x: f32,
 84 }
 85 
 86 impl RowLayout {
 87     pub fn new(x: f32, y: f32, height: f32, gap: f32, margin: f32) -> Self {
 88         Self {
 89             x,
 90             y,
 91             height,
 92             gap,
 93             margin,
 94             current_x: x + margin,
 95         }
 96     }
 97 
 98     pub fn add_widget(&mut self, widget: &mut dyn WidgetHost, width: f32) {
 99         widget.set_rect(self.current_x, self.y + self.margin, width, self.height - 2.0 * self.margin);
100         self.current_x += width + self.gap;
101     }
102 
103     pub fn current_x(&self) -> f32 {
104         self.current_x - self.gap + self.margin
105     }
106 }