Improve title bar

This commit is contained in:
Michael Mikovsky
2025-11-29 16:38:12 -07:00
parent c83e2f1527
commit f85a0c0295
8 changed files with 80 additions and 30 deletions
+6 -1
View File
@@ -1,7 +1,10 @@
use egui::Frame; use egui::Frame;
use egui_tiles::Tree; use egui_tiles::Tree;
use crate::app::{AppState, windows::WindowWrapper}; use crate::{
FORCE_REDRAW_DELAY,
app::{AppState, windows::WindowWrapper},
};
/// We derive Deserialize/Serialize so we can persist app state on shutdown. /// We derive Deserialize/Serialize so we can persist app state on shutdown.
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
@@ -83,5 +86,7 @@ impl eframe::App for TemplateApp {
.frame(Frame::central_panel(&ctx.style()).inner_margin(0)) .frame(Frame::central_panel(&ctx.style()).inner_margin(0))
.show(ctx, |ui| self.tree.ui(&mut self.state, ui)); .show(ctx, |ui| self.tree.ui(&mut self.state, ui));
} }
ctx.request_repaint_after(FORCE_REDRAW_DELAY);
} }
} }
+15 -2
View File
@@ -19,7 +19,7 @@ pub struct AppState {
impl AppState { impl AppState {
pub fn labels(&mut self, tree: &mut Tree<WindowWrapper>, ui: &mut egui::Ui) { pub fn labels(&mut self, tree: &mut Tree<WindowWrapper>, ui: &mut egui::Ui) {
for (i, (key, name)) in (vec![ for (_, (key, name)) in (vec![
(AppWindow::Flowchart, "Flowchart"), (AppWindow::Flowchart, "Flowchart"),
(AppWindow::Config, "Config"), (AppWindow::Config, "Config"),
]) ])
@@ -38,7 +38,7 @@ impl AppState {
// if self.open_windows.is_empty() // if self.open_windows.is_empty()
} else { } else {
let tid = tree.tiles.insert_pane(WindowWrapper { let tid = tree.tiles.insert_pane(WindowWrapper {
nr: i + 1, name: name.to_string(),
window: *key, window: *key,
}); });
@@ -78,4 +78,17 @@ impl AppWindow {
AppWindow::Config => state.config.update(&mut state.auth, ui), AppWindow::Config => state.config.update(&mut state.auth, ui),
} }
} }
fn render_title_buttons(&self, state: &mut AppState, ui: &mut egui::Ui) {
match self {
AppWindow::Flowchart => {
if ui.button("Arrange").clicked() {
state.flowchart.arrange();
}
}
_ => {
ui.label("");
}
}
}
} }
+36 -13
View File
@@ -1,14 +1,16 @@
use egui::Rect;
use crate::app::{AppState, AppWindow}; use crate::app::{AppState, AppWindow};
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
pub struct WindowWrapper { pub struct WindowWrapper {
pub nr: usize, pub name: String,
pub window: AppWindow, pub window: AppWindow,
} }
impl egui_tiles::Behavior<WindowWrapper> for AppState { impl egui_tiles::Behavior<WindowWrapper> for AppState {
fn tab_title_for_pane(&mut self, pane: &WindowWrapper) -> egui::WidgetText { fn tab_title_for_pane(&mut self, pane: &WindowWrapper) -> egui::WidgetText {
format!("Pane {}", pane.nr).into() format!("{}", pane.name).into()
} }
fn pane_ui( fn pane_ui(
@@ -19,28 +21,49 @@ impl egui_tiles::Behavior<WindowWrapper> for AppState {
) -> egui_tiles::UiResponse { ) -> egui_tiles::UiResponse {
let mut ret = egui_tiles::UiResponse::None; let mut ret = egui_tiles::UiResponse::None;
let mut rect = Rect::NOTHING;
ui.horizontal(|ui| { ui.horizontal(|ui| {
let titlebar = ui.interact( rect = ui.max_rect();
ui.max_rect(),
ui.id().with(&format!("Pane_{}_sense", pane.nr)), let bg_color = ui.style().visuals.extreme_bg_color;
ui.painter().rect_filled(rect, 0.0, bg_color);
ui.vertical_centered(|ui| {
ui.label(&pane.name);
});
});
let mut open_space = Rect::NOTHING;
#[allow(deprecated)]
ui.allocate_ui_at_rect(rect, |ui| {
ui.horizontal(|ui| {
pane.window.render_title_buttons(self, ui);
open_space = ui.available_rect_before_wrap();
})
});
let drag_sense = ui.interact(
open_space,
ui.id().with(&format!("Pane_{}_sense", pane.name)),
egui::Sense::drag(), egui::Sense::drag(),
); );
if titlebar.drag_started() { if drag_sense.drag_started() {
ret = egui_tiles::UiResponse::DragStarted; ret = egui_tiles::UiResponse::DragStarted;
} }
if titlebar.hovered() { if drag_sense.hovered() {
ui.ctx().set_cursor_icon(egui::CursorIcon::Grab); ui.ctx().set_cursor_icon(egui::CursorIcon::Grab);
} }
let color = egui::epaint::Hsva::new(0.103 * pane.nr as f32, 0.5, 0.5, 1.0);
ui.painter().rect_filled(ui.max_rect(), 0.0, color);
ui.label("Test");
});
pane.window.update(self, ui); pane.window.update(self, ui);
ret ret
} }
fn tab_bar_color(&self, visuals: &egui::Visuals) -> egui::Color32 {
visuals.panel_fill // same as the tab contents
}
} }
+2 -4
View File
@@ -1,8 +1,6 @@
use serde_json::json;
use std::{collections::HashMap, sync::Arc, time::Duration};
use chrono::Utc;
use egui::{Align2, Area, Frame, Order, Sense, UiKind, Vec2, mutex::Mutex}; use egui::{Align2, Area, Frame, Order, Sense, UiKind, Vec2, mutex::Mutex};
use serde_json::json;
use std::sync::Arc;
use wasm_bindgen::prelude::Closure; use wasm_bindgen::prelude::Closure;
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
+3 -1
View File
@@ -1,7 +1,9 @@
use crate::auth::Auth; use crate::auth::Auth;
#[derive(Default, serde::Deserialize, serde::Serialize)] #[derive(Default, serde::Deserialize, serde::Serialize)]
pub struct Config {} pub struct Config {
response_text: String,
}
impl Config { impl Config {
pub fn update(&mut self, auth: &mut Auth, ui: &mut egui::Ui) { pub fn update(&mut self, auth: &mut Auth, ui: &mut egui::Ui) {
+9 -6
View File
@@ -2,6 +2,8 @@ use egui::{Color32, Painter, Pos2, Rect, Scene, Shape, Ui};
use crate::flowchart::CONNECTION_STROKE; use crate::flowchart::CONNECTION_STROKE;
use crate::flowchart::GROUP_BORDER_MARGIN; use crate::flowchart::GROUP_BORDER_MARGIN;
use crate::flowchart::ITERATIONS;
use crate::flowchart::RESOLUTION;
use crate::flowchart::container::DraggableContainer; use crate::flowchart::container::DraggableContainer;
use crate::flowchart::group::convex_hull; use crate::flowchart::group::convex_hull;
use crate::flowchart::{BG_STROKE, TARGET_LINE_GAP}; use crate::flowchart::{BG_STROKE, TARGET_LINE_GAP};
@@ -34,12 +36,19 @@ impl Default for FlowChart {
}; };
this.arrange_circle(); this.arrange_circle();
this.arrange();
this this
} }
} }
impl FlowChart { impl FlowChart {
pub fn arrange(&mut self) {
for _ in 0..ITERATIONS {
self.force(RESOLUTION);
}
}
fn paint_bg(rect: &Rect, painter: &Painter) { fn paint_bg(rect: &Rect, painter: &Painter) {
let h_start = (rect.min.x / TARGET_LINE_GAP).round() as i32; let h_start = (rect.min.x / TARGET_LINE_GAP).round() as i32;
let h_end = ((rect.min.x + rect.width()) / TARGET_LINE_GAP).round() as i32 + 1; let h_end = ((rect.min.x + rect.width()) / TARGET_LINE_GAP).round() as i32 + 1;
@@ -93,12 +102,6 @@ impl FlowChart {
} }
pub fn paint(&mut self, ui: &mut Ui) { pub fn paint(&mut self, ui: &mut Ui) {
if ui.button("Arrange").clicked() {
for _ in 0..1_000 {
self.force(0.1);
}
}
let scene = Scene::new() let scene = Scene::new()
// .max_inner_size([350.0, 1000.0]) // .max_inner_size([350.0, 1000.0])
.zoom_range(0.1..=2.0); .zoom_range(0.1..=2.0);
+3
View File
@@ -6,6 +6,9 @@ mod group;
use egui::{Color32, Stroke}; use egui::{Color32, Stroke};
pub use flowchart::FlowChart; pub use flowchart::FlowChart;
const ITERATIONS: usize = 1_000;
const RESOLUTION: f32 = 0.6;
const TARGET_LINE_GAP: f32 = 80.; const TARGET_LINE_GAP: f32 = 80.;
const BG_STROKE: Stroke = Stroke { const BG_STROKE: Stroke = Stroke {
+3
View File
@@ -8,6 +8,9 @@ mod auth;
mod config; mod config;
mod flowchart; mod flowchart;
use std::time::Duration;
const FORCE_REDRAW_DELAY: Duration = Duration::from_millis(300);
// mod JsFunc { // mod JsFunc {
// use wasm_bindgen::JsValue; // use wasm_bindgen::JsValue;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;