graphic design tool
git clone https://git.lucas.co/cce-designer.git
Throttle inspector state updates and update cce-ui references
Cargo.toml | 2 +-
src/app.rs | 86 +++++++++++++++++++++++++++++----------------------------
src/graphics.rs | 2 +-
src/main.rs | 31 ++++++++++++---------
src/project.rs | 38 ++++++++++++++++---------
src/render.rs | 22 +++++++--------
src/shortcut.rs | 2 +-
src/window.rs | 74 ++++++++++++++++++++++++-------------------------
8 files changed, 138 insertions(+), 119 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index bf2a8be..09b3fec 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
-clear-ui = { path = "../clear-ui" }
+cce-ui = { path = "../cce-ui" }
smithay-client-toolkit = "0.19.2"
calloop = "0.13.0"
calloop-wayland-source = "0.3.0"
diff --git a/src/app.rs b/src/app.rs
index c14f570..bbb5855 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -6,7 +6,7 @@ use std::io::BufReader;
use serde::{Deserialize, Serialize};
-use clear_ui::widget::{ElementState, MouseButton, MouseScrollDelta, KeyEvent, Key, NamedKey};
+use cce_ui::widget::{ElementState, MouseButton, MouseScrollDelta, KeyEvent, Key, NamedKey};
use smithay_client_toolkit::{
compositor::{CompositorHandler, CompositorState},
@@ -36,9 +36,9 @@ use wayland_client::{
use calloop_wayland_source::WaylandSource;
use wgpu::util::DeviceExt;
-use clear_ui::widget::{Breadcrumb, Canvas, MenuBar, Plate, ParametersBg, Splitter, Spreadsheet, StatusBar, TextLabel, ViewportBg, Element, GraphNode, Graph, Paginator, Button, Checkbox, Slider, Spinbox, ScrollingList, Label, ColorSelector, Switcher};
-use clear_ui::colors;
-use clear_ui::engine::quad_vertices_with_clip;
+use cce_ui::widget::{Breadcrumb, Canvas, MenuBar, Plate, ParametersBg, Splitter, Spreadsheet, StatusBar, TextLabel, ViewportBg, Element, GraphNode, Graph, Paginator, Button, Checkbox, Slider, Spinbox, ScrollingList, Label, ColorSelector, Switcher};
+use cce_ui::colors;
+use cce_ui::engine::quad_vertices_with_clip;
use glyphon::{Attrs, Buffer, Cache, FontSystem, Metrics, Resolution, SwashCache, TextArea, TextAtlas, TextBounds, TextRenderer, Viewport};
use glam::{Mat4, Vec3};
@@ -47,7 +47,7 @@ use crate::project::*;
use crate::render::*;
use crate::shortcut::{Shortcut, ShortcutManager, Action};
use crate::graphics::TexturedVertex;
-use clear_ui::engine::Vertex;
+use cce_ui::engine::Vertex;
use crate::window::{AppState, WindowEvent, LocalPosition};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -450,7 +450,7 @@ impl Element for NodePalette {
fn rect(&self) -> (f32, f32, f32, f32) { (self.x, self.y, self.w, self.h) }
fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) { self.x = x; self.y = y; self.w = w; self.h = h; }
fn color(&self) -> [f32; 4] { [0.0, 0.0, 0.0, 0.0] }
- fn hit_test(&self, px: f32, py: f32, ctx: &clear_ui::context::UiContext) -> bool {
+ fn hit_test(&self, px: f32, py: f32, ctx: &cce_ui::context::UiContext) -> bool {
if ctx.is_coordinate_covered(self as *const Self as *const () as usize, px, py) {
return false;
}
@@ -526,10 +526,10 @@ pub fn make_text_buffer_with_font(font_system: &mut FontSystem, text: &str, size
let metrics = Metrics::new(size, size * 1.4);
let mut buffer = Buffer::new(font_system, metrics);
let mut attrs = Attrs::new();
- let family_name = font.map(|f| clear_ui::layout::parse_font_string(f).0);
+ let family_name = font.map(|f| cce_ui::layout::parse_font_string(f).0);
if let Some(ref name) = family_name {
let family = match name.as_str() {
- "monospace" => glyphon::Family::Name(clear_ui::layout::get_system_monospace_font()),
+ "monospace" => glyphon::Family::Name(cce_ui::layout::get_system_monospace_font()),
"sans-serif" => glyphon::Family::SansSerif,
"serif" => glyphon::Family::Serif,
_ => glyphon::Family::Name(name),
@@ -655,7 +655,7 @@ pub struct ResizeDirection {
}
pub struct State {
- pub wgpu_adapter: clear_ui::backend::WgpuAdapter,
+ pub wgpu_adapter: cce_ui::backend::WgpuAdapter,
pub render_pipeline: wgpu::RenderPipeline,
pub vertex_buffer: wgpu::Buffer,
pub window: XdgWindow,
@@ -722,7 +722,7 @@ pub struct State {
pub widgets: Vec<Box<dyn Element>>,
pub positions: Vec<(f32, f32, f32, f32)>,
- pub splitter_layout: clear_ui::layout::SplitterLayout,
+ pub splitter_layout: cce_ui::layout::SplitterLayout,
pub node_palette_visible: bool,
pub node_palette_query: String,
pub node_palette_filtered: Vec<usize>,
@@ -797,13 +797,14 @@ pub struct State {
pub scroll_speed: f32,
pub last_config_read: Instant,
pub circular_network_pane: bool,
- pub circular_network_layout: clear_ui::layout::CircularPaneLayout,
+ pub circular_network_layout: cce_ui::layout::CircularPaneLayout,
pub is_detached_network: bool,
pub detached_circular_network: bool,
pub last_project_mod_time: Option<std::time::SystemTime>,
pub last_project_check: std::time::Instant,
pub last_inspector_check: std::time::Instant,
pub last_inspector_update: std::time::Instant,
+ pub last_serialized: String,
pub needs_autosave: bool,
pub last_autosave_time: std::time::Instant,
pub window_x: i32,
@@ -855,7 +856,7 @@ pub struct State {
pub last_viewport_height: u32,
pub last_viewport_active_camera: String,
pub last_viewport_show_viewport: bool,
- pub ui_context: clear_ui::context::UiContext,
+ pub ui_context: cce_ui::context::UiContext,
}
impl State {
@@ -904,51 +905,51 @@ impl State {
self.widgets[NODE_PALETTE_IDX].as_any_mut().downcast_mut::<NodePalette>().expect("not a NodePalette")
}
- pub fn menu(&self, idx: usize) -> &dyn clear_ui::widget::MenuController {
+ pub fn menu(&self, idx: usize) -> &dyn cce_ui::widget::MenuController {
self.widgets[idx].as_menu_controller().expect("not a MenuController")
}
- pub fn menu_mut(&mut self, idx: usize) -> &mut dyn clear_ui::widget::MenuController {
+ pub fn menu_mut(&mut self, idx: usize) -> &mut dyn cce_ui::widget::MenuController {
self.widgets[idx].as_menu_controller_mut().expect("not a MenuController")
}
- pub fn graph(&self) -> &dyn clear_ui::widget::GraphController {
+ pub fn graph(&self) -> &dyn cce_ui::widget::GraphController {
self.widgets[CONTENT_IDX].as_graph_controller().expect("not a GraphController")
}
- pub fn graph_mut(&mut self) -> &mut dyn clear_ui::widget::GraphController {
+ pub fn graph_mut(&mut self) -> &mut dyn cce_ui::widget::GraphController {
self.widgets[CONTENT_IDX].as_graph_controller_mut().expect("not a GraphController")
}
- pub fn page_selector(&self, idx: usize) -> &dyn clear_ui::widget::PageSelector {
+ pub fn page_selector(&self, idx: usize) -> &dyn cce_ui::widget::PageSelector {
self.widgets[idx].as_page_selector().expect("not a PageSelector")
}
- pub fn page_selector_mut(&mut self, idx: usize) -> &mut dyn clear_ui::widget::PageSelector {
+ pub fn page_selector_mut(&mut self, idx: usize) -> &mut dyn cce_ui::widget::PageSelector {
self.widgets[idx].as_page_selector_mut().expect("not a PageSelector")
}
- pub fn param(&self) -> &dyn clear_ui::widget::ParamController {
+ pub fn param(&self) -> &dyn cce_ui::widget::ParamController {
self.widgets[PARAM_IDX].as_param_controller().expect("not a ParamController")
}
- pub fn param_mut(&mut self) -> &mut dyn clear_ui::widget::ParamController {
+ pub fn param_mut(&mut self) -> &mut dyn cce_ui::widget::ParamController {
self.widgets[PARAM_IDX].as_param_controller_mut().expect("not a ParamController")
}
- pub fn spreadsheet_mut(&mut self) -> &mut dyn clear_ui::widget::SpreadsheetController {
+ pub fn spreadsheet_mut(&mut self) -> &mut dyn cce_ui::widget::SpreadsheetController {
self.widgets[SPREADSHEET_IDX].as_spreadsheet_controller_mut().expect("not a SpreadsheetController")
}
- pub fn path_mut(&mut self) -> &mut dyn clear_ui::widget::PathController {
+ pub fn path_mut(&mut self) -> &mut dyn cce_ui::widget::PathController {
self.widgets[BREADCRUMB_IDX].as_path_controller_mut().expect("not a PathController")
}
- pub fn geom_mut(&mut self, idx: usize) -> &mut dyn clear_ui::widget::GeomController {
+ pub fn geom_mut(&mut self, idx: usize) -> &mut dyn cce_ui::widget::GeomController {
self.widgets[idx].as_geom_controller_mut().expect("not a GeomController")
}
- pub fn scroll_mut(&mut self, idx: usize) -> &mut dyn clear_ui::widget::ScrollController {
+ pub fn scroll_mut(&mut self, idx: usize) -> &mut dyn cce_ui::widget::ScrollController {
self.widgets[idx].as_scroll_controller_mut().expect("not a ScrollController")
}
@@ -2155,7 +2156,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
scale: f64,
is_detached_network: bool,
) -> Self {
- clear_ui::scale::set_scale_factor(scale as f32);
+ cce_ui::scale::set_scale_factor(scale as f32);
let settings = DesignSettings::load();
let lw = pw as f32 / scale as f32;
let lh = ph as f32 / scale as f32;
@@ -2177,7 +2178,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
let display_ptr = conn.backend().display_id().as_ptr() as *mut std::ffi::c_void;
let surface_ptr = wl_surface.id().as_ptr() as *mut std::ffi::c_void;
- let wgpu_adapter = clear_ui::backend::WgpuAdapter::new(display_ptr, surface_ptr, pw, ph).await;
+ let wgpu_adapter = cce_ui::backend::WgpuAdapter::new(display_ptr, surface_ptr, pw, ph).await;
let device = &wgpu_adapter.device;
let queue = &wgpu_adapter.queue;
@@ -2576,7 +2577,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
});
- let splitter_layout = clear_ui::layout::SplitterLayout::new(sw, SPLITTER_W, MIN_COLUMN);
+ let splitter_layout = cce_ui::layout::SplitterLayout::new(sw, SPLITTER_W, MIN_COLUMN);
let (depth_texture, depth_texture_view) = {
let tex = device.create_texture(&wgpu::TextureDescriptor {
label: Some("Depth Texture"),
@@ -2843,7 +2844,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
scroll_speed: 1.0,
last_config_read: Instant::now(),
circular_network_pane: is_detached_network,
- circular_network_layout: clear_ui::layout::CircularPaneLayout::new(250.0, 300.0, 180.0),
+ circular_network_layout: cce_ui::layout::CircularPaneLayout::new(250.0, 300.0, 180.0),
is_detached_network,
detached_circular_network: false,
last_project_mod_time: {
@@ -2852,7 +2853,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
},
last_project_check: std::time::Instant::now(),
last_inspector_check: std::time::Instant::now(),
- last_inspector_update: std::time::Instant::now(),
+ last_inspector_update: std::time::Instant::now() - std::time::Duration::from_secs(1),
+ last_serialized: String::new(),
needs_autosave: false,
last_autosave_time: std::time::Instant::now(),
window_x: 0,
@@ -2922,7 +2924,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
last_viewport_height: 0,
last_viewport_active_camera: String::new(),
last_viewport_show_viewport: false,
- ui_context: clear_ui::context::UiContext::new(),
+ ui_context: cce_ui::context::UiContext::new(),
};
state.update_inertial_settings();
@@ -2990,20 +2992,20 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
graph.set_skipped_sizes(skipped_row_h, skipped_col_w);
graph.set_grid_origin(active_node_area_x + pan_x, active_node_area_y + pan_y);
graph.set_grid_snap_enabled(grid_snap_enabled);
- if let Some(graph) = self.widgets[CONTENT_IDX].as_any_mut().downcast_mut::<clear_ui::widget::Graph>() {
+ if let Some(graph) = self.widgets[CONTENT_IDX].as_any_mut().downcast_mut::<cce_ui::widget::Graph>() {
graph.set_uniform_background(self.uniform_background);
graph.set_cell_opacity(self.cell_opacity);
graph.set_gap_opacity(self.gap_opacity);
graph.set_cell_color(self.cell_color);
graph.set_gap_color(self.gap_color);
}
- if let Some(menubar) = self.widgets[LEFT_MENUBAR_IDX].as_any_mut().downcast_mut::<clear_ui::widget::MenuBar>() {
+ if let Some(menubar) = self.widgets[LEFT_MENUBAR_IDX].as_any_mut().downcast_mut::<cce_ui::widget::MenuBar>() {
menubar.set_network_opacity(self.network_opacity);
}
- if let Some(breadcrumb) = self.widgets[BREADCRUMB_IDX].as_any_mut().downcast_mut::<clear_ui::widget::Breadcrumb>() {
+ if let Some(breadcrumb) = self.widgets[BREADCRUMB_IDX].as_any_mut().downcast_mut::<cce_ui::widget::Breadcrumb>() {
breadcrumb.set_network_opacity(self.network_opacity);
}
- if let Some(plate) = self.widgets[NETWORK_PANEL_IDX].as_any_mut().downcast_mut::<clear_ui::widget::Plate>() {
+ if let Some(plate) = self.widgets[NETWORK_PANEL_IDX].as_any_mut().downcast_mut::<cce_ui::widget::Plate>() {
plate.set_network_opacity(self.network_opacity);
}
}
@@ -3223,14 +3225,14 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
self.positions[0] = (0.0, 0.0, 0.0, 0.0);
self.positions[LEFT_MENUBAR_IDX] = (0.0, 0.0, 0.0, 0.0);
- if let Some(menubar) = self.widgets[LEFT_MENUBAR_IDX].as_any_mut().downcast_mut::<clear_ui::widget::MenuBar>() {
+ if let Some(menubar) = self.widgets[LEFT_MENUBAR_IDX].as_any_mut().downcast_mut::<cce_ui::widget::MenuBar>() {
menubar.set_curved_circle(None);
}
self.positions[BREADCRUMB_IDX] = (cx - r, cy - r + 45.0, 2.0 * r, BREADCRUMB_H);
self.positions[CONTENT_IDX] = (cx - r, cy - r + 45.0 + BREADCRUMB_H, 2.0 * r, 2.0 * r - (45.0 + BREADCRUMB_H));
self.positions[NETWORK_PANEL_IDX] = (cx - r, cy - r, 2.0 * r, 2.0 * r);
self.widgets[NETWORK_PANEL_IDX].set_rect(cx - r, cy - r, 2.0 * r, 2.0 * r);
- if let Some(plate) = self.widgets[NETWORK_PANEL_IDX].as_any_mut().downcast_mut::<clear_ui::widget::Plate>() {
+ if let Some(plate) = self.widgets[NETWORK_PANEL_IDX].as_any_mut().downcast_mut::<cce_ui::widget::Plate>() {
plate.set_curved_circle(Some((cx, cy, r)));
}
self.positions[SPLITTER1_IDX] = (0.0, 0.0, 0.0, 0.0);
@@ -3427,14 +3429,14 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
let cy = self.circular_network_layout.y;
self.positions[LEFT_MENUBAR_IDX] = (0.0, 0.0, 0.0, 0.0);
- if let Some(menubar) = self.widgets[LEFT_MENUBAR_IDX].as_any_mut().downcast_mut::<clear_ui::widget::MenuBar>() {
+ if let Some(menubar) = self.widgets[LEFT_MENUBAR_IDX].as_any_mut().downcast_mut::<cce_ui::widget::MenuBar>() {
menubar.set_curved_circle(None);
}
self.positions[BREADCRUMB_IDX] = (cx - r, cy - r + 45.0, 2.0 * r, BREADCRUMB_H);
self.positions[CONTENT_IDX] = (cx - r, cy - r + 45.0 + BREADCRUMB_H, 2.0 * r, 2.0 * r - (45.0 + BREADCRUMB_H));
self.positions[NETWORK_PANEL_IDX] = (cx - r, cy - r, 2.0 * r, 2.0 * r);
self.widgets[NETWORK_PANEL_IDX].set_rect(cx - r, cy - r, 2.0 * r, 2.0 * r);
- if let Some(plate) = self.widgets[NETWORK_PANEL_IDX].as_any_mut().downcast_mut::<clear_ui::widget::Plate>() {
+ if let Some(plate) = self.widgets[NETWORK_PANEL_IDX].as_any_mut().downcast_mut::<cce_ui::widget::Plate>() {
plate.set_curved_circle(Some((cx, cy, r)));
}
self.widgets[NETWORK_PANEL_IDX].set_drag_bounds(0.0, 0.0, self.width, self.height);
@@ -3515,7 +3517,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
(0.0, 0.0, 0.0, 0.0)
};
- if let Some(menubar) = self.widgets[LEFT_MENUBAR_IDX].as_any_mut().downcast_mut::<clear_ui::widget::MenuBar>() {
+ if let Some(menubar) = self.widgets[LEFT_MENUBAR_IDX].as_any_mut().downcast_mut::<cce_ui::widget::MenuBar>() {
menubar.set_curved_circle(None);
}
@@ -3526,7 +3528,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
self.positions[CONTENT_IDX] = (px, py + mb_h + bc_h, pw, content_h);
self.positions[NETWORK_PANEL_IDX] = (px, py, pw, ph);
self.widgets[NETWORK_PANEL_IDX].set_rect(px, py, pw, ph);
- if let Some(plate) = self.widgets[NETWORK_PANEL_IDX].as_any_mut().downcast_mut::<clear_ui::widget::Plate>() {
+ if let Some(plate) = self.widgets[NETWORK_PANEL_IDX].as_any_mut().downcast_mut::<cce_ui::widget::Plate>() {
plate.set_curved_circle(None);
}
self.positions[SPLITTER1_IDX] = (0.0, 0.0, 0.0, 0.0);
@@ -5276,7 +5278,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
}
if current_mod_time != self.last_config_mod_time {
self.last_config_mod_time = current_mod_time;
- clear_ui::layout::reload_config();
+ cce_ui::layout::reload_config();
self.update_inertial_settings();
self.update_graph_settings_from_config();
self.rebuild_positions();
@@ -5380,7 +5382,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
tick_changed = true;
}
}
- if clear_ui::widget::hover_animation::tick(dt) {
+ if cce_ui::widget::hover_animation::tick(dt) {
tick_changed = true;
}
self.update_recent_files_layout();
diff --git a/src/graphics.rs b/src/graphics.rs
index e40ffaf..0f8202f 100644
--- a/src/graphics.rs
+++ b/src/graphics.rs
@@ -1,4 +1,4 @@
-use clear_ui::engine::Vertex;
+use cce_ui::engine::Vertex;
#[repr(C)]
#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
diff --git a/src/main.rs b/src/main.rs
index a2c3668..d1b503e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,7 +4,7 @@ use std::path::Path;
use serde::{Deserialize, Serialize};
-use clear_ui::widget::{ElementState, MouseButton, MouseScrollDelta, KeyEvent, Key, NamedKey};
+use cce_ui::widget::{ElementState, MouseButton, MouseScrollDelta, KeyEvent, Key, NamedKey};
use smithay_client_toolkit::{
compositor::{CompositorHandler, CompositorState},
@@ -32,7 +32,7 @@ use wayland_client::{
};
use calloop_wayland_source::WaylandSource;
-use clear_ui::widget::{Breadcrumb, Canvas, MenuBar, Plate, ParametersBg, Splitter, Spreadsheet, StatusBar, ViewportBg, GraphNode, Graph, Paginator, Button, Checkbox, Slider, Spinbox, ScrollingList, Label, ColorSelector, Switcher};
+use cce_ui::widget::{Breadcrumb, Canvas, MenuBar, Plate, ParametersBg, Splitter, Spreadsheet, StatusBar, ViewportBg, GraphNode, Graph, Paginator, Button, Checkbox, Slider, Spinbox, ScrollingList, Label, ColorSelector, Switcher};
use wgpu::util::DeviceExt;
use glyphon::{Attrs, Buffer, Cache, FontSystem, Metrics, Resolution, SwashCache, TextArea, TextAtlas, TextBounds, TextRenderer, Viewport};
use glam::{Mat4, Vec3};
@@ -90,7 +90,7 @@ fn main() {
// Perform a roundtrip to populate output_state with active output scales
event_queue.roundtrip(&mut app).unwrap();
- let scale = clear_ui::wayland::detect_scale_factor(&app.output_state);
+ let scale = cce_ui::wayland::detect_scale_factor(&app.output_state);
let (pw, ph) = if is_detached_network {
((400.0 * scale) as u32, (400.0 * scale) as u32)
@@ -206,8 +206,8 @@ fn main() {
if now.duration_since(pk.last_repeated) >= KEY_REPEAT_INTERVAL {
pk.last_repeated = now;
if let Some(st) = &mut app.state {
- let custom_event = clear_ui::widget::KeyEvent {
- state: clear_ui::widget::ElementState::Pressed,
+ let custom_event = cce_ui::widget::KeyEvent {
+ state: cce_ui::widget::ElementState::Pressed,
logical_key: pk.logical_key.clone(),
text: pk.text.clone(),
repeat: true,
@@ -245,14 +245,19 @@ fn create_memfd_with_data(name: &str, data: &[u8]) -> std::io::Result<std::os::u
}
if let Some(ref inspector) = app.inspector {
if let Some(ref surface) = app.surface {
- let now = std::time::Instant::now();
- if now.duration_since(state.last_inspector_update) >= std::time::Duration::from_millis(100) {
- state.last_inspector_update = now;
- let json = clear_ui::widget::serialize_widgets(&state.widgets);
- if let Ok(raw_fd) = create_memfd_with_data("clear_ui_state", json.as_bytes()) {
- use std::os::unix::io::{FromRawFd, AsFd};
- let file = unsafe { std::fs::File::from_raw_fd(raw_fd) };
- inspector.update_state(surface, file.as_fd(), json.len() as u32);
+ let json = cce_ui::widget::serialize_widgets(&state.widgets);
+ if json != state.last_serialized {
+ let now = std::time::Instant::now();
+ if now.duration_since(state.last_inspector_update) >= std::time::Duration::from_millis(100) {
+ state.last_serialized = json.clone();
+ state.last_inspector_update = now;
+ if let Ok(raw_fd) = create_memfd_with_data("cce_ui_state", json.as_bytes()) {
+ use std::os::unix::io::{FromRawFd, AsFd};
+ let file = unsafe { std::fs::File::from_raw_fd(raw_fd) };
+ inspector.update_state(surface, file.as_fd(), json.len() as u32);
+ }
+ } else {
+ app.redraw = true;
}
}
}
diff --git a/src/project.rs b/src/project.rs
index f88421f..bc276a2 100644
--- a/src/project.rs
+++ b/src/project.rs
@@ -1,9 +1,29 @@
use std::fs;
use std::path::Path;
-use clear_ui::widget::Button;
+use cce_ui::widget::Button;
use crate::app::{State, Project, FsNode, ProjectViewState, CONTENT_IDX, ParamDef};
+fn color_to_hex(rgb: [f32; 3]) -> String {
+ format!("#{:02x}{:02x}{:02x}",
+ (rgb[0] * 255.0).round().clamp(0.0, 255.0) as u8,
+ (rgb[1] * 255.0).round().clamp(0.0, 255.0) as u8,
+ (rgb[2] * 255.0).round().clamp(0.0, 255.0) as u8
+ )
+}
+
+fn hex_to_color(hex: &str) -> Option<[f32; 3]> {
+ let s = hex.trim().strip_prefix('#').unwrap_or(hex.trim());
+ if s.len() == 6 {
+ let r = u8::from_str_radix(&s[0..2], 16).ok()? as f32 / 255.0;
+ let g = u8::from_str_radix(&s[2..4], 16).ok()? as f32 / 255.0;
+ let b = u8::from_str_radix(&s[4..6], 16).ok()? as f32 / 255.0;
+ Some([r, g, b])
+ } else {
+ None
+ }
+}
+
impl State {
@@ -432,12 +452,8 @@ impl State {
ensure_param(vp_node, "Grid Thickness", "spinbox", &((self.grid_thickness * 1000.0) as i32).to_string(), &[], Some(2.0), Some(200.0), Some(1.0));
ensure_param(vp_node, "Origin Guide Size", "spinbox", &((self.origin_size * 10.0) as i32).to_string(), &[], Some(1.0), Some(50.0), Some(1.0));
ensure_param(vp_node, "Camera Pivot Size", "spinbox", &((self.camera_pivot_size * 10.0) as i32).to_string(), &[], Some(1.0), Some(50.0), Some(1.0));
- ensure_param(vp_node, "BG Color R", "spinbox", &((self.viewport_bg_color[0] * 255.0) as i32).to_string(), &[], Some(0.0), Some(255.0), Some(1.0));
- ensure_param(vp_node, "BG Color G", "spinbox", &((self.viewport_bg_color[1] * 255.0) as i32).to_string(), &[], Some(0.0), Some(255.0), Some(1.0));
- ensure_param(vp_node, "BG Color B", "spinbox", &((self.viewport_bg_color[2] * 255.0) as i32).to_string(), &[], Some(0.0), Some(255.0), Some(1.0));
- ensure_param(vp_node, "Grid Color R", "spinbox", &((self.grid_color[0] * 255.0) as i32).to_string(), &[], Some(0.0), Some(255.0), Some(1.0));
- ensure_param(vp_node, "Grid Color G", "spinbox", &((self.grid_color[1] * 255.0) as i32).to_string(), &[], Some(0.0), Some(255.0), Some(1.0));
- ensure_param(vp_node, "Grid Color B", "spinbox", &((self.grid_color[2] * 255.0) as i32).to_string(), &[], Some(0.0), Some(255.0), Some(1.0));
+ ensure_param(vp_node, "Background Color", "color", &color_to_hex(self.viewport_bg_color), &[], None, None, None);
+ ensure_param(vp_node, "Grid Color", "color", &color_to_hex(self.grid_color), &[], None, None, None);
// 4. Parameters subnet
let param_node = find_or_create_subnet(&mut self.fs_root, "Parameters", "utility", (6.0, 0.0));
@@ -488,12 +504,8 @@ impl State {
"Grid Thickness" => if let Ok(val) = p.default.parse::<f32>() { self.grid_thickness = val / 1000.0; }
"Origin Guide Size" => if let Ok(val) = p.default.parse::<f32>() { self.origin_size = val / 10.0; }
"Camera Pivot Size" => if let Ok(val) = p.default.parse::<f32>() { self.camera_pivot_size = val / 10.0; }
- "BG Color R" => if let Ok(val) = p.default.parse::<f32>() { self.viewport_bg_color[0] = val / 255.0; }
- "BG Color G" => if let Ok(val) = p.default.parse::<f32>() { self.viewport_bg_color[1] = val / 255.0; }
- "BG Color B" => if let Ok(val) = p.default.parse::<f32>() { self.viewport_bg_color[2] = val / 255.0; }
- "Grid Color R" => if let Ok(val) = p.default.parse::<f32>() { self.grid_color[0] = val / 255.0; }
- "Grid Color G" => if let Ok(val) = p.default.parse::<f32>() { self.grid_color[1] = val / 255.0; }
- "Grid Color B" => if let Ok(val) = p.default.parse::<f32>() { self.grid_color[2] = val / 255.0; }
+ "Background Color" => if let Some(col) = hex_to_color(&p.default) { self.viewport_bg_color = col; }
+ "Grid Color" => if let Some(col) = hex_to_color(&p.default) { self.grid_color = col; }
"Square Aspect" => if let Ok(val) = p.default.parse::<bool>() { self.square_viewport = val; }
"Show Grid" => if let Ok(val) = p.default.parse::<bool>() { self.show_grid = val; }
"Cube" => if let Ok(val) = p.default.parse::<bool>() { self.show_cube = val; }
diff --git a/src/render.rs b/src/render.rs
index 33cc841..5233059 100644
--- a/src/render.rs
+++ b/src/render.rs
@@ -1,8 +1,8 @@
use glyphon::{Buffer, Resolution, TextArea, TextBounds};
-use clear_ui::widget::TextLabel;
-use clear_ui::colors;
-use clear_ui::widget::Element;
+use cce_ui::widget::TextLabel;
+use cce_ui::colors;
+use cce_ui::widget::Element;
use crate::app::{
State, FsNode,
@@ -15,11 +15,11 @@ use crate::app::{
push_circle_vertices, push_circle_border_vertices,
};
use crate::graphics::TexturedVertex;
-use clear_ui::engine::Vertex;
+use cce_ui::engine::Vertex;
use crate::geometry::{
network_sphere_vertices_with_errors,
};
-use clear_ui::engine::{
+use cce_ui::engine::{
push_widget_vertices, push_extra_quad_vertices,
push_extra_quad_vertices_clipped, push_arc_background_vertices,
};
@@ -262,7 +262,7 @@ impl State {
// Dropdown popover
if w.visible() && (self.focused_widget == Some(idx) || idx == PARAM_IDX) {
- let mut popover_pc = clear_ui::layout::PopoverCollector::new();
+ let mut popover_pc = cce_ui::layout::PopoverCollector::new();
w.render_popover(&mut popover_pc);
for (color, px, py, pw, ph) in popover_pc.rects {
let ndc_x = (px / sw) * 2.0 - 1.0;
@@ -384,7 +384,7 @@ impl State {
fn collect_popovers(
w: &dyn Element,
popovers: &mut Vec<(f32, f32, f32, f32)>,
- ctx: &clear_ui::context::UiContext,
+ ctx: &cce_ui::context::UiContext,
) {
if let Some(rect) = w.popover_rect() {
popovers.push(rect);
@@ -448,7 +448,7 @@ impl State {
..
} = self;
- let clear_ui::backend::WgpuAdapter {
+ let cce_ui::backend::WgpuAdapter {
ref device,
ref queue,
ref mut font_system,
@@ -515,7 +515,7 @@ impl State {
continue;
}
if self.focused_widget == Some(i) || i == PARAM_IDX {
- let mut popover_pc = clear_ui::layout::PopoverCollector::new();
+ let mut popover_pc = cce_ui::layout::PopoverCollector::new();
w.render_popover(&mut popover_pc);
for (t, size, _x, _y, _tc, font_opt, _bounds) in popover_pc.texts {
let key = (t.clone(), (size * 100.0) as u32, font_opt.clone());
@@ -535,7 +535,7 @@ impl State {
fn collect_popovers(
w: &dyn Element,
popovers: &mut Vec<(f32, f32, f32, f32)>,
- ctx: &clear_ui::context::UiContext,
+ ctx: &cce_ui::context::UiContext,
) {
if let Some(rect) = w.popover_rect() {
popovers.push(rect);
@@ -758,7 +758,7 @@ impl State {
continue;
}
if self.focused_widget == Some(i) || i == PARAM_IDX {
- let mut popover_pc = clear_ui::layout::PopoverCollector::new();
+ let mut popover_pc = cce_ui::layout::PopoverCollector::new();
w.render_popover(&mut popover_pc);
for (t, size, x, y, tc, font_opt, label_bounds) in popover_pc.texts {
let key = (t.clone(), (size * 100.0) as u32, font_opt.clone());
diff --git a/src/shortcut.rs b/src/shortcut.rs
index c8ef0be..92970be 100644
--- a/src/shortcut.rs
+++ b/src/shortcut.rs
@@ -1,4 +1,4 @@
-use clear_ui::widget::{Key, NamedKey};
+use cce_ui::widget::{Key, NamedKey};
use crate::ModifiersState;
#[derive(Debug, Clone, Copy, PartialEq)]
diff --git a/src/window.rs b/src/window.rs
index 3135d77..3404e95 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -6,7 +6,7 @@ use std::net::TcpListener;
use serde::{Deserialize, Serialize};
-use clear_ui::widget::{ElementState, MouseButton, MouseScrollDelta, KeyEvent, Key, NamedKey};
+use cce_ui::widget::{ElementState, MouseButton, MouseScrollDelta, KeyEvent, Key, NamedKey};
use smithay_client_toolkit::{
compositor::{CompositorHandler, CompositorState},
@@ -36,8 +36,8 @@ use wayland_client::{
use calloop_wayland_source::WaylandSource;
use wgpu::util::DeviceExt;
-use clear_ui::widget::{Breadcrumb, Canvas, MenuBar, Plate, ParametersBg, Splitter, Spreadsheet, StatusBar, TextLabel, ViewportBg, Element, GraphNode, Graph, Paginator, Button, Checkbox, Slider, Spinbox, ScrollingList, Label, ColorSelector, Switcher};
-use clear_ui::colors;
+use cce_ui::widget::{Breadcrumb, Canvas, MenuBar, Plate, ParametersBg, Splitter, Spreadsheet, StatusBar, TextLabel, ViewportBg, Element, GraphNode, Graph, Paginator, Button, Checkbox, Slider, Spinbox, ScrollingList, Label, ColorSelector, Switcher};
+use cce_ui::colors;
use glyphon::{Attrs, Buffer, Cache, FontSystem, Metrics, Resolution, SwashCache, TextArea, TextAtlas, TextBounds, TextRenderer, Viewport};
use glam::{Mat4, Vec3};
@@ -46,7 +46,7 @@ use crate::project::*;
use crate::render::*;
use crate::shortcut::{Shortcut, ShortcutManager, Action};
use crate::app::{State, CustomEvent, HttpAction, ModifiersState, TouchPhase, DesignSettings, param_display, NodePalette, NODE_PALETTE_IDX, LEFT_MENUBAR_IDX, RIGHT_MENUBAR_IDX, PARAM_MENUBAR_IDX, SPREADSHEET_MENUBAR_IDX, HEADER_IDX, CONTENT_IDX, BREADCRUMB_IDX, VIEWPORT_IDX, PARAM_IDX, SPREADSHEET_IDX, PAGINATOR_IDX, get_next_visible_pane, Project, ProjectViewState, ParamDef};
-use clear_ui::engine::Vertex;
+use cce_ui::engine::Vertex;
#[derive(Debug, Clone, Copy)]
pub struct LocalPosition {
@@ -55,23 +55,23 @@ pub struct LocalPosition {
}
pub enum WindowEvent {
- MouseWheel { delta: clear_ui::widget::MouseScrollDelta, phase: TouchPhase },
+ MouseWheel { delta: cce_ui::widget::MouseScrollDelta, phase: TouchPhase },
PinchGesture { delta: f64 },
CursorMoved { position: LocalPosition },
- MouseInput { state: clear_ui::widget::ElementState, button: clear_ui::widget::MouseButton },
+ MouseInput { state: cce_ui::widget::ElementState, button: cce_ui::widget::MouseButton },
ModifiersChanged(ModifiersState),
- KeyboardInput { event: clear_ui::widget::KeyEvent },
+ KeyboardInput { event: cce_ui::widget::KeyEvent },
}
pub struct PressedKey {
- pub logical_key: clear_ui::widget::Key,
+ pub logical_key: cce_ui::widget::Key,
pub text: Option<String>,
pub first_pressed: std::time::Instant,
pub last_repeated: std::time::Instant,
}
-pub fn is_repeatable_key(key: &clear_ui::widget::Key) -> bool {
- use clear_ui::widget::{Key, NamedKey};
+pub fn is_repeatable_key(key: &cce_ui::widget::Key) -> bool {
+ use cce_ui::widget::{Key, NamedKey};
match key {
Key::Named(NamedKey::Backspace) |
Key::Named(NamedKey::Delete) |
@@ -113,7 +113,7 @@ pub struct AppState {
pub exit: bool,
pub redraw: bool,
pub pressed_key: Option<PressedKey>,
- pub inspector: Option<clear_ui::protocol::zclear_inspector_v1::ZclearInspectorV1>,
+ pub inspector: Option<cce_ui::protocol::zclear_inspector_v1::ZclearInspectorV1>,
pub pending_resize: Option<PendingResize>,
pub _sender: calloop::channel::Sender<CustomEvent>,
}
@@ -129,7 +129,7 @@ impl CompositorHandler for AppState {
_surface.set_buffer_scale(scale_factor);
if let Some(state) = &mut self.state {
state.scale = scale_factor as f64;
- clear_ui::scale::set_scale_factor(scale_factor as f32);
+ cce_ui::scale::set_scale_factor(scale_factor as f32);
let pw = (state.width as f64 * state.scale) as u32;
let ph = (state.height as f64 * state.scale) as u32;
state.resize(pw, ph);
@@ -354,15 +354,15 @@ impl PointerHandler for AppState {
}
PointerEventKind::Press { button, serial, .. } => {
let btn = match *button {
- 272 => clear_ui::widget::MouseButton::Left,
- 273 => clear_ui::widget::MouseButton::Right,
- 274 => clear_ui::widget::MouseButton::Middle,
+ 272 => cce_ui::widget::MouseButton::Left,
+ 273 => cce_ui::widget::MouseButton::Right,
+ 274 => cce_ui::widget::MouseButton::Middle,
_ => continue,
};
// eprintln!("DEBUG MOUSE PRESS: button={:?}, pos={:?}, local=({}, {})", btn, event.position, cx, cy);
if let Some(ref st) = self.state {
- if st.is_detached_network && btn == clear_ui::widget::MouseButton::Left {
+ if st.is_detached_network && btn == cce_ui::widget::MouseButton::Left {
let lx = event.position.0 as f32;
let ly = event.position.1 as f32;
let dx = lx - st.circular_network_layout.x;
@@ -433,24 +433,24 @@ impl PointerHandler for AppState {
}
let ev = WindowEvent::MouseInput {
- state: clear_ui::widget::ElementState::Pressed,
+ state: cce_ui::widget::ElementState::Pressed,
button: btn,
};
self.process_event(ev);
}
PointerEventKind::Release { button, .. } => {
let btn = match *button {
- 272 => clear_ui::widget::MouseButton::Left,
- 273 => clear_ui::widget::MouseButton::Right,
- 274 => clear_ui::widget::MouseButton::Middle,
+ 272 => cce_ui::widget::MouseButton::Left,
+ 273 => cce_ui::widget::MouseButton::Right,
+ 274 => cce_ui::widget::MouseButton::Middle,
_ => continue,
};
// eprintln!("DEBUG MOUSE RELEASE: button={:?}, pos={:?}, local=({}, {})", btn, event.position, cx, cy);
- if btn == clear_ui::widget::MouseButton::Left {
+ if btn == cce_ui::widget::MouseButton::Left {
self.pending_resize = None;
}
let ev = WindowEvent::MouseInput {
- state: clear_ui::widget::ElementState::Released,
+ state: cce_ui::widget::ElementState::Released,
button: btn,
};
self.process_event(ev);
@@ -460,7 +460,7 @@ impl PointerHandler for AppState {
let v_val = vertical.absolute as f32;
// eprintln!("DEBUG AXIS EVENT: horizontal={:?}, vertical={:?}, scale={}", horizontal, vertical, st.scale);
let ev = WindowEvent::MouseWheel {
- delta: clear_ui::widget::MouseScrollDelta::LineDelta(-h_val / 10.0, -v_val / 10.0),
+ delta: cce_ui::widget::MouseScrollDelta::LineDelta(-h_val / 10.0, -v_val / 10.0),
phase: TouchPhase::Moved,
};
self.process_event(ev);
@@ -512,7 +512,7 @@ impl KeyboardHandler for AppState {
_serial: u32,
event: smithay_client_toolkit::seat::keyboard::KeyEvent,
) {
- self.handle_key(event, clear_ui::widget::ElementState::Pressed);
+ self.handle_key(event, cce_ui::widget::ElementState::Pressed);
}
fn release_key(
@@ -523,7 +523,7 @@ impl KeyboardHandler for AppState {
_serial: u32,
event: smithay_client_toolkit::seat::keyboard::KeyEvent,
) {
- self.handle_key(event, clear_ui::widget::ElementState::Released);
+ self.handle_key(event, cce_ui::widget::ElementState::Released);
}
fn update_modifiers(
@@ -595,17 +595,17 @@ impl ProvidesRegistryState for AppState {
) {}
}
-impl wayland_client::Dispatch<clear_ui::protocol::zclear_inspector_v1::ZclearInspectorV1, ()> for AppState {
+impl wayland_client::Dispatch<cce_ui::protocol::zclear_inspector_v1::ZclearInspectorV1, ()> for AppState {
fn event(
state: &mut Self,
- _proxy: &clear_ui::protocol::zclear_inspector_v1::ZclearInspectorV1,
- event: clear_ui::protocol::zclear_inspector_v1::Event,
+ _proxy: &cce_ui::protocol::zclear_inspector_v1::ZclearInspectorV1,
+ event: cce_ui::protocol::zclear_inspector_v1::Event,
_data: &(),
_conn: &Connection,
_qh: &QueueHandle<Self>,
) {
match event {
- clear_ui::protocol::zclear_inspector_v1::Event::InspectedSurface { app_id, x, y, .. } => {
+ cce_ui::protocol::zclear_inspector_v1::Event::InspectedSurface { app_id, x, y, .. } => {
if let Some(ref mut st) = state.state {
let expected_id = if st.is_detached_network {
"circular-network-pane"
@@ -634,8 +634,8 @@ delegate_registry!(AppState);
delegate_output!(AppState);
impl AppState {
- fn handle_key(&mut self, event: smithay_client_toolkit::seat::keyboard::KeyEvent, state: clear_ui::widget::ElementState) {
- use clear_ui::widget::{Key, KeyEvent, NamedKey};
+ fn handle_key(&mut self, event: smithay_client_toolkit::seat::keyboard::KeyEvent, state: cce_ui::widget::ElementState) {
+ use cce_ui::widget::{Key, KeyEvent, NamedKey};
let logical_key = match event.keysym {
xkeysym::Keysym::Escape => Key::Named(NamedKey::Escape),
xkeysym::Keysym::Return => Key::Named(NamedKey::Enter),
@@ -678,16 +678,16 @@ impl AppState {
if let Some(st) = &mut self.state {
match event.keysym {
xkeysym::Keysym::Control_L | xkeysym::Keysym::Control_R => {
- st.modifiers.ctrl = state == clear_ui::widget::ElementState::Pressed;
+ st.modifiers.ctrl = state == cce_ui::widget::ElementState::Pressed;
}
xkeysym::Keysym::Alt_L | xkeysym::Keysym::Alt_R => {
- st.modifiers.alt = state == clear_ui::widget::ElementState::Pressed;
+ st.modifiers.alt = state == cce_ui::widget::ElementState::Pressed;
}
xkeysym::Keysym::Shift_L | xkeysym::Keysym::Shift_R => {
- st.modifiers.shift = state == clear_ui::widget::ElementState::Pressed;
+ st.modifiers.shift = state == cce_ui::widget::ElementState::Pressed;
}
xkeysym::Keysym::Super_L | xkeysym::Keysym::Super_R => {
- st.modifiers.logo = state == clear_ui::widget::ElementState::Pressed;
+ st.modifiers.logo = state == cce_ui::widget::ElementState::Pressed;
}
_ => {}
}
@@ -701,7 +701,7 @@ impl AppState {
shift: st.modifiers.shift,
};
- if state == clear_ui::widget::ElementState::Pressed {
+ if state == cce_ui::widget::ElementState::Pressed {
if is_repeatable_key(&custom_event.logical_key) {
self.pressed_key = Some(PressedKey {
logical_key: custom_event.logical_key.clone(),
@@ -712,7 +712,7 @@ impl AppState {
} else {
self.pressed_key = None;
}
- } else if state == clear_ui::widget::ElementState::Released {
+ } else if state == cce_ui::widget::ElementState::Released {
if let Some(ref pk) = self.pressed_key {
if pk.logical_key == custom_event.logical_key {
self.pressed_key = None;