Split UI drawing code out of main update code

This commit is contained in:
pjht 2024-01-30 13:01:02 -06:00
parent 51e0893c04
commit 3862080cb1
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A
4 changed files with 187 additions and 152 deletions

View File

@ -216,7 +216,7 @@ impl AudioThread {
}; };
} }
}, },
AudioMessage::SetVolume(vol) => self.sl.set_global_volume(*vol / 100.0) AudioMessage::SetVolume(vol) => self.sl.set_global_volume(*vol / 100.0),
} }
} }

View File

@ -1,7 +1,7 @@
use std::path::Path; use std::path::Path;
use eframe::{ use eframe::{
egui::{self, KeyboardShortcut, Modifiers, Sense, TextureOptions, Ui, Widget, Key}, egui::{self, Key, KeyboardShortcut, Modifiers, Sense, TextureOptions, Ui, Widget},
epaint::{vec2, Pos2, Rect, TextureHandle}, epaint::{vec2, Pos2, Rect, TextureHandle},
}; };
@ -117,10 +117,7 @@ impl Widget for &mut Frontpanel<'_> {
); );
let led_textures = let led_textures =
led::Textures::new(self.textures.led_on.clone(), self.textures.led_off.clone()); led::Textures::new(self.textures.led_on.clone(), self.textures.led_off.clone());
let resp = ui.allocate_response( let resp = ui.allocate_response(vec2(800.0, 333.0), Sense::click());
vec2(800.0, 333.0),
Sense::click(),
);
resp.request_focus(); resp.request_focus();
let fp_rect = resp.rect; let fp_rect = resp.rect;
ui.allocate_ui_at_rect(fp_rect, |ui| { ui.allocate_ui_at_rect(fp_rect, |ui| {
@ -176,7 +173,11 @@ impl Widget for &mut Frontpanel<'_> {
}; };
let shortcut = KeyboardShortcut::new(mods, key); let shortcut = KeyboardShortcut::new(mods, key);
if ui if ui
.add(switch::ToggleSwitch::new(&mut sw_state, &sw_textures, Some(shortcut))) .add(switch::ToggleSwitch::new(
&mut sw_state,
&sw_textures,
Some(shortcut),
))
.changed() .changed()
{ {
self.state.ad_sws = self.state.ad_sws =
@ -207,7 +208,12 @@ impl Widget for &mut Frontpanel<'_> {
let up_shortcut = KeyboardShortcut::new(Modifiers::NONE, up_key); let up_shortcut = KeyboardShortcut::new(Modifiers::NONE, up_key);
let down_shortcut = KeyboardShortcut::new(Modifiers::NONE, down_key); let down_shortcut = KeyboardShortcut::new(Modifiers::NONE, down_key);
if ui if ui
.add(switch::ThreePosSwitch::new(state, &sw_textures, Some(up_shortcut), Some(down_shortcut))) .add(switch::ThreePosSwitch::new(
state,
&sw_textures,
Some(up_shortcut),
Some(down_shortcut),
))
.changed() .changed()
{ {
let sw = match i { let sw = match i {

View File

@ -59,8 +59,18 @@ pub struct ThreePosSwitch<'a> {
} }
impl<'a> ThreePosSwitch<'a> { impl<'a> ThreePosSwitch<'a> {
pub fn new(state: &'a mut SwitchState, textures: &'a Textures, up_shortcut: Option<KeyboardShortcut>, down_shortcut: Option<KeyboardShortcut>) -> Self { pub fn new(
Self { state, textures, up_shortcut, down_shortcut } state: &'a mut SwitchState,
textures: &'a Textures,
up_shortcut: Option<KeyboardShortcut>,
down_shortcut: Option<KeyboardShortcut>,
) -> Self {
Self {
state,
textures,
up_shortcut,
down_shortcut,
}
} }
} }
@ -74,16 +84,24 @@ impl Widget for ThreePosSwitch<'_> {
NULL_TINT, NULL_TINT,
); );
let up_shortcut_pressed = self.up_shortcut.map_or(false, |shortcut| { let up_shortcut_pressed = self.up_shortcut.map_or(false, |shortcut| {
ui.input_mut(|input| input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers) ui.input_mut(|input| {
input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers
})
}); });
let down_shortcut_pressed = self.down_shortcut.map_or(false, |shortcut| { let down_shortcut_pressed = self.down_shortcut.map_or(false, |shortcut| {
ui.input_mut(|input| input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers) ui.input_mut(|input| {
input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers
})
}); });
let up_shortcut_released = self.up_shortcut.map_or(false, |shortcut| { let up_shortcut_released = self.up_shortcut.map_or(false, |shortcut| {
ui.input_mut(|input| input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers) ui.input_mut(|input| {
input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers
})
}); });
let down_shortcut_released = self.down_shortcut.map_or(false, |shortcut| { let down_shortcut_released = self.down_shortcut.map_or(false, |shortcut| {
ui.input_mut(|input| input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers) ui.input_mut(|input| {
input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers
})
}); });
let old_state = *self.state; let old_state = *self.state;
if resp.dragged() { if resp.dragged() {
@ -101,7 +119,10 @@ impl Widget for ThreePosSwitch<'_> {
} else if resp.drag_released() || up_shortcut_released || down_shortcut_released { } else if resp.drag_released() || up_shortcut_released || down_shortcut_released {
*self.state = SwitchState::Neut; *self.state = SwitchState::Neut;
} }
if *self.state != SwitchState::Neut && !resp.dragged() && ui.input(|input| input.keys_down.is_empty()) { if *self.state != SwitchState::Neut
&& !resp.dragged()
&& ui.input(|input| input.keys_down.is_empty())
{
*self.state = SwitchState::Neut; *self.state = SwitchState::Neut;
} }
if *self.state != old_state { if *self.state != old_state {

View File

@ -9,7 +9,7 @@ use std::sync::mpsc::Sender;
use audio::{AudioMessage, AudioThread}; use audio::{AudioMessage, AudioThread};
use cpu::{MemCycle, Status, I8080}; use cpu::{MemCycle, Status, I8080};
use eframe::{ use eframe::{
egui::{self, menu, Button, Slider}, egui::{self, menu, Button, Slider, Ui},
NativeOptions, NativeOptions,
}; };
use egui_modal::Modal; use egui_modal::Modal;
@ -66,14 +66,20 @@ struct AltairEmulator {
impl AltairEmulator { impl AltairEmulator {
fn new(cc: &eframe::CreationContext<'_>, audio_tx: Sender<AudioMessage>) -> Self { fn new(cc: &eframe::CreationContext<'_>, audio_tx: Sender<AudioMessage>) -> Self {
let options = if cc.storage.unwrap().get_string("options").is_none() { let options = if cc.storage.unwrap().get_string("options").is_none() {
Options { mute: false, fan_enabled: true, volume: 1.0 } Options {
mute: false,
fan_enabled: true,
volume: 1.0,
}
} else { } else {
eframe::get_value(cc.storage.unwrap(), "options").unwrap() eframe::get_value(cc.storage.unwrap(), "options").unwrap()
}; };
if options.mute { if options.mute {
audio_tx.send(AudioMessage::SetVolume(0.0)).unwrap(); audio_tx.send(AudioMessage::SetVolume(0.0)).unwrap();
} else { } else {
audio_tx.send(AudioMessage::SetVolume(options.volume)).unwrap(); audio_tx
.send(AudioMessage::SetVolume(options.volume))
.unwrap();
} }
let mut mem = [0; 65536]; let mut mem = [0; 65536];
let cpu = I8080::new(); let cpu = I8080::new();
@ -163,25 +169,15 @@ impl AltairEmulator {
self.cpu.finish_m_cycle(data); self.cpu.finish_m_cycle(data);
self.update_fp(); self.update_fp();
} }
}
impl eframe::App for AltairEmulator { fn show_menubar(&mut self, ui: &mut Ui) {
fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, "options", &self.options);
}
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
ctx.set_pixels_per_point(1.0);
// frame.set_window_size((800.0, 333.0).into());
let mut disable_fp_sws = self.option_window.is_some();
egui::TopBottomPanel::top("menu").show(ctx, |ui| {
menu::bar(ui, |ui| { menu::bar(ui, |ui| {
menu::menu_button(ui, "Edit", |ui| { menu::menu_button(ui, "Edit", |ui| {
disable_fp_sws = true;
if ui if ui
.add_enabled(self.option_window.is_none(), Button::new("Options")) .add_enabled(self.option_window.is_none(), Button::new("Options"))
.clicked() .clicked()
{ {
self.option_window = Some(OptionWindow::new(ctx, self.options)); self.option_window = Some(OptionWindow::new(ui.ctx(), self.options));
ui.close_menu(); ui.close_menu();
} }
if ui.button("Load binary file").clicked() { if ui.button("Load binary file").clicked() {
@ -194,9 +190,10 @@ impl eframe::App for AltairEmulator {
.add_filter("All files", &["*"]) .add_filter("All files", &["*"])
.pick_file(); .pick_file();
if let Some(file) = file { if let Some(file) = file {
if file.extension().map_or(false, |ext| { if file
ihex_exts.contains(&ext.to_str().unwrap_or("")) .extension()
}) { .map_or(false, |ext| ihex_exts.contains(&ext.to_str().unwrap_or("")))
{
let data = std::fs::read_to_string(file).unwrap(); let data = std::fs::read_to_string(file).unwrap();
for record in ihex::Reader::new(&data) { for record in ihex::Reader::new(&data) {
let record = record.unwrap(); let record = record.unwrap();
@ -218,8 +215,9 @@ impl eframe::App for AltairEmulator {
} }
}); });
}); });
}); }
egui::CentralPanel::default().show(ctx, |ui| {
fn show_frontpanel(&mut self, ui: &mut Ui) {
let mut fp = Frontpanel::new(&self.textures, &mut self.fp_state); let mut fp = Frontpanel::new(&self.textures, &mut self.fp_state);
ui.add(&mut fp); ui.add(&mut fp);
let interaction = fp.interaction(); let interaction = fp.interaction();
@ -246,8 +244,7 @@ impl eframe::App for AltairEmulator {
// Assume M1 // Assume M1
self.cpu.finish_m_cycle(0xC3); // JMP self.cpu.finish_m_cycle(0xC3); // JMP
self.cpu.finish_m_cycle(self.fp_state.ad_sws() as u8); self.cpu.finish_m_cycle(self.fp_state.ad_sws() as u8);
self.cpu self.cpu.finish_m_cycle((self.fp_state.ad_sws() >> 8) as u8);
.finish_m_cycle((self.fp_state.ad_sws() >> 8) as u8);
self.update_fp(); self.update_fp();
} else if state == SwitchState::Down { } else if state == SwitchState::Down {
// Assume M1 // Assume M1
@ -297,11 +294,20 @@ impl eframe::App for AltairEmulator {
} }
} }
} }
}
}
impl eframe::App for AltairEmulator {
fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, "options", &self.options);
}
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
ctx.set_pixels_per_point(1.0);
egui::TopBottomPanel::top("menu").show(ctx, |ui| self.show_menubar(ui));
egui::CentralPanel::default().show(ctx, |ui| self.show_frontpanel(ui));
if self.running { if self.running {
self.run_cpu_cycle(); self.run_cpu_cycle();
} }
});
let old_fan_enabled = self.options.fan_enabled; let old_fan_enabled = self.options.fan_enabled;
if let Some(option_window) = self.option_window.as_mut() { if let Some(option_window) = self.option_window.as_mut() {
if option_window.draw(ctx, &mut self.options) { if option_window.draw(ctx, &mut self.options) {
@ -310,7 +316,9 @@ impl eframe::App for AltairEmulator {
if self.options.mute { if self.options.mute {
self.audio_tx.send(AudioMessage::SetVolume(0.0)).unwrap(); self.audio_tx.send(AudioMessage::SetVolume(0.0)).unwrap();
} else { } else {
self.audio_tx.send(AudioMessage::SetVolume(self.options.volume)).unwrap(); self.audio_tx
.send(AudioMessage::SetVolume(self.options.volume))
.unwrap();
} }
} }
if (old_fan_enabled != self.options.fan_enabled) && self.fp_state.power() { if (old_fan_enabled != self.options.fan_enabled) && self.fp_state.power() {