Skip to content

Commit

Permalink
gui-emulator-cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
sevonj committed Mar 21, 2024
1 parent a19128b commit 4352846
Show file tree
Hide file tree
Showing 11 changed files with 351 additions and 364 deletions.
4 changes: 4 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub struct Config {
pub cpuview_visible: bool,
pub cpuview_regs_base: Radix,

// --- Legacy Terminal
pub legacyterm_visible: bool,
}

impl Default for Config {
Expand All @@ -60,6 +62,8 @@ impl Default for Config {

cpuview_visible: false,
cpuview_regs_base: Default::default(),

legacyterm_visible: false,
}
}
}
61 changes: 56 additions & 5 deletions src/gui.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use std::sync::mpsc::Sender;
use eframe::emath::format_with_decimals_in_range;
use eframe::epaint::FontId;
use crate::{emulator::emu_debug::CtrlMSG, TitoApp};
use serde;

pub mod gui_editor;
pub mod gui_emulator;
pub(crate) mod memoryview;
pub(crate) mod cpuview;
pub(crate) mod graphicsview;
pub(crate) mod legacytermview;
mod emutoolbar;

use egui::{Align, Button, Color32, DragValue, Layout, Modifiers, OpenUrl, RichText};
use egui::{Align, Button, Color32, Context, DragValue, Frame, Layout, Modifiers, OpenUrl, RichText, TopBottomPanel, Ui};
use crate::config::Config;

#[derive(PartialEq)]
Expand Down Expand Up @@ -44,7 +50,10 @@ impl Radix {
const URL_GITHUB: &str = "https://github.com/sevonj/titomachine/";
const URL_GUIDE: &str = "https://sevonj.github.io/titouserdoc/";
const URL_OLDREF: &str = "https://www.cs.helsinki.fi/group/titokone/ttk91_ref_fi.html";

const FONT_TBL: FontId = FontId::monospace(12.0);
const FONT_TBLH: FontId = FontId::proportional(12.5);
const COL_TEXT: Color32 = Color32::DARK_GRAY;
const COL_TEXT_HI: Color32 = Color32::WHITE;
pub const SHORTCUT_NEW: egui::KeyboardShortcut =
egui::KeyboardShortcut::new(Modifiers::COMMAND, egui::Key::N);
pub const SHORTCUT_OPEN: egui::KeyboardShortcut =
Expand Down Expand Up @@ -104,7 +113,7 @@ impl TitoApp {
ui.separator();
// Context toolbar
match self.guimode == GuiMode::Emulator {
true => self.emulator_toolbar(ctx, ui),
true => self.emulator_toolbar(ui),
false => self.editor_toolbar(ctx, ui),
}
});
Expand Down Expand Up @@ -333,11 +342,53 @@ impl TitoApp {
}
}
}
pub fn emulator_panel(&mut self, ctx: &Context, _: &mut Ui) {
// Refresh cached regs and memory
let _ = self.tx_ctrl.send(CtrlMSG::GetState);
let _ = self.tx_ctrl.send(CtrlMSG::GetMem(self.memoryview.get_view_cache_range()));

egui::CentralPanel::default().show(ctx, |_| {

// Status Panel
egui::SidePanel::right("register_panel")
.frame(Frame::none())
.resizable(false)
// Limit max width when base isn't binary, because auto shrink doesn't work properly
// when separators and some other things are present.
.max_width(if self.config.cpuview_regs_base == Radix::Bin { 500.0 } else { 120.0 })
.show(ctx, |ui| {
TopBottomPanel::top("status")
.resizable(false)
.show_inside(ui, |ui| {
ui.label("Achieved speed:");
ui.label(format_with_decimals_in_range(self.emu_achieved_speed as f64, 1..=1) + "%");
});
self.cpuview.ui(ui, &mut self.config, &self.tx_ctrl);
});

// IO Panel
egui::SidePanel::right("io_panel")
.frame(Frame::none())
.resizable(false)
.max_width(128.0)
.show(ctx, |ui| {
self.legacytermview.ui(ui, &mut self.config, &self.tx_ctrl);
});

// Main Panel
egui::CentralPanel::default()
.frame(Frame::none())
.show(ctx, |ui| {
self.graphicsview.ui(ui, &mut self.config, &self.tx_ctrl);
self.memoryview.ui(ui, &mut self.config, &self.tx_ctrl);
});
});
}
}


/// Trait for emulator GUI panels
pub trait EmulatorPanel {
/// Args are references to ui, persistent settings struct, and emulator control message sender.
fn ui(&mut self, ui: &mut egui::Ui, config: &mut Config, sender: &Sender<CtrlMSG>);
}
}
101 changes: 45 additions & 56 deletions src/gui/gui_emulator/cpuview.rs → src/gui/cpuview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,15 @@
//! This module contains the CPU View Panel
//!

