Work on card settings UI
This commit is contained in:
parent
235d3c3600
commit
e322c4084c
51
src/card.rs
51
src/card.rs
@ -1,36 +1,11 @@
|
|||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use eframe::egui::Ui;
|
use eframe::egui::Ui;
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
pub struct Config<'a> {
|
|
||||||
#[serde(rename = "type")]
|
|
||||||
typ: &'a str,
|
|
||||||
#[serde(flatten)]
|
|
||||||
settings: ron::Value,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config<'_> {
|
|
||||||
pub fn to_card(&self) -> anyhow::Result<Box<dyn Card>> {
|
|
||||||
inventory::iter::<Type>
|
|
||||||
.into_iter()
|
|
||||||
.find(|card_type| card_type.name == self.typ)
|
|
||||||
.ok_or_else(|| anyhow!("Invalid card type {}", self.typ))?
|
|
||||||
.new_card(self.settings.clone())
|
|
||||||
}
|
|
||||||
pub fn to_settings_ui(&self) -> anyhow::Result<Box<dyn SettingsUi>> {
|
|
||||||
inventory::iter::<Type>
|
|
||||||
.into_iter()
|
|
||||||
.find(|card_type| card_type.name == self.typ)
|
|
||||||
.ok_or_else(|| anyhow!("Invalid card type {}", self.typ))?
|
|
||||||
.settings_ui(self.settings.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Type {
|
pub struct Type {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
new: fn(settings: ron::Value) -> anyhow::Result<Box<dyn Card>>,
|
new: fn(settings: ron::Value) -> anyhow::Result<Box<dyn Card>>,
|
||||||
settings_ui: fn(settings: ron::Value) -> anyhow::Result<Box<dyn SettingsUi>>,
|
settings_ui: fn(settings: ron::Value) -> anyhow::Result<Box<dyn SettingsUi>>,
|
||||||
|
default_settings: fn() -> String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
@ -39,16 +14,32 @@ impl Type {
|
|||||||
name,
|
name,
|
||||||
new: T::new_dyn,
|
new: T::new_dyn,
|
||||||
settings_ui: T::settings_ui_dyn,
|
settings_ui: T::settings_ui_dyn,
|
||||||
|
default_settings: T::default_settings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_card(&self, settings: ron::Value) -> anyhow::Result<Box<dyn Card>> {
|
pub fn new_card(&self, settings: ron::Value) -> anyhow::Result<Box<dyn Card>> {
|
||||||
(self.new)(settings)
|
(self.new)(settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn settings_ui(&self, settings: ron::Value) -> anyhow::Result<Box<dyn SettingsUi>> {
|
pub fn settings_ui(&self, settings: ron::Value) -> anyhow::Result<Box<dyn SettingsUi>> {
|
||||||
(self.settings_ui)(settings)
|
(self.settings_ui)(settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default_settings(&self) -> String {
|
||||||
|
(self.default_settings)()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(name: &str) -> anyhow::Result<&'static Self> {
|
||||||
|
inventory::iter::<Type>
|
||||||
|
.into_iter()
|
||||||
|
.find(|card_type| card_type.name == name)
|
||||||
|
.ok_or_else(|| anyhow!("Invalid card type {}", name))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &'static str {
|
||||||
|
self.name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inventory::collect!(Type);
|
inventory::collect!(Type);
|
||||||
@ -66,6 +57,10 @@ pub trait Card {
|
|||||||
Ok(Box::new(card))
|
Ok(Box::new(card))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_settings() -> String
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
|
||||||
fn read_mem(&mut self, _address: u16) -> Option<u8> {
|
fn read_mem(&mut self, _address: u16) -> Option<u8> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,23 @@
|
|||||||
use eframe::egui::{self, Slider};
|
use eframe::{
|
||||||
|
egui::{
|
||||||
|
self, CentralPanel, DragValue, Layout, Margin, SidePanel, Slider, Style, TopBottomPanel,
|
||||||
|
},
|
||||||
|
emath::Align,
|
||||||
|
};
|
||||||
use egui_modal::Modal;
|
use egui_modal::Modal;
|
||||||
|
|
||||||
use crate::{state::EmuState, window::Window, Options};
|
use crate::{
|
||||||
|
card::{SettingsUi, Type},
|
||||||
|
state::EmuState,
|
||||||
|
window::Window,
|
||||||
|
Options,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct OptionWindow {
|
pub struct OptionWindow {
|
||||||
options: Options,
|
options: Options,
|
||||||
category: OptionsCategory,
|
category: OptionsCategory,
|
||||||
|
card_options: Vec<(&'static str, Box<dyn SettingsUi>)>,
|
||||||
|
select_idx: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
@ -17,9 +29,17 @@ enum OptionsCategory {
|
|||||||
impl OptionWindow {
|
impl OptionWindow {
|
||||||
pub fn new(ctx: &egui::Context, state: &EmuState) -> Self {
|
pub fn new(ctx: &egui::Context, state: &EmuState) -> Self {
|
||||||
Modal::new(ctx, "options_modal").open();
|
Modal::new(ctx, "options_modal").open();
|
||||||
|
let ramcard_type = Type::get("RAM card").unwrap();
|
||||||
|
let def_opts = ramcard_type.default_settings();
|
||||||
|
let settings_ui = ramcard_type
|
||||||
|
.settings_ui(ron::from_str(&def_opts).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
let card_options = vec![(ramcard_type.name(), settings_ui)];
|
||||||
Self {
|
Self {
|
||||||
options: state.options(),
|
options: state.options(),
|
||||||
category: OptionsCategory::General,
|
category: OptionsCategory::General,
|
||||||
|
card_options,
|
||||||
|
select_idx: Some(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,12 +58,37 @@ impl Window for OptionWindow {
|
|||||||
ui.checkbox(&mut self.options.mute, "Mute");
|
ui.checkbox(&mut self.options.mute, "Mute");
|
||||||
ui.checkbox(&mut self.options.fan_enabled, "Fan enabled");
|
ui.checkbox(&mut self.options.fan_enabled, "Fan enabled");
|
||||||
ui.add(Slider::new(&mut self.options.volume, 0.0..=100.0).text("Volume"));
|
ui.add(Slider::new(&mut self.options.volume, 0.0..=100.0).text("Volume"));
|
||||||
|
ui.separator();
|
||||||
}
|
}
|
||||||
OptionsCategory::Cards => {
|
OptionsCategory::Cards => {
|
||||||
ui.heading("TODO");
|
TopBottomPanel::top("card_opts").show_inside(ui, |ui| {
|
||||||
|
SidePanel::left("card_opts_left")
|
||||||
|
.show_separator_line(false)
|
||||||
|
.show_inside(ui, |ui| {
|
||||||
|
let frame =
|
||||||
|
egui::Frame::canvas(&Style::default()).outer_margin(Margin {
|
||||||
|
left: 0.0,
|
||||||
|
right: 0.0,
|
||||||
|
top: 0.0,
|
||||||
|
bottom: 10.0,
|
||||||
|
});
|
||||||
|
frame.show(ui, |ui| {
|
||||||
|
for (i, (name, _settings_ui)) in
|
||||||
|
self.card_options.iter().enumerate()
|
||||||
|
{
|
||||||
|
ui.selectable_value(&mut self.select_idx, Some(i), *name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
CentralPanel::default().show_inside(ui, |ui| {
|
||||||
|
if let Some(select_idx) = self.select_idx {
|
||||||
|
self.card_options[select_idx].1.draw_ui(ui);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
modal.buttons(ui, |ui| {
|
ui.with_layout(Layout::right_to_left(Align::Min), |ui| {
|
||||||
if ui.button("Apply").clicked() {
|
if ui.button("Apply").clicked() {
|
||||||
state.update_options(self.options);
|
state.update_options(self.options);
|
||||||
}
|
}
|
||||||
|
13
src/ram.rs
13
src/ram.rs
@ -1,7 +1,10 @@
|
|||||||
use eframe::egui::{DragValue, Ui};
|
use eframe::egui::{DragValue, Ui};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{card::{Card, SettingsUi}, register};
|
use crate::{
|
||||||
|
card::{Card, SettingsUi},
|
||||||
|
register,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct RamCardSettings {
|
pub struct RamCardSettings {
|
||||||
@ -47,6 +50,14 @@ impl Card for RamCard {
|
|||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_settings() -> String {
|
||||||
|
ron::to_string(&RamCardSettings {
|
||||||
|
size: 4096,
|
||||||
|
start_addr: 0,
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
fn settings_ui(settings: ron::Value) -> anyhow::Result<impl SettingsUi>
|
fn settings_ui(settings: ron::Value) -> anyhow::Result<impl SettingsUi>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
Loading…
Reference in New Issue
Block a user