Chirp/chirp-imgui/src/gui/menubar.rs

165 lines
4.7 KiB
Rust

//! The menubar that shows at the top of the screen
use super::Drawable;
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct Menubar {
pub(super) active: bool,
pub file: File,
pub settings: Settings,
pub debug: Debug,
pub about: Help,
}
impl Drawable for Menubar {
fn draw(&mut self, ui: &imgui::Ui) {
if self.active {
ui.main_menu_bar(|| {
self.file.draw(ui);
self.settings.draw(ui);
self.debug.draw(ui);
self.about.draw(ui);
})
}
}
}
impl Default for Menubar {
fn default() -> Self {
Self {
active: true,
file: Default::default(),
settings: Default::default(),
debug: Default::default(),
about: Default::default(),
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct File {
pub(super) reset: bool,
pub(super) quit: bool,
}
impl Drawable for File {
fn draw(&mut self, ui: &imgui::Ui) {
ui.menu("File", || {
self.reset = ui.menu_item("Reset");
self.quit = ui.menu_item("Quit");
})
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Debug {
pub(super) reset: bool,
pub(super) dis: bool,
}
impl Drawable for Debug {
fn draw(&mut self, ui: &imgui::Ui) {
ui.menu("Debug", || {
self.reset = ui.menu_item("Reset");
ui.checkbox("Live Disassembly", &mut self.dis);
})
}
}
impl Debug {
pub fn reset(&self) -> bool {
self.reset
}
pub fn dis(&self) -> bool {
self.dis
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Help {
pub(super) about_open: bool,
}
impl Drawable for Help {
fn draw(&mut self, ui: &imgui::Ui) {
ui.menu("Help", || self.about_open = ui.menu_item("About..."))
}
}
#[derive(Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Settings {
pub(super) target_ipf: usize,
pub(super) quirks: chirp::Quirks,
pub(super) mode_index: usize,
pub(super) colors: [[f32; 4]; 2],
pub(super) applied: bool,
}
impl Drawable for Settings {
fn draw(&mut self, ui: &imgui::Ui) {
self.applied = false;
ui.menu("Settings", || {
use chirp::Mode::*;
ui.menu("Foreground Color", || {
self.applied |= ui.color_picker4("", &mut self.colors[0])
});
ui.menu("Background Color", || {
self.applied |= ui.color_picker4("", &mut self.colors[1])
});
const MODES: [chirp::Mode; 3] = [Chip8, SChip, XOChip];
if ui.combo_simple_string("Mode", &mut self.mode_index, &MODES) {
self.quirks = MODES[self.mode_index].into();
self.applied |= true;
}
self.applied |= {
ui.input_scalar("IPF", &mut self.target_ipf)
.chars_decimal(true)
.build()
| ui.checkbox("Bin-ops don't clear vF", &mut self.quirks.bin_ops)
| ui.checkbox("DMA doesn't modify I", &mut self.quirks.dma_inc)
| ui.checkbox("Draw calls are instant", &mut self.quirks.draw_wait)
| ui.checkbox("Screen wraps at edge", &mut self.quirks.screen_wrap)
| ui.checkbox("Shift ops ignore vY", &mut self.quirks.shift)
| ui.checkbox("Jumps behave eratically", &mut self.quirks.stupid_jumps)
};
})
}
}
impl Settings {
pub fn target_ipf(&mut self) -> &mut usize {
&mut self.target_ipf
}
pub fn quirks(&mut self) -> &mut chirp::Quirks {
&mut self.quirks
}
pub fn set_mode(&mut self, mode: chirp::Mode) {
self.mode_index = mode as usize;
}
pub fn set_color(&mut self, fg: &[u8; 4], bg: &[u8; 4]) {
for (idx, component) in fg.iter().enumerate() {
self.colors[0][idx] = *component as f32 / 255.0;
}
for (idx, component) in bg.iter().enumerate() {
self.colors[1][idx] = *component as f32 / 255.0;
}
}
pub fn applied(&mut self) -> Option<(usize, chirp::Quirks, [u8; 4], [u8; 4])> {
let (fg, bg) = (self.colors[0], self.colors[1]);
let fg = [
(fg[0] * 255.0) as u8,
(fg[1] * 255.0) as u8,
(fg[2] * 255.0) as u8,
(fg[3] * 255.0) as u8,
];
let bg = [
(bg[0] * 255.0) as u8,
(bg[1] * 255.0) as u8,
(bg[2] * 255.0) as u8,
(bg[3] * 255.0) as u8,
];
self.applied
.then_some((self.target_ipf, self.quirks, fg, bg))
}
}