use std::{default::Default, ops::Range};
use std::collections::{HashMap, HashSet};
use std::sync::mpsc::Sender;
use egui::{CentralPanel, Color32, Frame, Image, include_image, RichText, ScrollArea, Sense, SidePanel, Slider, TopBottomPanel, Ui, scroll_area::ScrollBarVisibility, TextBuffer};
use egui_extras::{Column, TableBody, TableBuilder, TableRow};
use libttktk::disassembler::disassemble_instruction;
use num_traits::ToPrimitive;
use egui::{Button, RichText, TopBottomPanel, Ui};
use egui_extras::{Column, TableBody, TableBuilder};
use crate::config::Config;
use crate::emulator::emu_debug::CtrlMSG;
use crate::gui::{Radix, EmulatorPanel};
use crate::gui::gui_emulator::{COL_TEXT, COL_TEXT_HI, FONT_TBL, FONT_TBLH};
use crate::gui::FONT_TBL;

/// CPUView is the UI component responsible for the memory viewer panel.
/// CPUView is the GUI panel for registers.
pub(crate) struct CPUView {
pub cpu_halt: bool,
pub cpu_cu_pc: i32,
Expand Down Expand Up @@ -101,65 +97,58 @@ impl CPUView {
});
});
}

/// Table Shortcut: Header column
fn add_table_heading(&self, header: &mut TableRow, title: &str) {
header.col(|ui| {
ui.heading(RichText::new(title).font(FONT_TBLH.clone()));
});
}
}

