Added dark and light modes
This commit is contained in:
560
ui/src/main.rs
560
ui/src/main.rs
@@ -126,10 +126,6 @@ enum AppState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ChessApp {
|
struct ChessApp {
|
||||||
fullscreen: bool,
|
|
||||||
resolutions: Vec<(u32, u32)>,
|
|
||||||
pending_settings: PendingSettings,
|
|
||||||
selected_resolution: usize,
|
|
||||||
state: AppState,
|
state: AppState,
|
||||||
game_state: Arc<Mutex<GameState>>,
|
game_state: Arc<Mutex<GameState>>,
|
||||||
server_port: String,
|
server_port: String,
|
||||||
@@ -141,13 +137,18 @@ struct ChessApp {
|
|||||||
rx_from_network: Option<mpsc::UnboundedReceiver<ServerMessage2>>,
|
rx_from_network: Option<mpsc::UnboundedReceiver<ServerMessage2>>,
|
||||||
// UI state
|
// UI state
|
||||||
selected_square: Option<(usize, usize)>,
|
selected_square: Option<(usize, usize)>,
|
||||||
|
//Settings
|
||||||
|
fullscreen: bool,
|
||||||
|
resolutions: Vec<(u32, u32)>,
|
||||||
|
pending_settings: PendingSettings,
|
||||||
|
selected_resolution: usize,
|
||||||
|
dark_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct PendingSettings {
|
struct PendingSettings {
|
||||||
fullscreen: bool,
|
fullscreen: bool,
|
||||||
selected_resolution: usize,
|
selected_resolution: usize,
|
||||||
server_port: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ChessApp {
|
impl Default for ChessApp {
|
||||||
@@ -163,6 +164,7 @@ impl Default for ChessApp {
|
|||||||
],
|
],
|
||||||
pending_settings: PendingSettings::default(),
|
pending_settings: PendingSettings::default(),
|
||||||
selected_resolution: 2,
|
selected_resolution: 2,
|
||||||
|
dark_mode: false,
|
||||||
state: AppState::MainMenu,
|
state: AppState::MainMenu,
|
||||||
game_state: Arc::new(Mutex::new(GameState::default())),
|
game_state: Arc::new(Mutex::new(GameState::default())),
|
||||||
server_port: "9001".to_string(),
|
server_port: "9001".to_string(),
|
||||||
@@ -213,7 +215,6 @@ impl ChessApp {
|
|||||||
fn apply_settings(&mut self, ctx: &egui::Context) {
|
fn apply_settings(&mut self, ctx: &egui::Context) {
|
||||||
self.fullscreen = self.pending_settings.fullscreen;
|
self.fullscreen = self.pending_settings.fullscreen;
|
||||||
self.selected_resolution = self.pending_settings.selected_resolution;
|
self.selected_resolution = self.pending_settings.selected_resolution;
|
||||||
self.server_port = self.pending_settings.server_port.clone();
|
|
||||||
|
|
||||||
if let Some(resolution) = self.resolutions.get(self.selected_resolution) {
|
if let Some(resolution) = self.resolutions.get(self.selected_resolution) {
|
||||||
ctx.send_viewport_cmd(egui::ViewportCommand::InnerSize(
|
ctx.send_viewport_cmd(egui::ViewportCommand::InnerSize(
|
||||||
@@ -439,70 +440,151 @@ impl eframe::App for ChessApp {
|
|||||||
|
|
||||||
// Get current game state
|
// Get current game state
|
||||||
let game_state = self.game_state.lock().unwrap().clone();
|
let game_state = self.game_state.lock().unwrap().clone();
|
||||||
|
|
||||||
let screen_size = ctx.screen_rect().size();
|
let screen_size = ctx.screen_rect().size();
|
||||||
let base_size = screen_size.x.min(screen_size.y);
|
let base_size = screen_size.x.min(screen_size.y);
|
||||||
|
|
||||||
|
|
||||||
|
// Determine background color based on dark mode setting
|
||||||
|
let background_color = if self.dark_mode {
|
||||||
|
egui::Color32::from_rgb(27, 27, 27) // Dark mode
|
||||||
|
} else {
|
||||||
|
egui::Color32::from_rgb(235, 235, 235) // Light mode
|
||||||
|
};
|
||||||
|
// Also adjust text colors if needed
|
||||||
|
let text_color = if self.dark_mode {
|
||||||
|
egui::Color32::WHITE
|
||||||
|
} else {
|
||||||
|
egui::Color32::BLACK
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update the visual style based on dark mode
|
||||||
|
let mut visuals = ctx.style().visuals.clone();
|
||||||
|
|
||||||
|
if self.dark_mode {
|
||||||
|
// Dark mode visuals
|
||||||
|
visuals = egui::Visuals::dark();
|
||||||
|
// Adjust specific colors if needed
|
||||||
|
visuals.widgets.noninteractive.bg_fill = egui::Color32::from_rgb(40, 40, 40);
|
||||||
|
visuals.widgets.inactive.bg_fill = egui::Color32::from_rgb(60, 60, 60);
|
||||||
|
visuals.widgets.hovered.bg_fill = egui::Color32::from_rgb(70, 70, 70);
|
||||||
|
visuals.widgets.active.bg_fill = egui::Color32::from_rgb(80, 80, 80);
|
||||||
|
visuals.faint_bg_color = egui::Color32::from_rgb(50, 50, 50);
|
||||||
|
visuals.extreme_bg_color = egui::Color32::from_rgb(20, 20, 20);
|
||||||
|
visuals.code_bg_color = egui::Color32::from_rgb(40, 40, 40);
|
||||||
|
visuals.panel_fill = background_color;
|
||||||
|
} else {
|
||||||
|
// Light mode visuals
|
||||||
|
visuals = egui::Visuals::light();
|
||||||
|
visuals.widgets.noninteractive.bg_fill = egui::Color32::from_rgb(210, 210, 210);
|
||||||
|
visuals.widgets.inactive.bg_fill = egui::Color32::from_rgb(190,190,190);
|
||||||
|
visuals.widgets.hovered.bg_fill = egui::Color32::from_rgb(180,180,180);
|
||||||
|
visuals.widgets.active.bg_fill = egui::Color32::from_rgb(170,170,170);
|
||||||
|
visuals.faint_bg_color = egui::Color32::from_rgb(200,200,200);
|
||||||
|
visuals.extreme_bg_color = egui::Color32::from_rgb(230,230,230);
|
||||||
|
visuals.code_bg_color = egui::Color32::from_rgb(210,210,210);
|
||||||
|
visuals.panel_fill = background_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the updated visuals
|
||||||
|
ctx.set_visuals(visuals);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
match self.state {
|
match self.state {
|
||||||
AppState::MainMenu => {
|
AppState::MainMenu => {
|
||||||
|
// Proportional sizing
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//proportional sizing
|
|
||||||
let button_width = base_size*0.4;
|
let button_width = base_size*0.4;
|
||||||
let button_height = base_size*0.1;
|
let button_height = base_size*0.1;
|
||||||
let font_size = base_size*0.025;
|
let font_size = base_size*0.025;
|
||||||
let heading_size=base_size*0.1;
|
let heading_size=base_size*0.1;
|
||||||
let spacing_size = base_size*0.07;
|
let spacing_size = base_size*0.07;
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
// Set background color for the entire panel
|
||||||
ui.vertical_centered(|ui| {
|
egui::CentralPanel::default()
|
||||||
ui.heading("♞ Knightly ♞");
|
.frame(egui::Frame::default().fill(background_color))
|
||||||
ui.add_space(30.0);
|
.show(ctx, |ui| {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
ui.horizontal(|ui| {
|
// Style the heading based on dark mode
|
||||||
ui.label("Username:");
|
let heading_color = if self.dark_mode {
|
||||||
ui.text_edit_singleline(&mut self.username);
|
egui::Color32::WHITE
|
||||||
});
|
} else {
|
||||||
|
egui::Color32::BLACK
|
||||||
ui.add_space(20.0);
|
};
|
||||||
if ui.add_sized(
|
|
||||||
egui::Vec2::new(button_width, button_height),
|
|
||||||
egui::Button::new(egui::RichText::new("Online Play").size(font_size))
|
|
||||||
).clicked() {
|
|
||||||
self.server_ip = "127.0.0.1".to_string();
|
|
||||||
self.connect_to_server();
|
|
||||||
}
|
|
||||||
ui.add_space(20.0);
|
|
||||||
if ui.add_sized(
|
|
||||||
egui::Vec2::new(button_width, button_height),
|
|
||||||
egui::Button::new(egui::RichText::new("Private Play").size(font_size))
|
|
||||||
).clicked() {
|
|
||||||
self.state = AppState::PrivatePlayConnect;
|
|
||||||
}
|
|
||||||
ui.add_space(20.0);
|
|
||||||
if ui.add_sized(
|
|
||||||
egui::Vec2::new(button_width,button_height),
|
|
||||||
egui::Button::new(egui::RichText::new("Settings").size(font_size))
|
|
||||||
).clicked(){
|
|
||||||
self.state = AppState::Settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ui.heading(egui::RichText::new("♞ Knightly ♞").color(heading_color));
|
||||||
|
ui.add_space(30.0);
|
||||||
|
|
||||||
ui.add_space(20.0);
|
ui.horizontal(|ui| {
|
||||||
if ui.add_sized(
|
ui.label(egui::RichText::new("Username:").color(heading_color));
|
||||||
egui::Vec2::new(button_width, button_height),
|
ui.text_edit_singleline(&mut self.username);
|
||||||
egui::Button::new(egui::RichText::new("Quit").size(font_size))
|
});
|
||||||
).clicked() {
|
|
||||||
std::process::exit(0);
|
ui.add_space(20.0);
|
||||||
}
|
|
||||||
|
// Create styled button
|
||||||
|
let button_text_color = if self.dark_mode {
|
||||||
|
egui::Color32::WHITE
|
||||||
|
} else {
|
||||||
|
egui::Color32::BLACK
|
||||||
|
};
|
||||||
|
|
||||||
|
if ui.add_sized(
|
||||||
|
egui::Vec2::new(button_width, button_height),
|
||||||
|
egui::Button::new(
|
||||||
|
egui::RichText::new("Online Play")
|
||||||
|
.size(font_size)
|
||||||
|
.color(button_text_color)
|
||||||
|
)
|
||||||
|
).clicked() {
|
||||||
|
self.server_ip = "127.0.0.1".to_string();
|
||||||
|
self.connect_to_server();
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.add_space(20.0);
|
||||||
|
|
||||||
|
if ui.add_sized(
|
||||||
|
egui::Vec2::new(button_width, button_height),
|
||||||
|
egui::Button::new(
|
||||||
|
egui::RichText::new("Private Play")
|
||||||
|
.size(font_size)
|
||||||
|
.color(button_text_color)
|
||||||
|
)
|
||||||
|
).clicked() {
|
||||||
|
self.state = AppState::PrivatePlayConnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.add_space(20.0);
|
||||||
|
|
||||||
|
if ui.add_sized(
|
||||||
|
egui::Vec2::new(button_width, button_height),
|
||||||
|
egui::Button::new(
|
||||||
|
egui::RichText::new("Settings")
|
||||||
|
.size(font_size)
|
||||||
|
.color(button_text_color)
|
||||||
|
)
|
||||||
|
).clicked() {
|
||||||
|
self.state = AppState::Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.add_space(20.0);
|
||||||
|
|
||||||
|
if ui.add_sized(
|
||||||
|
egui::Vec2::new(button_width, button_height),
|
||||||
|
egui::Button::new(
|
||||||
|
egui::RichText::new("Quit")
|
||||||
|
.size(font_size)
|
||||||
|
.color(button_text_color)
|
||||||
|
)
|
||||||
|
).clicked() {
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
AppState::Settings => {
|
AppState::Settings => {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default()
|
||||||
|
.frame(egui::Frame::default().fill(background_color))
|
||||||
|
.show(ctx, |ui| {
|
||||||
ui.vertical_centered(|ui| {
|
ui.vertical_centered(|ui| {
|
||||||
ui.heading("Settings");
|
ui.heading("Settings");
|
||||||
ui.add_space(30.0);
|
ui.add_space(30.0);
|
||||||
@@ -535,8 +617,14 @@ impl eframe::App for ChessApp {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ui.add_space(30.0);
|
ui.add_space(10.0);
|
||||||
|
//dark mode toggle
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("Dark mode");
|
||||||
|
if ui.checkbox(&mut self.dark_mode, "").changed() {
|
||||||
|
info!("Dark mode changed to: {}", self.dark_mode);
|
||||||
|
}
|
||||||
|
});
|
||||||
// Apply and Cancel buttons
|
// Apply and Cancel buttons
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if ui.add_sized([140.0, 40.0], egui::Button::new("Apply")).clicked() {
|
if ui.add_sized([140.0, 40.0], egui::Button::new("Apply")).clicked() {
|
||||||
@@ -552,122 +640,174 @@ impl eframe::App for ChessApp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
AppState::PrivatePlayConnect => {
|
AppState::PrivatePlayConnect => {
|
||||||
let button_width = base_size*0.4;
|
let button_width = base_size*0.4;
|
||||||
let button_height = base_size*0.1;
|
let button_height = base_size*0.1;
|
||||||
let font_size = base_size*0.025;
|
let font_size = base_size*0.025;
|
||||||
let heading_size=base_size*0.1;
|
|
||||||
let spacing_size = base_size*0.07;
|
let text_color = if self.dark_mode {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::Color32::WHITE
|
||||||
ui.vertical_centered(|ui| {
|
} else {
|
||||||
ui.horizontal(|ui| {
|
egui::Color32::BLACK
|
||||||
ui.label("Server ip address");
|
};
|
||||||
ui.text_edit_singleline(&mut self.server_ip);
|
|
||||||
});
|
egui::CentralPanel::default()
|
||||||
|
.frame(egui::Frame::default().fill(background_color))
|
||||||
ui.horizontal(|ui| {
|
.show(ctx, |ui| {
|
||||||
ui.label("Server Port:");
|
ui.vertical_centered(|ui| {
|
||||||
ui.text_edit_singleline(&mut self.server_port);
|
ui.horizontal(|ui| {
|
||||||
});
|
ui.label(egui::RichText::new("Server ip address").color(text_color));
|
||||||
|
ui.text_edit_singleline(&mut self.server_ip);
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.checkbox(&mut self.start_local_server_instance, "Host Server");
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.add_space(20.0);
|
|
||||||
if ui.add_sized(
|
|
||||||
egui::Vec2::new(button_width, button_height),
|
|
||||||
egui::Button::new(egui::RichText::new("Play").size(font_size))
|
|
||||||
).clicked() {
|
|
||||||
if self.start_local_server_instance == true {
|
|
||||||
let path = if cfg!(windows) {
|
|
||||||
"./server.exe"
|
|
||||||
} else {
|
|
||||||
"./server"
|
|
||||||
};
|
|
||||||
|
|
||||||
if !Path::new(path).exists() {
|
|
||||||
error!("Server binary does not exist, cfg: {}", path);
|
|
||||||
} else {
|
|
||||||
let _ = Command::new(path).spawn();
|
|
||||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.connect_to_server();
|
|
||||||
}
|
|
||||||
ui.add_space(20.0);
|
|
||||||
if ui.add_sized(
|
|
||||||
egui::Vec2::new(button_width, button_height),
|
|
||||||
egui::Button::new(egui::RichText::new("Return to main menu").size(font_size))
|
|
||||||
).clicked(){
|
|
||||||
self.state=AppState::MainMenu;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(egui::RichText::new("Server Port:").color(text_color));
|
||||||
|
ui.text_edit_singleline(&mut self.server_port);
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(egui::RichText::new("Host Server").color(text_color));
|
||||||
|
ui.checkbox(&mut self.start_local_server_instance, "");
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.add_space(20.0);
|
||||||
|
if ui.add_sized(
|
||||||
|
egui::Vec2::new(button_width, button_height),
|
||||||
|
egui::Button::new(
|
||||||
|
egui::RichText::new("Play")
|
||||||
|
.size(font_size)
|
||||||
|
.color(text_color)
|
||||||
|
)
|
||||||
|
).clicked() {
|
||||||
|
if self.start_local_server_instance == true {
|
||||||
|
let path = if cfg!(windows) {
|
||||||
|
"./server.exe"
|
||||||
|
} else {
|
||||||
|
"./server"
|
||||||
|
};
|
||||||
|
|
||||||
|
if !Path::new(path).exists() {
|
||||||
|
error!("Server binary does not exist, cfg: {}", path);
|
||||||
|
} else {
|
||||||
|
let _ = Command::new(path).spawn();
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.connect_to_server();
|
||||||
|
}
|
||||||
|
ui.add_space(20.0);
|
||||||
|
if ui.add_sized(
|
||||||
|
egui::Vec2::new(button_width, button_height),
|
||||||
|
egui::Button::new(
|
||||||
|
egui::RichText::new("Return to main menu")
|
||||||
|
.size(font_size)
|
||||||
|
.color(text_color)
|
||||||
|
)
|
||||||
|
).clicked(){
|
||||||
|
self.state=AppState::MainMenu;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
AppState::Connecting => {
|
AppState::Connecting => {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
let text_color = if self.dark_mode {
|
||||||
ui.vertical_centered(|ui| {
|
egui::Color32::WHITE
|
||||||
ui.heading("Connecting to Server...");
|
} else {
|
||||||
ui.add_space(20.0);
|
egui::Color32::BLACK
|
||||||
ui.spinner();
|
};
|
||||||
});
|
|
||||||
|
egui::CentralPanel::default()
|
||||||
|
.frame(egui::Frame::default().fill(background_color))
|
||||||
|
.show(ctx, |ui| {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.heading(egui::RichText::new("Connecting to Server...").color(text_color));
|
||||||
|
ui.add_space(20.0);
|
||||||
|
ui.spinner();
|
||||||
|
|
||||||
if ui.button("Cancel").clicked() {
|
ui.add_space(20.0);
|
||||||
info!("Returning to menu from before connecting to the server");
|
if ui.button(
|
||||||
self.state = AppState::MainMenu;
|
egui::RichText::new("Cancel").color(text_color)
|
||||||
}
|
).clicked() {
|
||||||
});
|
info!("Returning to menu from before connecting to the server");
|
||||||
}
|
self.state = AppState::MainMenu;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
AppState::FindingMatch => {
|
AppState::FindingMatch => {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
let text_color = if self.dark_mode {
|
||||||
ui.vertical_centered(|ui| {
|
egui::Color32::WHITE
|
||||||
ui.heading("Finding Match...");
|
} else {
|
||||||
ui.add_space(20.0);
|
egui::Color32::BLACK
|
||||||
ui.label("Waiting for an opponent...");
|
};
|
||||||
ui.spinner();
|
|
||||||
|
egui::CentralPanel::default()
|
||||||
|
.frame(egui::Frame::default().fill(background_color))
|
||||||
|
.show(ctx, |ui| {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.heading(egui::RichText::new("Finding Match...").color(text_color));
|
||||||
|
ui.add_space(20.0);
|
||||||
|
ui.label(egui::RichText::new("Waiting for an opponent...").color(text_color));
|
||||||
|
ui.spinner();
|
||||||
|
|
||||||
ui.add_space(20.0);
|
ui.add_space(20.0);
|
||||||
if ui.button("cancel").clicked() {
|
if ui.button(
|
||||||
if let Some(tx) = &self.tx_to_network {
|
egui::RichText::new("cancel").color(text_color)
|
||||||
warn!("Closing connection to server, cancelled match findig!");
|
).clicked() {
|
||||||
tx.send(ClientEvent::CloseConnection);
|
if let Some(tx) = &self.tx_to_network {
|
||||||
self.state = AppState::MainMenu;
|
warn!("Closing connection to server, cancelled match finding!");
|
||||||
}
|
let _ = tx.send(ClientEvent::CloseConnection);
|
||||||
}
|
self.state = AppState::MainMenu;
|
||||||
});
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
AppState::InGame => {
|
AppState::InGame => {
|
||||||
|
let text_color = if self.dark_mode {
|
||||||
|
egui::Color32::WHITE
|
||||||
|
} else {
|
||||||
|
egui::Color32::BLACK
|
||||||
|
};
|
||||||
|
|
||||||
// Draw menu bar
|
// Draw menu bar
|
||||||
egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| {
|
egui::TopBottomPanel::top("menu_bar")
|
||||||
ui.horizontal(|ui| {
|
.frame(egui::Frame::default().fill(background_color))
|
||||||
if ui.button("Main Menu").clicked() {
|
.show(ctx, |ui| {
|
||||||
*self = ChessApp::default();
|
ui.horizontal(|ui| {
|
||||||
}
|
if ui.button(
|
||||||
|
egui::RichText::new("Main Menu").color(text_color)
|
||||||
if ui.button("Resign").clicked() {
|
).clicked() {
|
||||||
if let Some(tx) = &self.tx_to_network {
|
*self = ChessApp::default();
|
||||||
let _ = tx.send(ClientEvent::Resign);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ui.separator();
|
if ui.button(
|
||||||
|
egui::RichText::new("Resign").color(text_color)
|
||||||
|
).clicked() {
|
||||||
|
if let Some(tx) = &self.tx_to_network {
|
||||||
|
let _ = tx.send(ClientEvent::Resign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(color) = &game_state.player_color {
|
ui.separator();
|
||||||
ui.label(format!("You are: {}", color));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(opponent) = &game_state.opponent_name {
|
if let Some(color) = &game_state.player_color {
|
||||||
ui.label(format!("vs: {}", opponent));
|
ui.label(egui::RichText::new(format!("You are: {}", color)).color(text_color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(opponent) = &game_state.opponent_name {
|
||||||
|
ui.label(egui::RichText::new(format!("vs: {}", opponent)).color(text_color));
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Main content area with chess board and move history
|
// Main content area with chess board and move history
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default()
|
||||||
|
.frame(egui::Frame::default().fill(background_color))
|
||||||
|
.show(ctx, |ui| {
|
||||||
let total_width = ui.available_width();
|
let total_width = ui.available_width();
|
||||||
let total_height = ui.available_height();
|
let total_height = ui.available_height();
|
||||||
|
|
||||||
@@ -773,7 +913,11 @@ impl eframe::App for ChessApp {
|
|||||||
// Move History (right side) - match the board height
|
// Move History (right side) - match the board height
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
egui::Frame::default()
|
egui::Frame::default()
|
||||||
.fill(egui::Color32::from_rgb(240, 240, 240))
|
.fill(if self.dark_mode {
|
||||||
|
egui::Color32::from_rgb(60, 60, 60)
|
||||||
|
} else {
|
||||||
|
egui::Color32::from_rgb(240, 240, 240)
|
||||||
|
})
|
||||||
.stroke(egui::Stroke::new(1.0, egui::Color32::from_rgb(200, 200, 200)))
|
.stroke(egui::Stroke::new(1.0, egui::Color32::from_rgb(200, 200, 200)))
|
||||||
.inner_margin(egui::Margin::same(8))
|
.inner_margin(egui::Margin::same(8))
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
@@ -786,27 +930,37 @@ impl eframe::App for ChessApp {
|
|||||||
|
|
||||||
// Scroll area for move history
|
// Scroll area for move history
|
||||||
egui::ScrollArea::vertical()
|
egui::ScrollArea::vertical()
|
||||||
.max_height(board_size - 50.0) // Based on board height
|
.max_height(board_size - 50.0)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
// Use actual move history from game_state
|
if let Ok(game_state) = self.game_state.lock() {
|
||||||
if let Ok(game_state) = self.game_state.lock() {
|
for (i, move_text) in game_state.move_history.iter().enumerate() {
|
||||||
for (i, move_text) in game_state.move_history.iter().enumerate() {
|
ui.horizontal(|ui| {
|
||||||
ui.horizontal(|ui| {
|
// Alternate background based on dark mode
|
||||||
// Alternate background
|
if i % 2 == 0 {
|
||||||
if i % 2 == 0 {
|
ui.visuals_mut().widgets.noninteractive.bg_fill =
|
||||||
ui.visuals_mut().widgets.noninteractive.bg_fill =
|
if self.dark_mode {
|
||||||
egui::Color32::from_rgb(250, 250, 250);
|
egui::Color32::from_rgb(70, 70, 70)
|
||||||
} else {
|
} else {
|
||||||
ui.visuals_mut().widgets.noninteractive.bg_fill =
|
egui::Color32::from_rgb(250, 250, 250)
|
||||||
egui::Color32::from_rgb(230, 230, 230);
|
};
|
||||||
}
|
} else {
|
||||||
|
ui.visuals_mut().widgets.noninteractive.bg_fill =
|
||||||
ui.label(egui::RichText::new(move_text.to_string()).size(16.0));
|
if self.dark_mode {
|
||||||
|
egui::Color32::from_rgb(50, 50, 50)
|
||||||
if ui.small_button("📋").clicked() {
|
} else {
|
||||||
info!("Copy move: {}", move_text);
|
egui::Color32::from_rgb(230, 230, 230)
|
||||||
}
|
};
|
||||||
});
|
}
|
||||||
|
|
||||||
|
// Move text color
|
||||||
|
ui.label(egui::RichText::new(move_text.to_string())
|
||||||
|
.size(16.0)
|
||||||
|
.color(text_color));
|
||||||
|
|
||||||
|
if ui.small_button("📋").clicked() {
|
||||||
|
info!("Copy move: {}", move_text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if i < game_state.move_history.len() - 1 {
|
if i < game_state.move_history.len() - 1 {
|
||||||
ui.add_space(2.0);
|
ui.add_space(2.0);
|
||||||
@@ -814,11 +968,15 @@ impl eframe::App for ChessApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if game_state.move_history.is_empty() {
|
if game_state.move_history.is_empty() {
|
||||||
ui.vertical_centered(|ui| {
|
ui.vertical_centered(|ui| {
|
||||||
ui.add_space(20.0);
|
ui.add_space(20.0);
|
||||||
ui.label(egui::RichText::new("No moves yet").size(16.0));
|
ui.label(egui::RichText::new("No moves yet")
|
||||||
ui.label(egui::RichText::new("Game will start soon...").size(14.0));
|
.size(16.0)
|
||||||
});
|
.color(text_color));
|
||||||
|
ui.label(egui::RichText::new("Game will start soon...")
|
||||||
|
.size(14.0)
|
||||||
|
.color(text_color));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -831,23 +989,33 @@ impl eframe::App for ChessApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AppState::GameOver => {
|
AppState::GameOver => {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
let text_color = if self.dark_mode {
|
||||||
ui.vertical_centered(|ui| {
|
egui::Color32::WHITE
|
||||||
ui.heading("Game Over");
|
} else {
|
||||||
ui.add_space(20.0);
|
egui::Color32::BLACK
|
||||||
|
};
|
||||||
|
|
||||||
|
egui::CentralPanel::default()
|
||||||
|
.frame(egui::Frame::default().fill(background_color))
|
||||||
|
.show(ctx, |ui| {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.heading(egui::RichText::new("Game Over").color(text_color));
|
||||||
|
ui.add_space(20.0);
|
||||||
|
|
||||||
if let Some(reason) = &game_state.game_over {
|
if let Some(reason) = &game_state.game_over {
|
||||||
ui.label(format!("Result: {}", reason));
|
ui.label(egui::RichText::new(format!("Result: {}", reason)).color(text_color));
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.add_space(20.0);
|
ui.add_space(20.0);
|
||||||
|
|
||||||
if ui.button("Back to Main Menu").clicked() {
|
if ui.button(
|
||||||
*self = ChessApp::default();
|
egui::RichText::new("Back to Main Menu").color(text_color)
|
||||||
}
|
).clicked() {
|
||||||
});
|
*self = ChessApp::default();
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request repaint to keep UI responsive
|
// Request repaint to keep UI responsive
|
||||||
|
|||||||
Reference in New Issue
Block a user