UI code reworked

This commit is contained in:
Ultradesu
2025-07-22 20:10:44 +03:00
parent c342134f03
commit 7cc446d227
4 changed files with 667 additions and 286 deletions

View File

@@ -47,25 +47,123 @@ impl eframe::App for SettingsWindow {
// Apply enhanced modern dark theme
apply_modern_theme(ctx);
egui::CentralPanel::default()
.frame(egui::Frame::none().inner_margin(egui::Margin::same(20.0)))
// Bottom panel for Activity Log (fixed at bottom)
egui::TopBottomPanel::bottom("activity_log_panel")
.resizable(false)
.min_height(140.0)
.max_height(140.0)
.frame(egui::Frame::none()
.fill(egui::Color32::from_gray(12))
.stroke(egui::Stroke::new(1.0, egui::Color32::from_gray(60)))
)
.show(ctx, |ui| {
// Header with title
ui.horizontal(|ui| {
ui.heading(egui::RichText::new("🔑 KHM Settings").size(24.0));
render_bottom_activity_log(ui, &mut self.operation_log);
});
egui::CentralPanel::default()
.frame(egui::Frame::none()
.fill(egui::Color32::from_gray(18))
.inner_margin(egui::Margin::same(20.0))
)
.show(ctx, |ui| {
// Modern header with gradient-like styling
let header_frame = egui::Frame::none()
.fill(ui.visuals().panel_fill)
.rounding(egui::Rounding::same(8.0))
.inner_margin(egui::Margin::same(12.0))
.stroke(egui::Stroke::new(1.0, ui.visuals().widgets.noninteractive.bg_stroke.color));
header_frame.show(ui, |ui| {
ui.horizontal(|ui| {
ui.add_space(4.0);
ui.label("🔑");
ui.heading(egui::RichText::new("KHM Settings").size(20.0).strong());
ui.label(egui::RichText::new(
"(Known Hosts Manager for SSH key management and synchronization)"
).size(11.0).weak().italics());
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
// Version from Cargo.toml
let version = env!("CARGO_PKG_VERSION");
if ui.small_button(format!("v{}", version))
.on_hover_text(format!(
"{}\n{}\nRepository: {}\nLicense: {}",
env!("CARGO_PKG_DESCRIPTION"),
env!("CARGO_PKG_AUTHORS"),
env!("CARGO_PKG_REPOSITORY"),
"WTFPL"
))
.clicked()
{
// Open repository URL
if let Err(_) = std::process::Command::new("open")
.arg(env!("CARGO_PKG_REPOSITORY"))
.spawn()
{
// Fallback for non-macOS systems
let _ = std::process::Command::new("xdg-open")
.arg(env!("CARGO_PKG_REPOSITORY"))
.spawn();
}
}
});
});
});
ui.add_space(10.0);
ui.add_space(12.0);
// Tab selector
// Modern tab selector with card styling
ui.horizontal(|ui| {
ui.selectable_value(&mut self.current_tab, SettingsTab::Connection, "📃 Settings");
ui.selectable_value(&mut self.current_tab, SettingsTab::Admin, "🔧 Admin");
ui.spacing_mut().item_spacing.x = 6.0;
// Connection/Settings Tab
let connection_selected = matches!(self.current_tab, SettingsTab::Connection);
let connection_button = egui::Button::new(
egui::RichText::new("🌐 Connection").size(13.0)
)
.fill(if connection_selected {
egui::Color32::from_rgb(0, 120, 212)
} else {
ui.visuals().widgets.inactive.bg_fill
})
.stroke(if connection_selected {
egui::Stroke::new(1.0, egui::Color32::from_rgb(0, 120, 212))
} else {
egui::Stroke::new(1.0, ui.visuals().widgets.noninteractive.bg_stroke.color)
})
.rounding(6.0)
.min_size(egui::vec2(110.0, 32.0));
if ui.add(connection_button).clicked() {
self.current_tab = SettingsTab::Connection;
}
// Admin Tab
let admin_selected = matches!(self.current_tab, SettingsTab::Admin);
let admin_button = egui::Button::new(
egui::RichText::new("🔧 Admin Panel").size(13.0)
)
.fill(if admin_selected {
egui::Color32::from_rgb(120, 80, 0)
} else {
ui.visuals().widgets.inactive.bg_fill
})
.stroke(if admin_selected {
egui::Stroke::new(1.0, egui::Color32::from_rgb(120, 80, 0))
} else {
egui::Stroke::new(1.0, ui.visuals().widgets.noninteractive.bg_stroke.color)
})
.rounding(6.0)
.min_size(egui::vec2(110.0, 32.0));
if ui.add(admin_button).clicked() {
self.current_tab = SettingsTab::Admin;
}
});
ui.separator();
ui.add_space(15.0);
ui.add_space(16.0);
// Content area with proper spacing
match self.current_tab {
SettingsTab::Connection => {
render_connection_tab(
@@ -352,25 +450,93 @@ impl SettingsWindow {
}
}
/// Apply modern dark theme for the settings window
/// Apply modern dark theme for the settings window with enhanced styling
fn apply_modern_theme(ctx: &egui::Context) {
let mut visuals = egui::Visuals::dark();
visuals.window_fill = egui::Color32::from_gray(25);
visuals.panel_fill = egui::Color32::from_gray(30);
visuals.faint_bg_color = egui::Color32::from_gray(35);
visuals.extreme_bg_color = egui::Color32::from_gray(15);
// Modern color palette
visuals.window_fill = egui::Color32::from_gray(18); // Darker background
visuals.panel_fill = egui::Color32::from_gray(24); // Panel background
visuals.faint_bg_color = egui::Color32::from_gray(32); // Card background
visuals.extreme_bg_color = egui::Color32::from_gray(12); // Darkest areas
// Enhanced widget styling
visuals.button_frame = true;
visuals.collapsing_header_frame = true;
visuals.indent_has_left_vline = true;
visuals.menu_rounding = egui::Rounding::same(8.0);
visuals.window_rounding = egui::Rounding::same(12.0);
visuals.widgets.noninteractive.rounding = egui::Rounding::same(6.0);
visuals.widgets.inactive.rounding = egui::Rounding::same(6.0);
visuals.widgets.hovered.rounding = egui::Rounding::same(6.0);
visuals.widgets.active.rounding = egui::Rounding::same(6.0);
visuals.striped = true;
// Modern rounded corners
let rounding = egui::Rounding::same(8.0);
visuals.menu_rounding = rounding;
visuals.window_rounding = egui::Rounding::same(16.0);
visuals.widgets.noninteractive.rounding = rounding;
visuals.widgets.inactive.rounding = rounding;
visuals.widgets.hovered.rounding = rounding;
visuals.widgets.active.rounding = rounding;
// Better widget colors
visuals.widgets.noninteractive.bg_fill = egui::Color32::from_gray(40);
visuals.widgets.inactive.bg_fill = egui::Color32::from_gray(45);
visuals.widgets.hovered.bg_fill = egui::Color32::from_gray(55);
visuals.widgets.active.bg_fill = egui::Color32::from_gray(60);
// Subtle borders
let border_color = egui::Color32::from_gray(60);
visuals.widgets.noninteractive.bg_stroke = egui::Stroke::new(1.0, border_color);
visuals.widgets.inactive.bg_stroke = egui::Stroke::new(1.0, border_color);
visuals.widgets.hovered.bg_stroke = egui::Stroke::new(1.5, egui::Color32::from_gray(80));
visuals.widgets.active.bg_stroke = egui::Stroke::new(1.5, egui::Color32::from_gray(100));
ctx.set_visuals(visuals);
}
/// Render bottom activity log panel
fn render_bottom_activity_log(ui: &mut egui::Ui, operation_log: &mut Vec<String>) {
ui.add_space(18.0); // Larger top padding
ui.horizontal(|ui| {
ui.add_space(8.0);
ui.label("📋");
ui.label(egui::RichText::new("Activity Log").size(13.0).strong());
ui.with_layout(egui::Layout::right_to_left(egui::Align::Min), |ui| {
ui.add_space(8.0);
if ui.small_button("🗑 Clear").clicked() {
operation_log.clear();
}
});
});
ui.add_space(8.0);
// Add horizontal margin for the text area
ui.horizontal(|ui| {
ui.add_space(8.0); // Left margin
// Show last 5 log entries in multiline text
let log_text = if operation_log.is_empty() {
"No recent activity".to_string()
} else {
let start_idx = if operation_log.len() > 5 {
operation_log.len() - 5
} else {
0
};
operation_log[start_idx..].join("\n")
};
ui.add_sized(
[ui.available_width() - 8.0, 80.0], // Account for right margin
egui::TextEdit::multiline(&mut log_text.clone())
.font(egui::FontId::new(11.0, egui::FontFamily::Monospace))
.interactive(false)
);
ui.add_space(8.0); // Right margin
});
}
/// Create window icon for settings window
pub fn create_window_icon() -> egui::IconData {
// Create a simple programmatic icon (blue square with white border)
@@ -394,15 +560,19 @@ pub fn create_window_icon() -> egui::IconData {
}
}
/// Run the settings window application
/// Run the settings window application with modern horizontal styling
pub fn run_settings_window() {
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_title("KHM Settings")
.with_inner_size([600.0, 800.0])
.with_min_inner_size([500.0, 650.0])
.with_resizable(true)
.with_icon(create_window_icon()),
.with_inner_size([900.0, 905.0]) // Decreased height by another 15px
.with_min_inner_size([900.0, 905.0]) // Fixed size
.with_max_inner_size([900.0, 905.0]) // Same as min - fixed size
.with_resizable(false) // Disable resizing since window is fixed size
.with_icon(create_window_icon())
.with_decorations(true)
.with_transparent(false),
centered: true,
..Default::default()
};