impl EmulatorPanel for CPUView {
fn ui(&mut self, ui: &mut Ui, config: &mut Config, sender: &Sender<CtrlMSG>) {
fn ui(&mut self, ui: &mut Ui, config: &mut Config, _sender: &Sender<CtrlMSG>) {

// Memview titlebar

ui.horizontal(|ui| {
match config.cpuview_visible {
true => if ui.selectable_label(config.cpuview_visible, "⏷ CPU").clicked() {
config.cpuview_visible = false
}
false => if ui.selectable_label(config.cpuview_visible, "⏵ CPU").clicked() {
config.cpuview_visible = true
}
};
if !config.cpuview_visible {
return;
}
ui.menu_button("Show as", |ui| {
if ui.radio_value(&mut config.cpuview_regs_base, Radix::Bin, "Binary").clicked() { ui.close_menu(); };
if ui.radio_value(&mut config.cpuview_regs_base, Radix::Dec, "Decimal").clicked() { ui.close_menu(); };
if ui.radio_value(&mut config.cpuview_regs_base, Radix::Hex, "Hex").clicked() { ui.close_menu(); };
// CPUView titlebar
TopBottomPanel::top("cpuview_titlebar")
.resizable(false)
.show_inside(ui, |ui| {
ui.horizontal(|ui| {
let toggle_text = if config.cpuview_visible { "⏷ CPU" } else { "⏵ CPU" };
if ui.add(Button::new(toggle_text).frame(false)).clicked(){
config.cpuview_visible = !config.cpuview_visible;
}
if !config.cpuview_visible {
return;
}
ui.menu_button("Options", |ui| {
ui.label("Display registers as");
if ui.radio_value(&mut config.cpuview_regs_base, Radix::Bin, "Binary").clicked() { ui.close_menu(); };
if ui.radio_value(&mut config.cpuview_regs_base, Radix::Dec, "Decimal").clicked() { ui.close_menu(); };
if ui.radio_value(&mut config.cpuview_regs_base, Radix::Hex, "Hex").clicked() { ui.close_menu(); };
});
});
});
});

ui.separator();

if !config.cpuview_visible {
return;
}

// Memview main panel
TableBuilder::new(ui)
// CPUView main panel
TopBottomPanel::top("cpuview_main")
.resizable(false)
.striped(true)
.vscroll(false)
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
.column(Column::auto().at_least(106.0))
.body(|mut body| {
self.add_row_pc(&mut body, config);
self.add_row_gpr(&mut body, config, "R0", self.cpu_gpr_r0);
self.add_row_gpr(&mut body, config, "R1", self.cpu_gpr_r1);
self.add_row_gpr(&mut body, config, "R2", self.cpu_gpr_r2);
self.add_row_gpr(&mut body, config, "R3", self.cpu_gpr_r3);
self.add_row_gpr(&mut body, config, "R4", self.cpu_gpr_r4);
self.add_row_gpr(&mut body, config, "R5", self.cpu_gpr_r5);
self.add_row_gpr(&mut body, config, "SP", self.cpu_gpr_sp);
self.add_row_gpr(&mut body, config, "FP", self.cpu_gpr_fp);
self.add_row_sr(&mut body);
.show_inside(ui, |ui| {
TableBuilder::new(ui)
.resizable(false)
.striped(true)
.vscroll(false)
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
.column(Column::auto().at_least(106.0))
.body(|mut body| {
self.add_row_pc(&mut body, config);
self.add_row_gpr(&mut body, config, "R0", self.cpu_gpr_r0);
self.add_row_gpr(&mut body, config, "R1", self.cpu_gpr_r1);
self.add_row_gpr(&mut body, config, "R2", self.cpu_gpr_r2);
self.add_row_gpr(&mut body, config, "R3", self.cpu_gpr_r3);
self.add_row_gpr(&mut body, config, "R4", self.cpu_gpr_r4);
self.add_row_gpr(&mut body, config, "R5", self.cpu_gpr_r5);
self.add_row_gpr(&mut body, config, "SP", self.cpu_gpr_sp);
self.add_row_gpr(&mut body, config, "FP", self.cpu_gpr_fp);
self.add_row_sr(&mut body);
});
});

ui.separator();
}
}
64 changes: 64 additions & 0 deletions src/gui/emutoolbar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-FileCopyrightText: 2024 sevonj
//
// SPDX-License-Identifier: MPL-2.0

//!
//!

use eframe::epaint::Color32;
use egui::{Button, RichText, Ui};
use crate::emulator::emu_debug::CtrlMSG;
use crate::TitoApp;

impl TitoApp {
pub fn emulator_toolbar(&mut self, ui: &mut Ui) {
// Power button
let text_onoff = match self.emu_running {
true => RichText::new("⏼on/off").color(Color32::WHITE),
false => RichText::new("⏼on/off"),
};
if ui.selectable_label(self.emu_running, text_onoff).clicked() {
self.emu_playing = false;
let _ = self.tx_ctrl.send(CtrlMSG::PlaybackPlayPause(false));
if self.emu_running {
self.stop_emulation();
} else {
self.emu_running = true;
let _ = self.tx_ctrl.send(CtrlMSG::EnableBreakpoints(self.config.memview_breakpoints_enabled));
let _ = self.tx_ctrl.send(CtrlMSG::PlaybackStart);
}
}

ui.add_enabled_ui(self.emu_running, |ui| {
// PlayPause Button
let text_play;
match self.emu_playing {
true => text_play = RichText::new("⏸").color(Color32::WHITE),
false => text_play = RichText::new("▶"),
}
if ui.add(Button::new(text_play).min_size(egui::vec2(24.0, 0.0))).clicked() {
self.emu_playing = !self.emu_playing;
let _ = self.tx_ctrl
.send(CtrlMSG::PlaybackPlayPause(self.emu_playing));
}
// Step Button
ui.add_enabled_ui(!self.emu_playing, |ui| {
if ui.add(Button::new(RichText::new("|▶")).min_size(egui::vec2(24.0, 0.0))).clicked() {
let _ = self.tx_ctrl.send(CtrlMSG::PlaybackTick);
if self.config.memview_follow_pc {
self.memoryview.jump_to_pc();
}
}
})
});

ui.separator();

if ui.button("Reset").clicked() {
let _ = self.tx_ctrl.send(CtrlMSG::Reset());
self.legacytermview.clear();
self.graphicsview.clear();
}
ui.separator();
}
}
17 changes: 6 additions & 11 deletions src/gui/gui_emulator/graphicsview.rs → src/gui/graphicsview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
//! This module houses the Graphics Display Panel
//!

use std::default::Default;
use std::sync::mpsc::{Receiver, Sender};
use egui::{TopBottomPanel, Ui, Layout};
use egui::{TopBottomPanel, Ui, Layout, Button};
use egui_extras::RetainedImage;
use image::{ImageBuffer, Rgba};
use num_traits::clamp;
Expand Down Expand Up @@ -47,22 +46,18 @@ impl GraphicsView {
}

impl EmulatorPanel for GraphicsView {
fn ui(&mut self, ui: &mut Ui, config: &mut Config, sender: &Sender<CtrlMSG>) {
fn ui(&mut self, ui: &mut Ui, config: &mut Config, _sender: &Sender<CtrlMSG>) {
self.update();

// Graphics titlebar
TopBottomPanel::top("graphics_titlebar")
.resizable(false)
.show_inside(ui, |ui| {
ui.horizontal(|ui| {
match config.display_visible {
true => if ui.selectable_label(config.display_visible, "⏷ Graphics").clicked() {
config.display_visible = false
}
false => if ui.selectable_label(config.display_visible, "⏵ Graphics").clicked() {
config.display_visible = true
}
};
let toggle_text = if config.display_visible { "⏷ Graphics" } else { "⏵ Graphics" };
if ui.add(Button::new(toggle_text).frame(false)).clicked(){
config.display_visible = !config.display_visible;
}
if !config.display_visible {
return;
}/*
Expand Down
Loading

0 comments on commit 4352846

Please sign in to comment.