mod.rs moment

This commit is contained in:
2026-07-30 23:55:05 +01:00
parent fd3fed5143
commit a5190b69c6
5 changed files with 126 additions and 81 deletions
+11 -18
View File
@@ -28,30 +28,26 @@ impl Controller {
.show(ui, |ui| {
ui.horizontal(|ui| {
use RunningState::*;
let status = self.emulator.status();
let padding = Vec2::new(14.0, 8.0);
match status {
RunningState::Paused | RunningState::Breakpoint(_) => {
Paused | Breakpoint(_) =>
if PaddedWidget::button("▶ Run").color(Color32::GREEN).ui(ui).clicked() {
self.emulator.request_resume()
}
},
RunningState::Running | RunningState::Halted => {
Running | Halted =>
if PaddedWidget::button("⏸ Pause").color(Color32::YELLOW).ui(ui).clicked() {
self.emulator.request_pause()
}
}
RunningState::Shutdown => {
Shutdown => {
ui.add_enabled_ui(false, |ui| {
PaddedWidget::button("▶ Run").color(Color32::GREEN).ui(ui);
});
}
}
if PaddedWidget::indicator(status).ui(ui).clicked() {}
PaddedWidget::indicator(status).ui(ui);
if PaddedWidget::button("⟳ Reset All").color(Color32::ORANGE).ui(ui).clicked() {
self.emulator.when_paused(|emu| emu.reset());
@@ -83,19 +79,16 @@ impl Controller {
ui.separator();
let pcx = self.emulator.get_register(Register::Pcx);
let clock = self.emulator.clock();
let time = self.emulator.time().as_micros();
let mips = if time != 0 {
clock as u128 / time
} else {
0
};
PaddedWidget::label(format!("Clock: {clock}")).ui(ui);
let pcx = self.emulator.get_register(Register::Pcx);
PaddedWidget::label( format!("Pcx: 0x{pcx:08X}")).ui(ui);
let time = self.emulator.time().as_micros();
PaddedWidget::label( format!("Elapsed: {} micros", time)).ui(ui);
let mips = (clock as u128).checked_div(time).unwrap_or(0);
PaddedWidget::label(format!("Freq: {}MHz", mips)).ui(ui);
});
});
+3 -1
View File
@@ -85,6 +85,7 @@ pub struct DamnSimpleUI {
tools: Vec<PanelFactory>,
show_process_manager: bool,
process_manager: ProcessManager
}
@@ -119,7 +120,7 @@ impl eframe::App for DamnSimpleUI {
// TODO: File Explorer!
});
Panel::bottom("bottom_panel").resizable(true).show(ui, |ui| {
Panel::bottom("bottom_panel").resizable(true).show_collapsible(ui, &mut self.show_process_manager,|ui| {
self.process_manager.ui(ui);
});
@@ -184,6 +185,7 @@ impl DamnSimpleUI {
})
],
emulator,
show_process_manager: true,
process_manager: ProcessManager::new()
}
}
@@ -1,17 +1,21 @@
use crate::ui::Action;
use crate::ui::panels::TilePane;
use common::process::{ProcessAgent, TraceableProcess};
use egui::{Key, Ui};
use egui_code_editor::CodeEditor;
use egui::{Color32, Key, Ui, Widget};
use egui_code_editor::{CodeEditor, Completer, Syntax};
use egui_tiles::TileId;
use std::any::Any;
use std::fs::File;
use std::io::Error;
use std::path::{Path, PathBuf};
use std::thread;
use std::time::Duration;
use assembler::prelude::Assembler;
use common::formats::binary_dse::DseExecutable;
use theme::THEME;
use crate::ui::DataSource::Data;
use crate::ui::panels::editor::syntax::SyntaxFrom;
use crate::ui::ui_helpers::PaddedWidget;
mod syntax;
mod theme;
@@ -20,6 +24,8 @@ pub struct Editor {
buffer: String,
filename: Option<PathBuf>,
editor: CodeEditor,
syntax: Syntax,
completer: Completer,
}
impl Default for Editor {
@@ -28,15 +34,22 @@ impl Default for Editor {
buffer: String::new(),
filename: None,
editor: CodeEditor::default().with_fontsize(12.0).with_theme(THEME).with_numlines(true),
syntax: Syntax::default(),
completer: Completer::default().with_auto_indent().with_user_words(),
}
}
}
impl Editor {
pub fn new_open(path: &Path) -> Self {
let syntax = Syntax::from_file(path).unwrap_or(syntax::dsa());
Self {
buffer: std::fs::read_to_string(path).unwrap(),
filename: Some(path.to_path_buf()),
syntax: syntax.clone(),
completer: Completer::new_with_syntax(&syntax)
.with_auto_indent()
.with_user_words(),
..Default::default()
}
}
@@ -52,6 +65,21 @@ impl Editor {
pub fn get_buffer(&mut self) -> &mut String {
&mut self.buffer
}
pub fn build_cmd(&self, filename: PathBuf, on_complete: impl FnOnce(DseExecutable) -> Action + Send + 'static) -> Action {
Action::SpawnProcess(Box::new(move |pm| {
let builder = Assembler::new(filename);
pm.spawn(
builder.label(),
builder,
move |result| match result {
Ok(bin) => on_complete(bin),
Err(e) => Action::ShowError(e.to_string()),
}
);
}))
}
}
impl TilePane for Editor {
@@ -62,56 +90,62 @@ impl TilePane for Editor {
}
fn ui(&mut self, ui: &mut Ui, tile_id: TileId) -> Option<Action> {
let mut action = Action::None;
let response = egui::Panel::top("panel").show(ui, |ui| {
let mut action = None;
egui::Panel::top("panel").show(ui, |ui| {
ui.horizontal(|ui| {
if let Some(filename) = self.filename.as_ref() {
ui.label(filename.display().to_string());
} else {
ui.label("New File*");
}
if PaddedWidget::button("Build & Load").ui(ui).clicked() {
let Some(filename) = self.filename.clone() else {
action = Action::ShowError("Error - no filename set".to_string());
return;
};
if ui.button("Build").clicked() {
let Some(filename) = self.filename.clone() else {
println!("error!");
return None;
};
action = Some(Action::SpawnProcess(Box::new(move |pm| {
pm.spawn(
"Assembler",
Assembler::new(filename),
move |result| {
return if let Ok(bin) = result {
Action::LoadBinary(Data(bin.to_memory_image()))
} else {
Action::None
}
action = self.build_cmd(
filename, |res| {
Action::LoadBinary(Data(res.to_memory_image()))
}
);
})));
};
}
action
if PaddedWidget::button("Build").ui(ui).clicked() {
let Some(filename) = self.filename.clone() else {
action = Action::ShowError("Error - no filename set".to_string());
return;
};
action = self.build_cmd(
filename.clone(), move |res| {
let filename = filename.with_extension("dsb");
let mut writer = File::create(&filename).unwrap();
res.write(&mut writer).unwrap();
Action::OpenFile(filename)
}
);
}
PaddedWidget::label(
self.filename
.as_ref()
.map(|f| f.display().to_string())
.unwrap_or_else(|| String::from("New File"))
).color(Color32::DARK_GRAY).ui(ui);
});
});
if let Some(action) = response.inner {
return Some(action);
}
self.editor.show(ui, &mut self.buffer, &syntax::dsa());
self.editor.show_with_completer(ui, &mut self.buffer, &self.syntax, &mut self.completer);
if ui.input(|i| i.key_pressed(Key::S) && i.modifiers.ctrl) {
return if let Some(filename) = self.filename.clone() {
Some(Action::SaveFile(filename, tile_id))
action = if let Some(filename) = self.filename.clone() {
Action::SaveFile(filename, tile_id)
} else {
Some(Action::RequestSaveAs(tile_id))
Action::RequestSaveAs(tile_id)
}
};
None
Some(action)
}
fn as_any_mut(&mut self) -> &mut dyn Any { self }
@@ -1,6 +1,21 @@
use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
use egui_code_editor::{Patch, Syntax};
pub trait SyntaxFrom {
fn from_file(f: &Path) -> Option<Syntax>;
}
impl SyntaxFrom for Syntax {
fn from_file(f: &Path) -> Option<Syntax> {
match f.extension()?.to_str()? {
"dsa" => Some(dsa()),
"dsc" => Some(dsc()),
_ => None,
}
}
}
pub fn dsa() -> Syntax {
Syntax {
word_start: BTreeSet::new(),
+24 -23
View File
@@ -9,8 +9,8 @@ pub mod registers;
pub mod serial;
use std::any::Any;
use eframe::epaint::Color32;
use egui::{Id, Response, Sense, TextStyle, Ui, WidgetInfo, WidgetType};
use eframe::epaint::{Color32, CornerRadius};
use egui::{Id, Response, Sense, Stroke, TextStyle, Ui, WidgetInfo, WidgetType};
use egui_tiles::{Behavior, Container, SimplificationOptions, TabState, Tile, TileId, Tiles, Tree, UiResponse};
use crate::ui::Action;
use crate::ui::Action::RequestCloseTab;
@@ -56,8 +56,9 @@ impl Behavior<Pane> for TileBehavior {
pane: &mut Box<dyn TilePane>,
) -> UiResponse {
egui::Frame::new()
.corner_radius(CornerRadius::same(4))
.inner_margin(egui::Margin::same(10))
.stroke(ui.visuals().widgets.active.bg_stroke)
.stroke(Stroke::new(2.0, Color32::DARK_GRAY))
.show(ui, |ui| {
if let Some(action) = pane.ui(ui, tile_id) {
self.pending_action = Some(action);
@@ -67,26 +68,6 @@ impl Behavior<Pane> for TileBehavior {
UiResponse::None
}
fn tab_ui(
&mut self,
tiles: &mut Tiles<Pane>,
ui: &mut Ui,
id: Id,
tile_id: TileId,
state: &TabState,
) -> Response {
let title = self.tab_title_for_tile(tiles, tile_id);
let draggable = self.is_tile_draggable(tiles, tile_id);
let tab = painted_tab(ui, id, title, state.active, state.closable, draggable);
if tab.close_clicked && self.on_tab_close(tiles, tile_id) {
tiles.remove(tile_id);
}
self.on_tab_button(tiles, tile_id, tab.response)
}
fn tab_title_for_pane(&mut self, pane: &Pane) -> egui::WidgetText {
pane.title()
}
@@ -109,6 +90,26 @@ impl Behavior<Pane> for TileBehavior {
true
}
fn tab_ui(
&mut self,
tiles: &mut Tiles<Pane>,
ui: &mut Ui,
id: Id,
tile_id: TileId,
state: &TabState,
) -> Response {
let title = self.tab_title_for_tile(tiles, tile_id);
let draggable = self.is_tile_draggable(tiles, tile_id);
let tab = painted_tab(ui, id, title, state.active, state.closable, draggable);
if tab.close_clicked && self.on_tab_close(tiles, tile_id) {
tiles.remove(tile_id);
}
self.on_tab_button(tiles, tile_id, tab.response)
}
fn tab_bar_height(&self, _style: &egui::Style) -> f32 {
36.0 // taller tab row = more vertical padding around the label
}