mirror of
https://github.com/Astatin3/raylock.git
synced 2026-06-09 00:28:00 -06:00
Add SciFi
This commit is contained in:
+2
-5
@@ -6,8 +6,5 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
eframe = "0.28"
|
eframe = "0.28"
|
||||||
egui = "0.28"
|
egui = "0.28"
|
||||||
portable-pty = "0.8.1"
|
rand = "0.8.5"
|
||||||
termwiz = "0.22.0"
|
serde = "1.0.214"
|
||||||
vte = "0.13.0"
|
|
||||||
egui-terminal = { git = "https://github.com/Quinntyx/egui-terminal" }
|
|
||||||
ecolor = "0.29.1"
|
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ Unfortunatly this is not the most secure desktop locker, as it involves using sw
|
|||||||
|
|
||||||
```
|
```
|
||||||
# Add this to your sway config:
|
# 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" {
|
mode "lock" {
|
||||||
bindsym $mod+Shift+q exec true
|
bindsym XF86MonBrightnessUp exec brightnessctl s +5%
|
||||||
|
bindsym XF86MonBrightnessDown exec brightnessctl s 5%-
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
Binary file not shown.
@@ -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
@@ -1,5 +1,5 @@
|
|||||||
use egui::Key;
|
use egui::Key;
|
||||||
use std::fs::{exists, File};
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
@@ -9,18 +9,18 @@ const LOCK_FILEPATH: &str = "/tmp/.raylock.lock";
|
|||||||
pub fn sway_lock_input() {
|
pub fn sway_lock_input() {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let _ = Command::new("swaymsg").args(["mode", "lock"]).spawn();
|
let _ = Command::new("swaymsg").args(["mode", "lock"]).spawn();
|
||||||
let _ = Command::new("swaymsg")
|
// let _ = Command::new("swaymsg")
|
||||||
.args(["input", "type:touchpad", "events", "disabled"])
|
// .args(["input", "type:touchpad", "events", "disabled"])
|
||||||
.spawn();
|
// .spawn();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sway_unlock_input() {
|
pub fn sway_unlock_input() {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let _ = Command::new("swaymsg").args(["mode", "default"]).spawn();
|
let _ = Command::new("swaymsg").args(["mode", "default"]).spawn();
|
||||||
let _ = Command::new("swaymsg")
|
// let _ = Command::new("swaymsg")
|
||||||
.args(["input", "type:touchpad", "events", "enabled"])
|
// .args(["input", "type:touchpad", "events", "enabled"])
|
||||||
.spawn();
|
// .spawn();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+37
-33
@@ -1,7 +1,6 @@
|
|||||||
use eframe::{egui, App};
|
use eframe::{egui, App};
|
||||||
use egui::FontFamily;
|
use egui::FontFamily;
|
||||||
use egui::Key;
|
use egui::Key;
|
||||||
use egui_terminal;
|
|
||||||
use input::is_locked;
|
use input::is_locked;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -9,6 +8,7 @@ use std::process::{Command, Stdio};
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use structs::{PaneConfig, PaneRenderer, SplitDirection};
|
||||||
|
|
||||||
// use egui::epaint::text::{FontInsert, InsertFontFamily};
|
// use egui::epaint::text::{FontInsert, InsertFontFamily};
|
||||||
|
|
||||||
@@ -16,54 +16,55 @@ use eframe::CreationContext;
|
|||||||
use egui::ecolor::Color32;
|
use egui::ecolor::Color32;
|
||||||
use egui::FontId;
|
use egui::FontId;
|
||||||
use egui::Stroke;
|
use egui::Stroke;
|
||||||
use egui_terminal::prelude::*;
|
// use egui_terminal::prelude::*;
|
||||||
use egui_terminal::render::CursorType;
|
// use egui_terminal::render::CursorType;
|
||||||
|
|
||||||
use egui::ecolor::HexColor;
|
use egui::ecolor::HexColor;
|
||||||
|
|
||||||
|
mod configs;
|
||||||
mod input;
|
mod input;
|
||||||
mod splitter;
|
mod splitter;
|
||||||
mod structs;
|
mod structs;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
// Demonstrates how to add a font to the existing ones
|
// Demonstrates how to add a font to the existing ones
|
||||||
fn add_font(ctx: &egui::Context) {
|
// fn add_font(ctx: &egui::Context) {
|
||||||
// Start with the default fonts (we will be adding to them rather than replacing them).
|
// // Start with the default fonts (we will be adding to them rather than replacing them).
|
||||||
let mut fonts = egui::FontDefinitions::default();
|
// let mut fonts = egui::FontDefinitions::default();
|
||||||
|
|
||||||
// Install my own font (maybe supporting non-latin characters).
|
// // Install my own font (maybe supporting non-latin characters).
|
||||||
// .ttf and .otf files supported.
|
// // .ttf and .otf files supported.
|
||||||
fonts.font_data.insert(
|
// fonts.font_data.insert(
|
||||||
"my_font".to_owned(),
|
// "my_font".to_owned(),
|
||||||
egui::FontData::from_static(include_bytes!(
|
// egui::FontData::from_static(include_bytes!(
|
||||||
"/home/astatin3/.fonts/UbuntuMono/UbuntuMonoNerdFontMono-Regular.ttf"
|
// "/home/astatin3/.fonts/UbuntuMono/UbuntuMonoNerdFontMono-Regular.ttf"
|
||||||
)),
|
// )),
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Put my font first (highest priority) for proportional text:
|
// // Put my font first (highest priority) for proportional text:
|
||||||
// fonts
|
// // fonts
|
||||||
// .families
|
// // .families
|
||||||
// .entry(egui::FontFamily::Proportional)
|
// // .entry(egui::FontFamily::Proportional)
|
||||||
// .or_default()
|
// // .or_default()
|
||||||
// .insert(0, "my_font".to_owned());
|
// // .insert(0, "my_font".to_owned());
|
||||||
|
|
||||||
// Put my font as last fallback for monospace:
|
// // Put my font as last fallback for monospace:
|
||||||
fonts
|
// fonts
|
||||||
.families
|
// .families
|
||||||
.entry(egui::FontFamily::Monospace)
|
// .entry(egui::FontFamily::Monospace)
|
||||||
.or_default()
|
// .or_default()
|
||||||
.push("my_font".to_owned());
|
// .push("my_font".to_owned());
|
||||||
|
|
||||||
// Tell egui to use these fonts:
|
// // Tell egui to use these fonts:
|
||||||
ctx.set_fonts(fonts);
|
// ctx.set_fonts(fonts);
|
||||||
}
|
// }
|
||||||
|
|
||||||
use splitter::Splitter;
|
use splitter::Splitter;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ExampleApp {
|
struct ExampleApp {
|
||||||
auth_state: Arc<Mutex<structs::AuthState>>,
|
auth_state: Arc<Mutex<structs::AuthState>>,
|
||||||
terminals: HashMap<String, TermHandler>,
|
// terminals: HashMap<String, TermHandler>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExampleApp {
|
impl ExampleApp {
|
||||||
@@ -101,6 +102,9 @@ impl eframe::App for ExampleApp {
|
|||||||
|
|
||||||
let mut state = self.auth_state.lock().unwrap();
|
let mut state = self.auth_state.lock().unwrap();
|
||||||
//ctx.set_pixels_per_point(1.5);
|
//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) {
|
if ctx.input(|i| i.events.len() > 0) {
|
||||||
ctx.input(|i| {
|
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));
|
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("0"), TermHandler::new_from_str("btop"));
|
||||||
// map.insert(String::from("1h-0"), TermHandler::new_from_str("nvitop"));
|
// map.insert(String::from("1h-0"), TermHandler::new_from_str("nvitop"));
|
||||||
// map.insert(String::from("1h-1"), TermHandler::new_from_str("neofetch"));
|
// map.insert(String::from("1h-1"), TermHandler::new_from_str("neofetch"));
|
||||||
@@ -247,7 +251,7 @@ fn main() -> eframe::Result<()> {
|
|||||||
Box::new(|_| {
|
Box::new(|_| {
|
||||||
Ok(Box::<ExampleApp>::new(ExampleApp {
|
Ok(Box::<ExampleApp>::new(ExampleApp {
|
||||||
auth_state: state,
|
auth_state: state,
|
||||||
terminals: map,
|
// terminals: map,
|
||||||
}))
|
}))
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
-190
@@ -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
@@ -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)]
|
#[derive(Default)]
|
||||||
pub struct AuthState {
|
pub struct AuthState {
|
||||||
pub password: String,
|
pub password: String,
|
||||||
pub to_be_submitted: bool,
|
pub to_be_submitted: bool,
|
||||||
pub failed_attempts: u16,
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,38 +1,19 @@
|
|||||||
|
use crate::configs::*;
|
||||||
use crate::structs;
|
use crate::structs;
|
||||||
|
use crate::structs::PaneRenderer;
|
||||||
|
// use crate::structs::cur_context;
|
||||||
|
// use crate::structs::windowTypes;
|
||||||
|
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui::Color32;
|
use egui::Color32;
|
||||||
use egui::Pos2;
|
use egui::Pos2;
|
||||||
use egui::Stroke;
|
use egui::Shape;
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
use structs::{PaneConfig, SplitDirection};
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
use std::sync::MutexGuard;
|
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 {
|
fn rot_circle(i: i16, center: Pos2, rad: f32, offset_ang: f32, ang_per_num: f32) -> Pos2 {
|
||||||
center
|
center
|
||||||
+ (egui::Vec2 {
|
+ (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(
|
pub fn update_password_viewer(
|
||||||
wstate: MutexGuard<'_, structs::AuthState>,
|
wstate: MutexGuard<'_, structs::AuthState>,
|
||||||
ctx: &egui::Context,
|
ctx: &egui::Context,
|
||||||
frame: &mut eframe::Frame,
|
frame: &mut eframe::Frame,
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
|
winconfig: PaneRenderer,
|
||||||
) {
|
) {
|
||||||
let mut state = wstate;
|
let rect: egui::Rect = ui.available_rect_before_wrap();
|
||||||
let rect = ui.clip_rect();
|
// let ctx: cur_context = cur_context {
|
||||||
let center = Pos2 {
|
let state: &structs::AuthState = wstate.deref();
|
||||||
|
|
||||||
|
let center: Pos2 = Pos2 {
|
||||||
x: rect.width() / 2.,
|
x: rect.width() / 2.,
|
||||||
y: rect.height() / 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 {
|
if state.failed_attempts > 0 {
|
||||||
painter.circle(
|
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) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user