GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
Update layout section padding to be uniform and align button/keybinds widgets
src/layout.rs | 6 +++---
src/widget/display/preview.rs | 19 +++++++++++--------
src/widget/input/button.rs | 25 ++++++++++++++++++++++++-
src/widget/input/keybinds_control.rs | 16 ++++++++++++----
src/widget/json_layout.rs | 4 ++++
5 files changed, 54 insertions(+), 16 deletions(-)
diff --git a/src/layout.rs b/src/layout.rs
index 568f04c..f6c6fcb 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -2989,7 +2989,7 @@ impl Section {
} else {
((usable_w + gap) / (min_col_width + gap)).floor().max(1.0).min(2.0) as usize
};
- let content_start_y = top + font_size + 5.0;
+ let content_start_y = top + pad + 19.0;
let grid = Grid::new(left + margin_x, content_start_y, usable_w, min_col_width, gap, max_cols);
Self { left, top, content_y: content_start_y, cw, label_width, is_child, grid, last_col: usize::MAX }
@@ -4146,7 +4146,7 @@ impl<'a, P: RenderTarget> SectionContext<'a, P> {
} else {
((usable_w + gap) / (min_col_width + gap)).floor().max(1.0).min(2.0) as usize
};
- let content_start_y = top + font_size + 5.0;
+ let content_start_y = top + pad + 19.0;
let grid = Grid::new(left + margin_x, content_start_y, usable_w, min_col_width, gap, max_cols);
Self {
@@ -4588,7 +4588,7 @@ mod tests {
stack.add_widget(&mut w1, 50.0, 30.0, &mut dummy);
// Standard margin should be applied
- assert_eq!(w1.x, 30.0);
+ assert_eq!(w1.x, 38.0);
assert_eq!(w1.y, start_y);
let mut w2 = MockWidget { x: 0.0, y: 0.0, w: 0.0, h: 0.0 };
diff --git a/src/widget/display/preview.rs b/src/widget/display/preview.rs
index 7ea879b..76bae42 100644
--- a/src/widget/display/preview.rs
+++ b/src/widget/display/preview.rs
@@ -247,18 +247,21 @@ impl PreviewState {
}
let half_h = ch * 0.5;
+ let pad = crate::layout::section_padding();
// 1. Top pane: File Preview Section
let mut preview_sec = SectionContext::new(&mut canvas, cx + 4.0, cy + 12.0, cw - 8.0, "Preview", false, false);
- preview_sec.content_y = cy + half_h - 20.0;
+ let rect_y = cy + pad + 31.0;
+ let rect_h = half_h - 2.0 * pad - 43.0;
+ preview_sec.content_y = cy + half_h - pad - 12.0;
preview_sec.finish();
let bg_color = color::scrollinglist_bg_color();
- canvas.rect(bg_color, cx + 12.0, cy + 32.0, cw - 24.0, half_h - 40.0);
+ canvas.rect(bg_color, cx + 12.0, rect_y, cw - 24.0, rect_h);
if let Some(image_data) = &self.image_preview {
let box_w = cw - 24.0;
- let box_h = half_h - 40.0;
+ let box_h = rect_h;
let img_w = image_data.width as f32;
let img_h = image_data.height as f32;
@@ -270,7 +273,7 @@ impl PreviewState {
let draw_h = img_h * scale;
let start_x = cx + 12.0 + (box_w - draw_w) * 0.5;
- let start_y = cy + 32.0 + (box_h - draw_h) * 0.5;
+ let start_y = rect_y + (box_h - draw_h) * 0.5;
for row in 0..image_data.height {
let mut col = 0;
@@ -317,9 +320,9 @@ impl PreviewState {
}
}
} else if let Some(content) = &self.content_preview {
- let mut text_y = cy + 44.0;
+ let mut text_y = rect_y + 12.0;
for line in content.lines().skip(self.scroll_line) {
- if text_y + 14.0 > cy + half_h - 16.0 {
+ if text_y + 14.0 > rect_y + rect_h - 8.0 {
break;
}
let limit = (((cw - 40.0) / 6.8).floor() as usize).max(20);
@@ -334,7 +337,7 @@ impl PreviewState {
text_y += 15.0;
}
} else {
- canvas.text("No preview available", cx + 20.0, cy + 44.0, 11.0, text_dim);
+ canvas.text("No preview available", cx + 20.0, rect_y + 12.0, 11.0, text_dim);
}
// 2. Bottom pane: Details Section
@@ -349,7 +352,7 @@ impl PreviewState {
("Modified", &self.modified),
];
- let details_content_start_y = bottom_y + 19.0;
+ let details_content_start_y = bottom_y + pad + 19.0;
let mut details_content_end_y = details_content_start_y + 36.0 + details.len() as f32 * 20.0;
if !self.target.is_empty() {
details_content_end_y += 24.0;
diff --git a/src/widget/input/button.rs b/src/widget/input/button.rs
index 1042c6e..a3f0c9e 100644
--- a/src/widget/input/button.rs
+++ b/src/widget/input/button.rs
@@ -21,6 +21,7 @@ pub struct Button {
pub hover_bg: Option<[f32; 4]>,
pub label_color: Option<[f32; 4]>,
pub justify: Justification,
+ pub svg: Option<Svg>,
}
impl std::fmt::Debug for Button {
@@ -49,6 +50,7 @@ impl Button {
hover_bg: None,
label_color: None,
justify: Justification::Center,
+ svg: None,
}
}
@@ -64,6 +66,7 @@ impl Button {
hover_bg: None,
label_color: None,
justify: Justification::Center,
+ svg: None,
}
}
@@ -79,6 +82,7 @@ impl Button {
hover_bg: None,
label_color: None,
justify: Justification::Center,
+ svg: None,
}
}
@@ -94,6 +98,7 @@ impl Button {
hover_bg: None,
label_color: None,
justify: Justification::Center,
+ svg: None,
}
}
@@ -102,6 +107,11 @@ impl Button {
self
}
+ pub fn with_svg(mut self, svg: Svg) -> Self {
+ self.svg = Some(svg);
+ self
+ }
+
pub fn with_selected(mut self, selected: bool) -> Self {
self.selected = selected;
self
@@ -217,6 +227,9 @@ impl Element for Button {
}
fn text_labels(&self) -> Vec<TextLabel> {
+ if self.svg.is_some() {
+ return Vec::new();
+ }
let mut labels = Vec::new();
if let Some(ref label) = self.base.label {
let font_size = 12.0;
@@ -270,7 +283,17 @@ impl Element for Button {
}
fn extra_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
- vec![(self.base.x, self.base.y, self.base.w, self.base.h, self.color())]
+ let mut quads = vec![(self.base.x, self.base.y, self.base.w, self.base.h, self.color())];
+ if let Some(ref svg) = self.svg {
+ let svg_x = self.base.x + (self.base.w - svg.w) / 2.0;
+ let svg_y = self.base.y + (self.base.h - svg.h) / 2.0;
+ let dx = svg_x - svg.x;
+ let dy = svg_y - svg.y;
+ for q in &svg.quads {
+ quads.push((q.0 + dx, q.1 + dy, q.2, q.3, q.4));
+ }
+ }
+ quads
}
fn rounded_corners(&self) -> (bool, bool, bool, bool) {
diff --git a/src/widget/input/keybinds_control.rs b/src/widget/input/keybinds_control.rs
index b168c04..1a14a19 100644
--- a/src/widget/input/keybinds_control.rs
+++ b/src/widget/input/keybinds_control.rs
@@ -15,7 +15,15 @@ impl KeybindRow {
pub fn new(binding: String, command: String) -> Self {
let key_input = TextBox::new(binding).with_placeholder("e.g. super+shift+q");
let cmd_input = TextBox::new(command).with_placeholder("e.g. close");
- let remove_button = Button::new(0.0, 0.0, 0.0, 0.0).with_label("Remove");
+
+ let remove_svg = Svg::from_file("/home/lsgalante/Dropbox/cce/cce-icons/svg/x.svg", 0.0, 0.0, 14.0, 14.0);
+ let mut remove_button = Button::new(0.0, 0.0, 0.0, 0.0);
+ if let Some(svg) = remove_svg {
+ remove_button = remove_button.with_svg(svg);
+ } else {
+ remove_button = remove_button.with_label("Remove");
+ }
+
Self {
key_input,
cmd_input,
@@ -171,9 +179,9 @@ impl Element for KeybindsControl {
let gap_x = 6.0;
let row_usable_w = usable_w - 2.0 * gap_x;
- let key_w = row_usable_w * 0.36;
- let cmd_w = row_usable_w * 0.49;
- let remove_w = row_usable_w * 0.15;
+ let key_w = row_usable_w * 0.38;
+ let cmd_w = row_usable_w * 0.50;
+ let remove_w = row_usable_w * 0.12;
let mut curr_y = origin.y + pad_y;
let self_ptr = self.as_ptr();
diff --git a/src/widget/json_layout.rs b/src/widget/json_layout.rs
index 10d4d64..d6eabfe 100644
--- a/src/widget/json_layout.rs
+++ b/src/widget/json_layout.rs
@@ -610,4 +610,8 @@ impl Element for JsonLayoutWidget {
fn on_cursor_moved(&mut self, px: f32, py: f32, ctx: &mut UiContext) -> bool {
self.handle_event(&Event::PointerMove { x: px, y: py, local_x: px, local_y: py }, ctx)
}
+
+ fn children(&self, _ctx: &UiContext) -> Vec<*mut (dyn Element + 'static)> {
+ self.widgets.iter().map(|w| w.widget.as_ptr()).collect()
+ }
}