Persist window state across runs

This commit is contained in:
2026-04-04 23:05:53 -04:00
parent f7b37caccb
commit e75bef634b
10 changed files with 342 additions and 155 deletions
+48 -29
View File
@@ -3,6 +3,7 @@ use egui::{
ViewportBuilder,
};
use egui_extras::{Column, Size, StripBuilder, TableBuilder};
use serde::{Deserialize, Serialize};
use crate::{
emulator::SimId,
@@ -10,42 +11,58 @@ use crate::{
memory::{MemoryClient, MemoryView},
window::{
AppWindow,
utils::{NumberEdit, UiExt as _},
utils::{NumberEdit, UiData, UiExt as _},
},
};
use super::utils;
pub struct FrameBufferWindow {
sim_id: SimId,
#[derive(Clone, PartialEq, Serialize, Deserialize)]
struct State {
index: usize,
left: bool,
right: bool,
generic_palette: bool,
params: ImageParams<FrameBufferParams>,
scale: f32,
}
impl FrameBufferWindow {
pub fn new(sim_id: SimId, memory: &MemoryClient, images: &ImageTextureLoader) -> Self {
let initial_params = FrameBufferParams {
impl Default for State {
fn default() -> Self {
Self {
index: 0,
left: true,
right: true,
generic_palette: false,
left_color: Color32::from_rgb(0xff, 0x00, 0x00),
right_color: Color32::from_rgb(0x00, 0xc6, 0xf0),
};
scale: 2.0,
}
}
}
pub struct FrameBufferWindow {
sim_id: SimId,
params: ImageParams<FrameBufferParams>,
state: UiData<State>,
}
impl FrameBufferWindow {
pub fn new(sim_id: SimId, memory: &MemoryClient, images: &ImageTextureLoader) -> Self {
let state: UiData<State> = UiData::new();
let renderer = FrameBufferRenderer::new(sim_id, memory);
let params = images.add(sim_id, renderer, initial_params);
let params = images.add(
sim_id,
renderer,
FrameBufferParams {
index: state.index,
left: state.left,
right: state.right,
generic_palette: state.generic_palette,
left_color: Color32::from_rgb(0xff, 0x00, 0x00),
right_color: Color32::from_rgb(0x00, 0xc6, 0xf0),
},
);
Self {
sim_id,
index: params.index,
left: params.left,
right: params.right,
generic_palette: params.generic_palette,
params,
scale: 2.0,
state,
}
}
@@ -61,7 +78,7 @@ impl FrameBufferWindow {
ui.label("Index");
});
row.col(|ui| {
ui.add(NumberEdit::new(&mut self.index).range(0..2));
ui.add(NumberEdit::new(&mut self.state.index).range(0..2));
});
});
body.row(row_height, |mut row| {
@@ -69,7 +86,7 @@ impl FrameBufferWindow {
ui.label("Left");
});
row.col(|ui| {
let address = self.index * 0x00008000;
let address = self.state.index * 0x00008000;
let mut address_str = format!("{address:08x}");
ui.add_enabled(
false,
@@ -82,7 +99,7 @@ impl FrameBufferWindow {
ui.label("Right");
});
row.col(|ui| {
let address = self.index * 0x00008000 + 0x00010000;
let address = self.state.index * 0x00008000 + 0x00010000;
let mut address_str = format!("{address:08x}");
ui.add_enabled(
false,
@@ -95,7 +112,7 @@ impl FrameBufferWindow {
ui.horizontal(|ui| {
ui.label("Scale");
ui.spacing_mut().slider_width = ui.available_width();
let slider = Slider::new(&mut self.scale, 1.0..=10.0)
let slider = Slider::new(&mut self.state.scale, 1.0..=10.0)
.step_by(1.0)
.show_value(false);
ui.add(slider);
@@ -105,29 +122,29 @@ impl FrameBufferWindow {
.body(|mut body| {
body.row(row_height, |mut row| {
row.col(|ui| {
ui.checkbox(&mut self.left, "Left");
ui.checkbox(&mut self.state.left, "Left");
});
row.col(|ui| {
ui.checkbox(&mut self.right, "Right");
ui.checkbox(&mut self.state.right, "Right");
});
});
});
ui.checkbox(&mut self.generic_palette, "Generic colors");
ui.checkbox(&mut self.state.generic_palette, "Generic colors");
});
});
self.params.write(FrameBufferParams {
index: self.index,
left: self.left,
right: self.right,
generic_palette: self.generic_palette,
index: self.state.index,
left: self.state.left,
right: self.state.right,
generic_palette: self.state.generic_palette,
..*self.params
});
}
fn show_buffers(&mut self, ui: &mut Ui) {
let image = Image::new(self.image_url("buffer"))
.fit_to_original_size(self.scale)
.fit_to_original_size(self.state.scale)
.texture_options(TextureOptions::NEAREST);
ui.add(image);
}
@@ -145,6 +162,7 @@ impl AppWindow for FrameBufferWindow {
}
fn show(&mut self, ui: &mut Ui) {
self.state.load(ui);
CentralPanel::default().show_inside(ui, |ui| {
ui.horizontal_top(|ui| {
StripBuilder::new(ui)
@@ -160,6 +178,7 @@ impl AppWindow for FrameBufferWindow {
});
});
});
self.state.save(ui);
}
}