Add SciFi

This commit is contained in:
Astatin3
2024-10-31 19:55:02 -06:00
parent 2e62807074
commit 0aa59fc94d
9 changed files with 510 additions and 269 deletions
+2 -5
View File
@@ -6,8 +6,5 @@ edition = "2021"
[dependencies]
eframe = "0.28"
egui = "0.28"
portable-pty = "0.8.1"
termwiz = "0.22.0"
vte = "0.13.0"
egui-terminal = { git = "https://github.com/Quinntyx/egui-terminal" }
ecolor = "0.29.1"
rand = "0.8.5"
serde = "1.0.214"
+3 -2
View File
@@ -5,8 +5,9 @@ Unfortunatly this is not the most secure desktop locker, as it involves using sw
```
# Add this to your sway config:
for_window [title="^raylock$"] sticky enable, floating enable, resize set 1920 px 1080 px, title_format "", border pixel none
for_window [title="^raylock$"] sticky enable, fullscreen
mode "lock" {
bindsym $mod+Shift+q exec true
bindsym XF86MonBrightnessUp exec brightnessctl s +5%
bindsym XF86MonBrightnessDown exec brightnessctl s 5%-
}
```
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
use crate::structs;
use egui::{Color32, Stroke};
use std::f32::consts::PI;
// pub const windows: PaneSplit =
// Pane::new(SplitHorisontal).new_hsplit(Pane::new(Temp1), Pane::new(Temp2));
pub const TEXT_COLOR: Color32 = Color32::from_rgb(255, 255, 255);
pub const BACKGROUND_2: Color32 = Color32::from_rgba_premultiplied(10, 10, 10, 230);
pub const LOGIN_CIRCLE_RADIUS: f32 = 50.;
pub const LOGIN_SUBCIRCLE_START_ANG: f32 = -PI / 4.;
pub const LOGIN_SUBCIRCLE_RADIUS: f32 = 4.;
pub const LOGIN_SUBCIRCLE_COLOR: Color32 = Color32::TRANSPARENT;
pub const LOGIN_SUBCIRCLE_STROKE: Stroke = Stroke {
width: 2.0,
color: Color32::from_rgb(255, 255, 255),
};
pub const LOGIN_CIRCLE_LINE_STROKE: Stroke = Stroke {
width: 2.0,
color: TEXT_COLOR,
};
pub const LOGIN_FAIL_COLOR: Color32 = Color32::from_rgb(184, 41, 11);
pub const LOGIN_FAIL_CIRCLE_STROKE: Stroke = Stroke {
width: 5.,
color: LOGIN_FAIL_COLOR,
};
pub const LOGIN_FAIL_COUNT_CIRCLE_RADIUS: f32 = 15.;
pub const LOGIN_FAIL_COUNT_CIRCLE_COLOR: Color32 = Color32::TRANSPARENT;
pub const LOGIN_FAIL_COUNT_CIRCLE_STROKE: Stroke = Stroke {
width: 2.,
color: LOGIN_FAIL_COLOR,
};
pub const DOTS_SPACING: f32 = 25.;
pub const DOTS_RAD: f32 = 0.7;
pub const DOTS_COLOR: Color32 = Color32::from_rgb(255, 255, 255);
// pub const DOTS_STROKE: Stroke = Stroke {0., DOTS_COLOR};
pub const CORNER_CUT: f32 = LOGIN_CIRCLE_RADIUS * 1.41421356237;
pub const PANE_GAP: f32 = 6.;
+7 -7
View File
@@ -1,5 +1,5 @@
use egui::Key;
use std::fs::{exists, File};
use std::fs::File;
use std::path::Path;
use std::process::Command;
use std::thread;
@@ -9,18 +9,18 @@ const LOCK_FILEPATH: &str = "/tmp/.raylock.lock";
pub fn sway_lock_input() {
thread::spawn(move || {
let _ = Command::new("swaymsg").args(["mode", "lock"]).spawn();
let _ = Command::new("swaymsg")
.args(["input", "type:touchpad", "events", "disabled"])
.spawn();
// let _ = Command::new("swaymsg")
// .args(["input", "type:touchpad", "events", "disabled"])
// .spawn();
});
}
pub fn sway_unlock_input() {
thread::spawn(move || {
let _ = Command::new("swaymsg").args(["mode", "default"]).spawn();
let _ = Command::new("swaymsg")
.args(["input", "type:touchpad", "events", "enabled"])
.spawn();
// let _ = Command::new("swaymsg")
// .args(["input", "type:touchpad", "events", "enabled"])
// .spawn();
});
}
+37 -33
View File
@@ -1,7 +1,6 @@
use eframe::{egui, App};
use egui::FontFamily;
use egui::Key;
use egui_terminal;
use input::is_locked;
use std::collections::BTreeMap;
use std::collections::HashMap;
@@ -9,6 +8,7 @@ use std::process::{Command, Stdio};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use structs::{PaneConfig, PaneRenderer, SplitDirection};
// use egui::epaint::text::{FontInsert, InsertFontFamily};
@@ -16,54 +16,55 @@ use eframe::CreationContext;
use egui::ecolor::Color32;
use egui::FontId;
use egui::Stroke;
use egui_terminal::prelude::*;
use egui_terminal::render::CursorType;
// use egui_terminal::prelude::*;
// use egui_terminal::render::CursorType;
use egui::ecolor::HexColor;
mod configs;
mod input;
mod splitter;
mod structs;
mod ui;
// Demonstrates how to add a font to the existing ones
fn add_font(ctx: &egui::Context) {
// Start with the default fonts (we will be adding to them rather than replacing them).
let mut fonts = egui::FontDefinitions::default();
// fn add_font(ctx: &egui::Context) {
// // Start with the default fonts (we will be adding to them rather than replacing them).
// let mut fonts = egui::FontDefinitions::default();
// Install my own font (maybe supporting non-latin characters).
// .ttf and .otf files supported.
fonts.font_data.insert(
"my_font".to_owned(),
egui::FontData::from_static(include_bytes!(
"/home/astatin3/.fonts/UbuntuMono/UbuntuMonoNerdFontMono-Regular.ttf"
)),
);
// // Install my own font (maybe supporting non-latin characters).
// // .ttf and .otf files supported.
// fonts.font_data.insert(
// "my_font".to_owned(),
// egui::FontData::from_static(include_bytes!(
// "/home/astatin3/.fonts/UbuntuMono/UbuntuMonoNerdFontMono-Regular.ttf"
// )),
// );
// Put my font first (highest priority) for proportional text:
// fonts
// .families
// .entry(egui::FontFamily::Proportional)
// .or_default()
// .insert(0, "my_font".to_owned());
// // Put my font first (highest priority) for proportional text:
// // fonts
// // .families
// // .entry(egui::FontFamily::Proportional)
// // .or_default()
// // .insert(0, "my_font".to_owned());
// Put my font as last fallback for monospace:
fonts
.families
.entry(egui::FontFamily::Monospace)
.or_default()
.push("my_font".to_owned());
// // Put my font as last fallback for monospace:
// fonts
// .families
// .entry(egui::FontFamily::Monospace)
// .or_default()
// .push("my_font".to_owned());
// Tell egui to use these fonts:
ctx.set_fonts(fonts);
}
// // Tell egui to use these fonts:
// ctx.set_fonts(fonts);
// }
use splitter::Splitter;
#[derive(Default)]
struct ExampleApp {
auth_state: Arc<Mutex<structs::AuthState>>,
terminals: HashMap<String, TermHandler>,
// terminals: HashMap<String, TermHandler>,
}
impl ExampleApp {
@@ -101,6 +102,9 @@ impl eframe::App for ExampleApp {
let mut state = self.auth_state.lock().unwrap();
//ctx.set_pixels_per_point(1.5);
let config = ui::winconfig();
let pane_renderer = PaneRenderer::new(config);
if ctx.input(|i| i.events.len() > 0) {
ctx.input(|i| {
@@ -177,7 +181,7 @@ impl eframe::App for ExampleApp {
// },
// );
ui::update_password_viewer(state, ctx, _frame, ui);
ui::update_password_viewer(state, ctx, _frame, ui, pane_renderer);
});
}
}
@@ -228,7 +232,7 @@ fn main() -> eframe::Result<()> {
thread::sleep(Duration::from_millis(100));
});
let mut map = HashMap::new();
// let mut map = HashMap::new();
// map.insert(String::from("0"), TermHandler::new_from_str("btop"));
// map.insert(String::from("1h-0"), TermHandler::new_from_str("nvitop"));
// map.insert(String::from("1h-1"), TermHandler::new_from_str("neofetch"));
@@ -247,7 +251,7 @@ fn main() -> eframe::Result<()> {
Box::new(|_| {
Ok(Box::<ExampleApp>::new(ExampleApp {
auth_state: state,
terminals: map,
// terminals: map,
}))
}),
)
-190
View File
@@ -1,190 +0,0 @@
/// https://gist.github.com/mkalte666/f9a982be0ac0276080d3434ab9ea4655
use std::hash::Hash;
use egui::{CursorIcon, Id, Layout, Pos2, Rect, Rounding, Sense, Ui, Vec2};
/// An axis that a Splitter can use
#[derive(Copy, Clone, Debug)]
pub enum SplitterAxis {
Horizontal,
Vertical,
}
/// The internal data used by a splitter. Stored into memory
#[derive(Debug, Clone)]
struct SplitterData {
axis: SplitterAxis,
pos: f32,
min_size: f32,
}
/// Splits a ui in half, using a draggable separator in the middle.
///
pub struct Splitter {
id: Id,
data: SplitterData,
}
impl Splitter {
/// Create a new Splitter
pub fn new(id_source: impl Hash, axis: SplitterAxis) -> Self {
Self {
id: Id::new(id_source),
data: SplitterData {
axis,
pos: 0.5,
min_size: 0.0,
},
}
}
/// Sets the minimum allowed size for the area
pub fn min_size(mut self, points: f32) -> Self {
self.data.min_size = points;
self
}
/// Thes the default position of the splitter separator. Usually it sits in the center, this moves it around.
pub fn default_pos(mut self, pos: f32) -> Self {
self.data.pos = pos;
self
}
/// Show the splitter and fill it with content.
///
/// ```
/// Splitter::new("some_plot_split", SplitterAxis::Vertical)
/// .min_size(250.0)
/// .default_pos(2.0 / 3.0)
/// .show(ui, |ui_a, ui_b| {
/// Plot::new("plot_a")
/// .legend(Legend::default())
/// .x_axis_formatter(log_formatter)
/// .y_axis_formatter(log_formatter)
/// .x_axis_label("X Axis")
/// .y_axis_label("A Axis")
/// .link_axis("axis_link", true, false)
/// .link_cursor("cursor_link", true, false)
/// .show(ui_a, |plot_ui| {
/// for line in plot_a_lines {
/// plot_ui.line(line);
/// }
/// });
///
/// Plot::new("plot_b")
/// .legend(Legend::default())
/// .x_axis_formatter(log_formatter)
/// .x_axis_label("X Axis")
/// .y_axis_label("Y Axis")
/// .link_axis("axis_link", true, false)
/// .link_cursor("cursor_link", true, false)
/// .show(ui_b, |plot_ui| {
/// for line in plot_b_lines {
/// plot_ui.line(line);
/// }
/// });
/// });
/// ```
pub fn show(mut self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui, &mut Ui)) {
let mut data = if let Some(d) = ui.memory(|mem| mem.data.get_temp(self.id)) {
d
} else {
self.data.clone()
};
let sep_size = 10.0;
let sep_stroke = 2.0;
let whole_area = ui.available_size();
let split_axis_size = match data.axis {
SplitterAxis::Horizontal => whole_area.x,
SplitterAxis::Vertical => whole_area.y,
};
let split_a_size = ((split_axis_size - sep_size) * data.pos);
let split_b_size = split_axis_size - sep_size - split_a_size;
let child_size_a = match data.axis {
SplitterAxis::Horizontal => Vec2::new(split_a_size, whole_area.y),
SplitterAxis::Vertical => Vec2::new(whole_area.x, split_a_size),
};
let child_size_b = match data.axis {
SplitterAxis::Horizontal => Vec2::new(split_b_size, whole_area.y),
SplitterAxis::Vertical => Vec2::new(whole_area.x, split_b_size),
};
let child_rect_a = Rect::from_min_size(ui.next_widget_position(), child_size_a);
let mut ui_a = ui.child_ui(child_rect_a, Layout::default(), None);
let sep_rect = match data.axis {
SplitterAxis::Horizontal => Rect::from_min_size(
Pos2::new(child_rect_a.max.x, child_rect_a.min.y),
Vec2::new(sep_size, whole_area.y),
),
SplitterAxis::Vertical => Rect::from_min_size(
Pos2::new(child_rect_a.min.x, child_rect_a.max.y),
Vec2::new(whole_area.x, sep_size),
),
};
let resp = ui.allocate_rect(sep_rect, Sense::hover().union(Sense::click_and_drag()));
let sep_draw_rect = match data.axis {
SplitterAxis::Horizontal => Rect::from_min_size(
Pos2::new(
sep_rect.min.x + sep_size / 2.0 - sep_stroke / 2.0,
sep_rect.min.y,
),
Vec2::new(sep_stroke, sep_rect.height()),
),
SplitterAxis::Vertical => Rect::from_min_size(
Pos2::new(
sep_rect.min.x,
sep_rect.min.y + sep_size / 2.0 - sep_stroke / 2.0,
),
Vec2::new(sep_rect.width(), sep_stroke),
),
};
ui.painter().rect_filled(
sep_draw_rect,
Rounding::ZERO,
ui.style().visuals.noninteractive().bg_stroke.color,
);
let child_rect_b = match data.axis {
SplitterAxis::Horizontal => {
Rect::from_min_size(Pos2::new(sep_rect.max.x, sep_rect.min.y), child_size_b)
}
SplitterAxis::Vertical => {
Rect::from_min_size(Pos2::new(sep_rect.min.x, sep_rect.max.y), child_size_b)
}
};
let mut ui_b = ui.child_ui(child_rect_b, Layout::default(), None);
add_contents(&mut ui_a, &mut ui_b);
if resp.hovered() {
match data.axis {
SplitterAxis::Horizontal => ui.ctx().set_cursor_icon(CursorIcon::ResizeVertical),
SplitterAxis::Vertical => ui.ctx().set_cursor_icon(CursorIcon::ResizeHorizontal),
}
}
if resp.dragged() {
let delta_pos = match data.axis {
SplitterAxis::Horizontal => resp.drag_delta().x / whole_area.x,
SplitterAxis::Vertical => resp.drag_delta().y / whole_area.y,
};
data.pos += delta_pos;
}
// clip pos
let min_pos = (data.min_size / split_axis_size).min(1.0);
let max_pos = (1.0 - min_pos).max(0.0);
data.pos = data.pos.max(min_pos).min(max_pos);
ui.memory_mut(|mem| {
mem.data.insert_temp(self.id, data);
})
}
}
+239
View File
@@ -1,6 +1,245 @@
use egui::{Color32, Painter, Pos2, Rect, Vec2};
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
use std::sync::MutexGuard;
// use serde::
#[derive(Default)]
pub struct AuthState {
pub password: String,
pub to_be_submitted: bool,
pub failed_attempts: u16,
}
// pub enum windowTypes {
// Temp1,
// Temp2,
// SplitVertical,
// SplitHorisontal,
// }
// pub struct Pane {
// pub wintype: windowTypes,
// }
// pub struct PaneSplit {
// pub wintype: windowTypes,
// pub sub_a: Pane,
// pub sub_b: Pane,
// }
// impl Pane {
// pub const fn new(wintype: windowTypes) -> Self {
// Self { wintype: wintype }
// }
// pub const fn new_hsplit(wintype: windowTypes, left: Pane, right: Pane) -> PaneSplit {
// PaneSplit {
// wintype: wintype,
// sub_a: left,
// sub_b: right,
// }
// }
// pub const fn new_rsplit(wintype: windowTypes, wintop: Pane, bottom: Pane) -> PaneSplit {
// PaneSplit {
// wintype: wintype,
// sub_a: top,
// sub_b: bottom,
// }
// }
// }
// pub struct cur_context {
// pub state: AuthState,
// pub ctx: egui::Context,
// pub frame: eframe::Frame,
// pub ui: egui::Ui,
// pub center: egui::Pos2,
// pub painter: egui::Painter,
// }
// #[derive(Debug)]
// type PaintCallback = dyn Fn() -> String;
// impl fmt::Debug for PaintCallback {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// write!("Test")
// }
// }
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum SplitDirection {
Horizontal,
Vertical,
}
// #[derive(Sized)]
pub struct PaneConfig {
pub id: String,
pub split: Option<(SplitDirection, f32)>,
pub children: Option<Vec<PaneConfig>>,
pub color: Option<Color32>, // Store color in config for consistency
pub callback: Option<Box<dyn Fn(&Painter, Rect)>>,
}
// #[derive(Debug)]
pub struct PaneRenderer {
config: PaneConfig,
}
impl PaneConfig {
pub fn new(id: impl Into<String>) -> Self {
Self {
id: id.into(),
split: None,
children: None,
color: None,
callback: None,
}
}
pub fn with_split(mut self, direction: SplitDirection, ratio: f32) -> Self {
self.split = Some((direction, ratio.clamp(0.0, 1.0)));
self
}
pub fn with_children(mut self, children: Vec<PaneConfig>) -> Self {
self.children = Some(children);
self
}
pub fn with_callback(mut self, callback: impl Fn(&Painter, Rect) + 'static) -> Self {
self.callback = Some(Box::new(callback));
self
}
pub fn with_random_color(mut self) -> Self {
let mut rng = rand::thread_rng();
self.color = Some(Color32::from_rgb(
rng.gen_range(0..255),
rng.gen_range(0..255),
rng.gen_range(0..255),
));
self
}
}
impl PaneRenderer {
pub fn new(config: PaneConfig) -> Self {
Self { config }
}
pub fn render(&self, painter: &Painter, rect: Rect) {
self.render_pane(painter, rect, &self.config);
}
fn render_pane(&self, painter: &Painter, rect: Rect, pane: &PaneConfig) {
if let Some((direction, ratio)) = &pane.split {
if let Some(children) = &pane.children {
if children.len() >= 2 {
let (first_rect, second_rect) = self.split_rect(rect, *direction, *ratio);
// Render first child
self.render_pane(painter, first_rect, &children[0]);
// Render second child
self.render_pane(painter, second_rect, &children[1]);
// Render any additional children (will be stacked after the split)
let remaining_rect = match direction {
SplitDirection::Horizontal => Rect::from_min_size(
Pos2::new(second_rect.max.x, rect.min.y),
Vec2::new(rect.max.x - second_rect.max.x, rect.height()),
),
SplitDirection::Vertical => Rect::from_min_size(
Pos2::new(rect.min.x, second_rect.max.y),
Vec2::new(rect.width(), rect.max.y - second_rect.max.y),
),
};
for child in children.iter().skip(2) {
self.render_pane(painter, remaining_rect, child);
}
// Draw split line
let split_line_color = Color32::from_gray(128);
match direction {
SplitDirection::Horizontal => {
let x = first_rect.max.x;
// painter.line_segment(
// [Pos2::new(x, rect.min.y), Pos2::new(x, rect.max.y)],
// (1.0, split_line_color),
// );
}
SplitDirection::Vertical => {
let y = first_rect.max.y;
// painter.line_segment(
// [Pos2::new(rect.min.x, y), Pos2::new(rect.max.x, y)],
// (1.0, split_line_color),
// );
}
}
}
}
} else {
if !pane.callback.is_none() {
pane.callback.as_ref().unwrap()(painter, rect);
return;
}
}
}
fn split_rect(&self, rect: Rect, direction: SplitDirection, ratio: f32) -> (Rect, Rect) {
match direction {
SplitDirection::Horizontal => {
let split_x = rect.min.x + rect.width() * ratio;
let first = Rect::from_min_max(rect.min, Pos2::new(split_x, rect.max.y));
let second = Rect::from_min_max(Pos2::new(split_x, rect.min.y), rect.max);
(first, second)
}
SplitDirection::Vertical => {
let split_y = rect.min.y + rect.height() * ratio;
let first = Rect::from_min_max(rect.min, Pos2::new(rect.max.x, split_y));
let second = Rect::from_min_max(Pos2::new(rect.min.x, split_y), rect.max);
(first, second)
}
}
}
}
// Example usage in an app
pub fn example_usage(ctx: &egui::Context) {
// Create a complex pane configuration
let config = PaneConfig::new("root")
.with_split(SplitDirection::Horizontal, 0.3)
.with_children(vec![
PaneConfig::new("left").with_random_color(),
PaneConfig::new("right")
.with_split(SplitDirection::Vertical, 0.6)
.with_children(vec![
PaneConfig::new("right_top").with_random_color(),
PaneConfig::new("right_bottom")
.with_split(SplitDirection::Horizontal, 0.5)
.with_children(vec![
PaneConfig::new("bottom_left").with_random_color(),
PaneConfig::new("bottom_right").with_random_color(),
]),
]),
]);
let pane_renderer = PaneRenderer::new(config);
egui::CentralPanel::default().show(ctx, |ui| {
// Get the painter and available rect from the UI
let painter = ui.painter();
let rect = ui.available_rect_before_wrap();
// Render the panes
pane_renderer.render(&painter, rect);
});
}
+180 -32
View File
@@ -1,38 +1,19 @@
use crate::configs::*;
use crate::structs;
use crate::structs::PaneRenderer;
// use crate::structs::cur_context;
// use crate::structs::windowTypes;
use eframe::egui;
use egui::Color32;
use egui::Pos2;
use egui::Stroke;
use egui::Shape;
use std::f32::consts::PI;
use structs::{PaneConfig, SplitDirection};
use std::ops::Deref;
use std::sync::MutexGuard;
const TEXT_COLOR: Color32 = Color32::from_rgb(255, 255, 255);
const LOGIN_CIRCLE_RADIUS: f32 = 50.;
const LOGIN_SUBCIRCLE_START_ANG: f32 = -PI / 4.;
const LOGIN_SUBCIRCLE_RADIUS: f32 = 4.;
const LOGIN_SUBCIRCLE_COLOR: Color32 = Color32::TRANSPARENT;
const LOGIN_SUBCIRCLE_STROKE: Stroke = Stroke {
width: 2.0,
color: Color32::from_rgb(255, 255, 255),
};
const LOGIN_CIRCLE_LINE_STROKE: Stroke = Stroke {
width: 2.0,
color: TEXT_COLOR,
};
const LOGIN_FAIL_COLOR: Color32 = Color32::from_rgb(184, 41, 11);
const LOGIN_FAIL_CIRCLE_STROKE: Stroke = Stroke {
width: 5.,
color: LOGIN_FAIL_COLOR,
};
const LOGIN_FAIL_COUNT_CIRCLE_RADIUS: f32 = 15.;
const LOGIN_FAIL_COUNT_CIRCLE_COLOR: Color32 = Color32::TRANSPARENT;
const LOGIN_FAIL_COUNT_CIRCLE_STROKE: Stroke = Stroke {
width: 2.,
color: LOGIN_FAIL_COLOR,
};
fn rot_circle(i: i16, center: Pos2, rad: f32, offset_ang: f32, ang_per_num: f32) -> Pos2 {
center
+ (egui::Vec2 {
@@ -41,22 +22,170 @@ fn rot_circle(i: i16, center: Pos2, rad: f32, offset_ang: f32, ang_per_num: f32)
})
}
pub fn background_render(painter: &egui::Painter, rect: egui::Rect) {
let left = rect.left() + PANE_GAP;
let right = rect.right() - PANE_GAP;
let bottom = rect.bottom() - PANE_GAP;
let top = rect.top() + PANE_GAP;
let x1 = left + CORNER_CUT - PANE_GAP;
let x2 = right - CORNER_CUT + PANE_GAP;
let y1 = top + CORNER_CUT - PANE_GAP;
let y2 = bottom - CORNER_CUT + PANE_GAP;
let points = [
egui::Pos2 { x: x1, y: top },
egui::Pos2 { x: x2, y: top },
egui::Pos2 { x: right, y: y1 },
egui::Pos2 { x: right, y: y2 },
egui::Pos2 { x: x2, y: bottom },
egui::Pos2 { x: x1, y: bottom },
egui::Pos2 { x: left, y: y2 },
egui::Pos2 { x: left, y: y1 },
];
let filled_polygon = Shape::convex_polygon(
points.to_vec(),
BACKGROUND_2,
egui::Stroke::new(0.5, TEXT_COLOR),
);
painter.add(filled_polygon);
// painter.rect_filled(rect, 0.0, Color32::RED);
// painter.rect_stroke(rect, 0.0, (1.0, Color32::BLACK));
}
// fn draw_polygon(ui: &mut egui::Ui, points: &[Pos2], fill_color: egui::Color32, stroke: ) {
// if points.len() < 3 {
// return; // Need at least 3 points for a polygon
// }
// // Create the filled polygon
// let filled_polygon = Shape::convex_polygon(
// points.to_vec(),
// fill_color,
// Stroke::new(0.0, fill_color), // No stroke for fill
// );
// // Create the outline
// let outline = Shape::line(
// points.iter().chain(std::iter::once(&points[0])).cloned().collect(),
// Stroke::new(stroke_width, outline_color),
// );
// // Get the painter and draw both shapes
// let painter = ui.painter();
// painter.add(filled_polygon);
// painter.add(outline);
// }
pub fn winconfig() -> PaneConfig {
PaneConfig::new("root")
.with_split(SplitDirection::Horizontal, 0.5)
.with_callback(|painter: &egui::Painter, rect: egui::Rect| background_render(painter, rect))
.with_children(vec![
PaneConfig::new("left")
.with_split(SplitDirection::Vertical, 0.5)
.with_children(vec![
PaneConfig::new("left_top").with_callback(
|painter: &egui::Painter, rect: egui::Rect| {
background_render(painter, rect)
},
),
PaneConfig::new("left_bottom")
// .with_split(SplitDirection::Horizontal, 0.5)
.with_callback(|painter: &egui::Painter, rect: egui::Rect| {
background_render(painter, rect)
}),
]),
PaneConfig::new("right")
.with_split(SplitDirection::Vertical, 0.5)
.with_callback(|painter: &egui::Painter, rect: egui::Rect| {
background_render(painter, rect)
})
.with_children(vec![
PaneConfig::new("right_top")
.with_split(SplitDirection::Horizontal, 0.5)
.with_children(vec![
PaneConfig::new("right_top_1").with_callback(
|painter: &egui::Painter, rect: egui::Rect| {
background_render(painter, rect)
},
),
PaneConfig::new("right_top_2").with_callback(
|painter: &egui::Painter, rect: egui::Rect| {
background_render(painter, rect)
},
),
]),
PaneConfig::new("right_bottom").with_callback(
|painter: &egui::Painter, rect: egui::Rect| {
background_render(painter, rect)
},
),
]),
])
}
pub fn update_password_viewer(
wstate: MutexGuard<'_, structs::AuthState>,
ctx: &egui::Context,
frame: &mut eframe::Frame,
ui: &mut egui::Ui,
winconfig: PaneRenderer,
) {
let mut state = wstate;
let rect = ui.clip_rect();
let center = Pos2 {
let rect: egui::Rect = ui.available_rect_before_wrap();
// let ctx: cur_context = cur_context {
let state: &structs::AuthState = wstate.deref();
let center: Pos2 = Pos2 {
x: rect.width() / 2.,
y: rect.height() / 2.,
};
let painter: &egui::Painter = ui.painter();
let painter = ui.painter();
paint_windows(
painter,
rect.width() as f32,
rect.height() as f32,
0.,
0.,
// windows,
);
// Login Circle
dots(painter, ui.clip_rect());
winconfig.render(painter, rect);
paint_password_circle(state, ctx, frame, ui, center, painter);
}
fn dots(painter: &egui::Painter, win_rect: egui::Rect) {
let dots_x = win_rect.right() / DOTS_SPACING;
let dots_y = win_rect.bottom() / DOTS_SPACING;
for x in (-dots_x as i32 / 2)..((dots_x as i32 / 2) + 1) {
for y in (-dots_y as i32 / 2)..((dots_y as i32 / 2) + 1) {
painter.circle(
Pos2 {
x: win_rect.right() / 2. + (x as f32 * DOTS_SPACING),
y: win_rect.bottom() / 2. + (y as f32 * DOTS_SPACING),
},
DOTS_RAD,
DOTS_COLOR,
egui::Stroke::NONE,
);
}
}
}
fn paint_password_circle(
state: &structs::AuthState,
ctx: &egui::Context,
frame: &eframe::Frame,
ui: &egui::Ui,
center: egui::Pos2,
painter: &egui::Painter,
) {
let len = state.password.len();
if state.failed_attempts > 0 {
painter.circle(
@@ -131,3 +260,22 @@ pub fn update_password_viewer(
}
}
}
fn paint_windows(
painter: &egui::Painter,
width: f32,
height: f32,
x: f32,
y: f32,
// pane: structs::PaneSplit,
) {
// match pane.wintype {
// windowTypes::SplitHorisontal => {
// paint_windows(painter, width, height / 2., x, y, pane.sub_a);
// paint_windows(painter, width, height / 2., x, y + height / 2., pane.sub_b);
// }
// }
}
fn paint_window(painter: &egui::Painter, width: f32, height: f32, x: f32, y: f32) {}