GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
Add page and layer background color and opacity support
src/color.rs | 33 ++++++++++++++++++
src/layout.rs | 79 +++++++++++++++++++++++++++++++++++++++++++
src/widget/container/layer.rs | 28 ++++++++++++---
src/widget/container/page.rs | 17 ++++++++--
src/widget/mod.rs | 3 ++
5 files changed, 154 insertions(+), 6 deletions(-)
diff --git a/src/color.rs b/src/color.rs
index aec8056..006a08c 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -38,6 +38,9 @@ static TOGGLE_OFF_COLOR: RwLock<[f32; 4]> = RwLock::new(TOGGLE_OFF);
static SCROLLINGLIST_BG_COLOR: RwLock<[f32; 4]> = RwLock::new([0.08, 0.08, 0.12, 0.3]);
static BREADCRUMB_BG_COLOR: RwLock<[f32; 4]> = RwLock::new([0.08, 0.08, 0.12, 1.0]);
static POPOVER_BG_COLOR: RwLock<[f32; 4]> = RwLock::new([0.08, 0.08, 0.12, 1.0]);
+static PAGE_COLOR: RwLock<[f32; 4]> = RwLock::new([0.0, 0.0, 0.0, 0.0]);
+static LAYER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.0, 0.0, 0.0, 0.0]);
+
pub fn node_color() -> [f32; 4] {
@@ -164,6 +167,13 @@ fn parse_and_set_colors(content: &str) {
if let Some(c) = parse_hex(trimmed, "popover_bg_color") {
parsed_popover_bg = Some(c);
}
+ if let Some(c) = parse_hex(trimmed, "page_color") {
+ if let Ok(mut lock) = PAGE_COLOR.write() { *lock = c; }
+ }
+ if let Some(c) = parse_hex(trimmed, "layer_color") {
+ if let Ok(mut lock) = LAYER_COLOR.write() { *lock = c; }
+ }
+
}
if let Some(c) = parsed_scrollinglist_bg {
if let Ok(mut lock) = SCROLLINGLIST_BG_COLOR.write() {
@@ -219,6 +229,29 @@ pub fn set_page_low_color(color: [f32; 4]) {
}
}
+pub fn page_color() -> [f32; 4] {
+ load_colors_once();
+ *PAGE_COLOR.read().unwrap()
+}
+
+pub fn set_page_color(color: [f32; 4]) {
+ if let Ok(mut lock) = PAGE_COLOR.write() {
+ *lock = color;
+ }
+}
+
+pub fn layer_color() -> [f32; 4] {
+ load_colors_once();
+ *LAYER_COLOR.read().unwrap()
+}
+
+pub fn set_layer_color(color: [f32; 4]) {
+ if let Ok(mut lock) = LAYER_COLOR.write() {
+ *lock = color;
+ }
+}
+
+
pub fn color_borders_color() -> [f32; 4] {
load_colors_once();
*COLOR_BORDERS_COLOR.read().unwrap()
diff --git a/src/layout.rs b/src/layout.rs
index f42d9d3..4879ce1 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -61,6 +61,9 @@ static DROPDOWN_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
static TOGGLE_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
static PLATE_CORNER_RADIUS: RwLock<f32> = RwLock::new(12.0);
static PLATE_OPACITY: RwLock<f32> = RwLock::new(1.0);
+static PAGE_OPACITY: RwLock<f32> = RwLock::new(1.0);
+static LAYER_OPACITY: RwLock<f32> = RwLock::new(1.0);
+
@@ -223,6 +226,25 @@ pub fn reload_config() {
}
}
}
+ if let Some(rest) = trimmed.strip_prefix("page_opacity") {
+ let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
+ let val_str = rest.trim_end_matches('"').trim();
+ if let Ok(val) = val_str.parse::<f32>() {
+ if let Ok(mut lock) = PAGE_OPACITY.write() {
+ *lock = val;
+ }
+ }
+ }
+ if let Some(rest) = trimmed.strip_prefix("layer_opacity") {
+ let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
+ let val_str = rest.trim_end_matches('"').trim();
+ if let Ok(val) = val_str.parse::<f32>() {
+ if let Ok(mut lock) = LAYER_OPACITY.write() {
+ *lock = val;
+ }
+ }
+ }
+
if let Some(rest) = trimmed.strip_prefix("toggle_height") {
@@ -781,6 +803,63 @@ pub fn set_plate_opacity(opacity: f32) {
}
}
+pub fn page_opacity() -> f32 {
+ use std::sync::Once;
+ static INIT: Once = Once::new();
+ INIT.call_once(|| {
+ if let Some(content) = read_config() {
+ for line in content.lines() {
+ let trimmed = line.trim();
+ if let Some(rest) = trimmed.strip_prefix("page_opacity") {
+ let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
+ let val_str = rest.trim_end_matches('"').trim();
+ if let Ok(val) = val_str.parse::<f32>() {
+ if let Ok(mut lock) = PAGE_OPACITY.write() {
+ *lock = val;
+ }
+ }
+ }
+ }
+ }
+ });
+ *PAGE_OPACITY.read().unwrap()
+}
+
+pub fn set_page_opacity(opacity: f32) {
+ if let Ok(mut lock) = PAGE_OPACITY.write() {
+ *lock = opacity;
+ }
+}
+
+pub fn layer_opacity() -> f32 {
+ use std::sync::Once;
+ static INIT: Once = Once::new();
+ INIT.call_once(|| {
+ if let Some(content) = read_config() {
+ for line in content.lines() {
+ let trimmed = line.trim();
+ if let Some(rest) = trimmed.strip_prefix("layer_opacity") {
+ let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
+ let val_str = rest.trim_end_matches('"').trim();
+ if let Ok(val) = val_str.parse::<f32>() {
+ if let Ok(mut lock) = LAYER_OPACITY.write() {
+ *lock = val;
+ }
+ }
+ }
+ }
+ }
+ });
+ *LAYER_OPACITY.read().unwrap()
+}
+
+pub fn set_layer_opacity(opacity: f32) {
+ if let Ok(mut lock) = LAYER_OPACITY.write() {
+ *lock = opacity;
+ }
+}
+
+
pub fn color_selector_height() -> f32 {
diff --git a/src/widget/container/layer.rs b/src/widget/container/layer.rs
index e3de6d1..6afa901 100644
--- a/src/widget/container/layer.rs
+++ b/src/widget/container/layer.rs
@@ -30,6 +30,8 @@ impl Layer {
impl Element for Layer {
fn base(&self) -> Option<&Widget> { Some(&self.base) }
+ fn is_layer(&self) -> bool { true }
+
fn base_mut(&mut self) -> Option<&mut Widget> { Some(&mut self.base) }
fn as_any(&self) -> &dyn std::any::Any { self }
fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self }
@@ -52,9 +54,12 @@ impl Element for Layer {
}
fn color(&self) -> [f32; 4] {
- [0.0, 0.0, 0.0, 0.0]
+ let mut c = crate::colors::layer_color();
+ c[3] *= crate::layout::layer_opacity();
+ c
}
+
fn visible(&self) -> bool {
self.visible
}
@@ -98,12 +103,27 @@ impl Element for Layer {
return Vec::new();
}
let mut quads = Vec::new();
+ let mut has_page_parent = false;
+ if let Some(parent_ptr) = self.parent {
+ unsafe {
+ if (*parent_ptr).is_page() {
+ has_page_parent = true;
+ }
+ }
+ }
+ if !has_page_parent {
+ let c = self.color();
+ if c[3] > 0.0 {
+ let (x, y, w, h) = self.rect();
+ quads.push((x, y, w, h, c));
+ }
+ }
for &child_ptr in &self.children {
let widget = unsafe { &*child_ptr };
- let c = widget.color();
- if c[3] > 0.0 {
+ let cc = widget.color();
+ if cc[3] > 0.0 {
let (wx, wy, ww, wh) = widget.rect();
- quads.push((wx, wy, ww, wh, c));
+ quads.push((wx, wy, ww, wh, cc));
}
quads.extend(widget.all_quads(ctx));
}
diff --git a/src/widget/container/page.rs b/src/widget/container/page.rs
index c774895..f4c5665 100644
--- a/src/widget/container/page.rs
+++ b/src/widget/container/page.rs
@@ -122,6 +122,8 @@ impl Page {
impl Element for Page {
fn base(&self) -> Option<&Widget> { Some(&self.base.base) }
+ fn is_page(&self) -> bool { true }
+
fn base_mut(&mut self) -> Option<&mut Widget> { Some(&mut self.base.base) }
fn as_any(&self) -> &dyn std::any::Any { self }
fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self }
@@ -145,9 +147,12 @@ impl Element for Page {
}
fn color(&self) -> [f32; 4] {
- [0.0, 0.0, 0.0, 0.0]
+ let mut c = crate::colors::page_color();
+ c[3] *= crate::layout::page_opacity();
+ c
}
+
fn visible(&self) -> bool {
self.visible
}
@@ -189,9 +194,17 @@ impl Element for Page {
if !self.visible {
return Vec::new();
}
- self.base.all_quads(ctx)
+ let mut quads = Vec::new();
+ let c = self.color();
+ if c[3] > 0.0 {
+ let (x, y, w, h) = self.rect();
+ quads.push((x, y, w, h, c));
+ }
+ quads.extend(self.base.all_quads(ctx));
+ quads
}
+
fn text_labels(&self) -> Vec<TextLabel> {
if !self.visible {
return Vec::new();
diff --git a/src/widget/mod.rs b/src/widget/mod.rs
index 5ae6400..af96410 100644
--- a/src/widget/mod.rs
+++ b/src/widget/mod.rs
@@ -494,7 +494,10 @@ pub trait Element {
fn z_index(&self) -> i32 { 0 }
fn is_plate(&self) -> bool { false }
+ fn is_page(&self) -> bool { false }
+ fn is_layer(&self) -> bool { false }
fn rounded_corners(&self) -> (bool, bool, bool, bool) { (false, false, false, false) }
+
fn corner_radius(&self) -> f32 { 12.0 }
fn layout_ignore(&self) -> bool { false }
fn color_u8(&self) -> Option<[u8; 4]> { None }