mirror of
https://github.com/house-of-vanity/khm.git
synced 2025-08-21 22:27:14 +00:00
UI code reworked
This commit is contained in:
@@ -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()
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user