mirror of
https://github.com/Astatin3/unshell.git
synced 2026-06-08 22:38:01 -06:00
Improve title bar
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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::*;
|
||||||
|
|||||||
Reference in New Issue
Block a user