804 lines
31 KiB
Rust
804 lines
31 KiB
Rust
//! # GUI Components Module
|
|
//!
|
|
//! This module implements all the individual GUI components for the Intel MCS-4 emulator.
|
|
//! Each component is responsible for rendering its specific section of the interface
|
|
//! and handling user interactions within that section.
|
|
//!
|
|
//! ## Component Architecture
|
|
//!
|
|
//! The GUI is organized into several specialized components:
|
|
//!
|
|
//! - **`GuiComponents`**: Main container managing all components
|
|
//! - **`ControlPanel`**: System control buttons and actions
|
|
//! - **`MemoryViewer`**: RAM content display and inspection
|
|
//! - **`RegisterViewer`**: CPU register state visualization
|
|
//! - **`RomLoader`**: File dialog integration for ROM loading
|
|
//! - **`StatusBar`**: System status and component health display
|
|
//!
|
|
//! ## Design Principles
|
|
//!
|
|
//! ### Separation of Concerns
|
|
//! Each component handles only its specific functionality:
|
|
//! - State management is centralized in `GuiState`
|
|
//! - Components receive immutable references where possible
|
|
//! - User interactions trigger state changes through controlled interfaces
|
|
//!
|
|
//! ### Performance Optimization
|
|
//! - Components minimize allocations and cloning
|
|
//! - State updates are batched and efficient
|
|
//! - UI layout uses egui's immediate mode for optimal performance
|
|
//!
|
|
//! ### User Experience
|
|
//! - Consistent visual design across all components
|
|
//! - Clear visual feedback for user actions
|
|
//! - Intuitive layout and component organization
|
|
//!
|
|
//! ## Component Communication
|
|
//!
|
|
//! Components communicate through the shared `GuiState`:
|
|
//! - Read-only access to state for display components
|
|
//! - Controlled mutation through specific methods
|
|
//! - Thread-safe state sharing with the emulator system
|
|
//!
|
|
//! ## Error Handling
|
|
//!
|
|
//! Components handle errors gracefully:
|
|
//! - Invalid states are displayed to users
|
|
//! - Failed operations show clear error messages
|
|
//! - Recovery options are provided where applicable
|
|
|
|
use super::state::GuiState;
|
|
use eframe::egui;
|
|
|
|
/// Container for all GUI components
|
|
///
|
|
/// This structure manages the lifecycle and coordination of all GUI components.
|
|
/// It acts as a facade, providing a clean interface for rendering different
|
|
/// sections of the user interface while maintaining proper separation of concerns.
|
|
///
|
|
/// ## Component Management
|
|
///
|
|
/// The container is responsible for:
|
|
/// - Component initialization and configuration
|
|
/// - Render orchestration and layout management
|
|
/// - State distribution to appropriate components
|
|
/// - Component lifecycle and cleanup
|
|
///
|
|
/// ## Performance Considerations
|
|
///
|
|
/// - Components are created once and reused across frames
|
|
/// - State references are passed efficiently without cloning
|
|
/// - Layout is managed centrally for consistent spacing
|
|
pub struct GuiComponents {
|
|
/// System control and management interface
|
|
control_panel: ControlPanel,
|
|
/// RAM content inspection and visualization
|
|
memory_viewer: MemoryViewer,
|
|
/// CPU register state display
|
|
register_viewer: RegisterViewer,
|
|
/// ROM file loading and management
|
|
#[allow(dead_code)] // RomLoader is currently a placeholder implementation
|
|
rom_loader: RomLoader,
|
|
/// System status and health monitoring
|
|
status_bar: StatusBar,
|
|
}
|
|
|
|
impl GuiComponents {
|
|
/// Create a new GUI components container with all components initialized
|
|
///
|
|
/// This constructor sets up all GUI components with their default configurations.
|
|
/// Components are ready to use immediately after creation.
|
|
///
|
|
/// # Returns
|
|
/// A fully initialized `GuiComponents` instance
|
|
///
|
|
/// # Example
|
|
/// ```rust,no_run
|
|
/// use rusty_emu::gui::components::GuiComponents;
|
|
///
|
|
/// let mut components = GuiComponents::new();
|
|
/// // Components are ready to render
|
|
/// ```
|
|
pub fn new() -> Self {
|
|
Self {
|
|
control_panel: ControlPanel::new(),
|
|
memory_viewer: MemoryViewer::new(),
|
|
register_viewer: RegisterViewer::new(),
|
|
rom_loader: RomLoader::new(),
|
|
status_bar: StatusBar::new(),
|
|
}
|
|
}
|
|
|
|
/// Render the control panel component
|
|
///
|
|
/// The control panel provides system management functionality including
|
|
/// start/stop/reset controls and ROM loading capabilities.
|
|
///
|
|
/// # Arguments
|
|
/// * `ui` - egui UI context for rendering
|
|
/// * `state` - Mutable reference to GUI state for control operations
|
|
pub fn render_control_panel(&mut self, ui: &mut egui::Ui, state: &mut GuiState) {
|
|
self.control_panel.render(ui, state);
|
|
}
|
|
|
|
/// Render the memory viewer component
|
|
///
|
|
/// Displays RAM contents in a tabular format with bank selection
|
|
/// and hex/decimal viewing options.
|
|
///
|
|
/// # Arguments
|
|
/// * `ui` - egui UI context for rendering
|
|
/// * `state` - Immutable reference to GUI state for display
|
|
pub fn render_memory_viewer(&self, ui: &mut egui::Ui, state: &GuiState) {
|
|
self.memory_viewer.render(ui, state);
|
|
}
|
|
|
|
/// Render the register viewer component
|
|
///
|
|
/// Shows CPU register state including accumulator, program counter,
|
|
/// index registers, and system flags.
|
|
///
|
|
/// # Arguments
|
|
/// * `ui` - egui UI context for rendering
|
|
/// * `state` - Immutable reference to GUI state for display
|
|
pub fn render_register_viewer(&self, ui: &mut egui::Ui, state: &GuiState) {
|
|
self.register_viewer.render(ui, state);
|
|
}
|
|
|
|
/// Render the status bar component
|
|
///
|
|
/// Displays system health, component status, cycle counts,
|
|
/// and any error conditions.
|
|
///
|
|
/// # Arguments
|
|
/// * `ui` - egui UI context for rendering
|
|
/// * `state` - Immutable reference to GUI state for display
|
|
pub fn render_status_bar(&self, ui: &mut egui::Ui, state: &GuiState) {
|
|
self.status_bar.render(ui, state);
|
|
}
|
|
}
|
|
|
|
/// Control panel component for system control buttons and operations
|
|
///
|
|
/// The control panel provides the primary interface for managing the emulator system.
|
|
/// It offers intuitive controls for starting, stopping, and resetting the emulation,
|
|
/// along with system configuration and file management capabilities.
|
|
///
|
|
/// ## Features
|
|
///
|
|
/// - **System Lifecycle Management**: Start, stop, and reset emulator execution
|
|
/// - **Visual State Feedback**: Dynamic button states reflecting current system status
|
|
/// - **Error Handling**: Clear error display and recovery mechanisms
|
|
/// - **Application Control**: Window management and application termination
|
|
///
|
|
/// ## Button States
|
|
///
|
|
/// The control panel adapts its interface based on system state:
|
|
/// - **Stopped**: Shows "Start System" button, disabled stop/reset buttons
|
|
/// - **Running**: Shows "System Running..." text, enabled stop/reset buttons
|
|
/// - **Error**: Displays error messages with option to clear them
|
|
pub struct ControlPanel {
|
|
/// Dynamic text for the start/stop button based on system state
|
|
start_button_text: String,
|
|
/// Whether the stop button should be enabled
|
|
stop_button_enabled: bool,
|
|
/// Whether the reset button should be enabled
|
|
reset_button_enabled: bool,
|
|
}
|
|
|
|
impl ControlPanel {
|
|
/// Create a new control panel with default state
|
|
///
|
|
/// Initializes the control panel in the "stopped" state with appropriate
|
|
/// button configurations for a system that's ready to start.
|
|
///
|
|
/// # Returns
|
|
/// A new `ControlPanel` instance ready for system control
|
|
pub fn new() -> Self {
|
|
Self {
|
|
start_button_text: "Start System".to_string(),
|
|
stop_button_enabled: false,
|
|
reset_button_enabled: false,
|
|
}
|
|
}
|
|
|
|
/// Render the control panel interface
|
|
///
|
|
/// Creates a horizontal layout with all control buttons and handles
|
|
/// user interactions. The interface adapts dynamically based on system state.
|
|
///
|
|
/// # Arguments
|
|
/// * `ui` - egui UI context for rendering and interaction
|
|
/// * `state` - Mutable reference to GUI state for system control
|
|
///
|
|
/// # Layout
|
|
/// ```text
|
|
/// ┌─────────────────────────────────────────────────┐
|
|
/// │ System Control ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ │
|
|
/// │ [Load ROM] [Start System] [Stop] [Reset] [Close] │
|
|
/// └─────────────────────────────────────────────────┘
|
|
/// ```
|
|
pub fn render(&mut self, ui: &mut egui::Ui, state: &mut GuiState) {
|
|
ui.horizontal(|ui| {
|
|
// Section header
|
|
ui.heading("System Control");
|
|
|
|
// ROM loading button
|
|
if ui.button("Load ROM").clicked() {
|
|
// ROM loading will be handled by RomLoader component
|
|
state.set_error("ROM loader not yet implemented".to_string());
|
|
}
|
|
|
|
// Start/Stop system button (context-sensitive)
|
|
if ui.button(&self.start_button_text).clicked() {
|
|
if !state.system_running {
|
|
self.start_system(state);
|
|
}
|
|
}
|
|
|
|
// Stop system button (only enabled when running)
|
|
if ui.button("Stop System").clicked() && state.system_running {
|
|
self.stop_system(state);
|
|
}
|
|
|
|
// Reset system button
|
|
if ui.button("Reset System").clicked() {
|
|
self.reset_system(state);
|
|
}
|
|
|
|
// Application close button
|
|
if ui.button("Close").clicked() {
|
|
// Close application - handled by eframe
|
|
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
|
|
}
|
|
});
|
|
|
|
ui.separator();
|
|
}
|
|
|
|
/// Start the emulator system
|
|
///
|
|
/// Transitions the system from stopped to running state and updates
|
|
/// all related UI elements to reflect the new state.
|
|
///
|
|
/// # Arguments
|
|
/// * `state` - Mutable reference to GUI state
|
|
fn start_system(&mut self, state: &mut GuiState) {
|
|
state.system_running = true;
|
|
self.start_button_text = "System Running...".to_string();
|
|
self.stop_button_enabled = true;
|
|
self.reset_button_enabled = true;
|
|
state.clear_error();
|
|
}
|
|
|
|
/// Stop the emulator system
|
|
///
|
|
/// Transitions the system from running to stopped state and updates
|
|
/// UI elements accordingly.
|
|
///
|
|
/// # Arguments
|
|
/// * `state` - Mutable reference to GUI state
|
|
fn stop_system(&mut self, state: &mut GuiState) {
|
|
state.system_running = false;
|
|
self.start_button_text = "Start System".to_string();
|
|
self.stop_button_enabled = false;
|
|
state.clear_error();
|
|
}
|
|
|
|
/// Reset the emulator system
|
|
///
|
|
/// Performs a complete system reset, stopping execution and clearing
|
|
/// all state including cycle counts and error conditions.
|
|
///
|
|
/// # Arguments
|
|
/// * `state` - Mutable reference to GUI state
|
|
fn reset_system(&mut self, state: &mut GuiState) {
|
|
state.system_running = false;
|
|
state.cycle_count = 0;
|
|
self.start_button_text = "Start System".to_string();
|
|
self.stop_button_enabled = false;
|
|
self.reset_button_enabled = false;
|
|
state.clear_error();
|
|
}
|
|
}
|
|
|
|
/// Memory viewer component for displaying RAM contents and state
|
|
///
|
|
/// The memory viewer provides comprehensive RAM inspection capabilities,
|
|
/// allowing users to examine memory contents across different banks with
|
|
/// flexible display options and intuitive navigation.
|
|
///
|
|
/// ## Features
|
|
///
|
|
/// - **Multi-Bank Display**: View RAM contents across 4 banks simultaneously
|
|
/// - **Flexible Formatting**: Toggle between hexadecimal and decimal display
|
|
/// - **Interactive Bank Selection**: Choose which memory bank to inspect
|
|
/// - **Scrollable Interface**: Navigate through memory contents efficiently
|
|
/// - **Real-time Updates**: Live memory content updates during emulation
|
|
///
|
|
/// ## Display Format
|
|
///
|
|
/// The memory viewer shows data in a structured grid:
|
|
/// - **Address Column**: Memory addresses in hexadecimal format
|
|
/// - **Bank Columns**: B0-B3 showing contents of each memory bank
|
|
/// - **Value Display**: Configurable hex or decimal representation
|
|
///
|
|
/// ## Memory Organization
|
|
///
|
|
/// The Intel 4002 RAM has the following structure:
|
|
/// - **4 Banks**: Independent memory banks (B0-B3)
|
|
/// - **4 Bytes per Bank**: Addresses 0x00-0x03 in each bank
|
|
/// - **4-bit Values**: Each memory location stores a 4-bit nibble
|
|
pub struct MemoryViewer {
|
|
/// Display mode: true for hexadecimal, false for decimal
|
|
show_hex: bool,
|
|
/// Number of bytes to display per row (currently fixed at 16)
|
|
#[allow(dead_code)]
|
|
// bytes_per_row is currently fixed at 16 but kept for future flexibility
|
|
bytes_per_row: usize,
|
|
}
|
|
|
|
impl MemoryViewer {
|
|
/// Create a new memory viewer with default configuration
|
|
///
|
|
/// Initializes the viewer with hexadecimal display mode and standard
|
|
/// layout optimized for the Intel 4002 RAM structure.
|
|
///
|
|
/// # Returns
|
|
/// A new `MemoryViewer` instance ready for RAM content display
|
|
pub fn new() -> Self {
|
|
Self {
|
|
show_hex: true,
|
|
bytes_per_row: 16,
|
|
}
|
|
}
|
|
|
|
/// Render the memory viewer interface
|
|
///
|
|
/// Creates a comprehensive memory inspection interface with bank selection,
|
|
/// display options, and a scrollable memory contents grid.
|
|
///
|
|
/// # Arguments
|
|
/// * `ui` - egui UI context for rendering
|
|
/// * `state` - Immutable reference to GUI state containing memory data
|
|
///
|
|
/// # Layout Structure
|
|
/// ```text
|
|
/// ┌─────────────────────────────────────────────────┐
|
|
/// │ Memory Viewer [─] [□] │
|
|
/// │ Bank: [0] □ Hex View │
|
|
/// ├─────────────────────────────────────────────────┤
|
|
/// │ Address B0 B1 B2 B3 │
|
|
/// │ [00] [12] [34] [56] [78] │
|
|
/// │ [01] [9A] [BC] [DE] [F0] │
|
|
/// │ [02] [11] [22] [33] [44] │
|
|
/// │ [03] [55] [66] [77] [88] │
|
|
/// └─────────────────────────────────────────────────┘
|
|
/// ```
|
|
pub fn render(&self, ui: &mut egui::Ui, state: &GuiState) {
|
|
ui.vertical(|ui| {
|
|
// Section header
|
|
ui.heading("Memory Viewer");
|
|
|
|
// Control bar with bank selection and display options
|
|
ui.horizontal(|ui| {
|
|
ui.label("Bank:");
|
|
// Bank selector (0-3 for Intel 4002)
|
|
ui.add(
|
|
egui::DragValue::new(&mut state.memory_state.selected_bank.clone())
|
|
.clamp_range(0..=3),
|
|
);
|
|
ui.checkbox(&mut self.show_hex.clone(), "Hex View");
|
|
});
|
|
|
|
ui.separator();
|
|
|
|
// Memory contents in scrollable area
|
|
egui::ScrollArea::vertical().show(ui, |ui| {
|
|
egui::Grid::new("memory_grid").striped(true).show(ui, |ui| {
|
|
// Header row with bank labels
|
|
ui.label("Address");
|
|
for i in 0..4 {
|
|
ui.label(format!("B{}", i));
|
|
}
|
|
ui.end_row();
|
|
|
|
// Memory contents rows
|
|
for addr in 0..4 {
|
|
// Address column
|
|
ui.label(format!("{:02X}", addr));
|
|
|
|
// Bank data columns
|
|
for bank in 0..4 {
|
|
let value = state.memory_state.ram_contents[bank][addr];
|
|
if self.show_hex {
|
|
ui.label(format!("{:02X}", value));
|
|
} else {
|
|
ui.label(format!("{}", value));
|
|
}
|
|
}
|
|
ui.end_row();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
ui.separator();
|
|
}
|
|
}
|
|
|
|
/// Register viewer component for displaying CPU register state
|
|
///
|
|
/// The register viewer provides comprehensive CPU state visualization,
|
|
/// showing all key registers, flags, and pointers that define the current
|
|
/// execution state of the Intel 4004 microprocessor.
|
|
///
|
|
/// ## Features
|
|
///
|
|
/// - **Complete Register Set**: Display all 16 index registers (R0-R15)
|
|
/// - **Core CPU State**: Accumulator, program counter, stack pointer
|
|
/// - **Flag Visualization**: Carry flag status with clear indicators
|
|
/// - **Interactive Selection**: Choose which index register to highlight
|
|
/// - **Dual Format Display**: Hexadecimal and decimal representations
|
|
/// - **Real-time Updates**: Live register state during emulation
|
|
///
|
|
/// ## Intel 4004 Register Architecture
|
|
///
|
|
/// The Intel 4004 has the following register structure:
|
|
/// - **Accumulator**: Main arithmetic register (4 bits)
|
|
/// - **Index Registers**: 16 general-purpose registers (R0-R15)
|
|
/// - **Program Counter**: 12-bit address pointer
|
|
/// - **Stack Pointer**: 4-bit stack address register
|
|
/// - **Carry Flag**: Arithmetic carry/borrow indicator
|
|
///
|
|
/// ## Display Organization
|
|
///
|
|
/// Registers are organized in a clear hierarchy:
|
|
/// - **Primary Registers**: Most frequently used (accumulator, PC, stack)
|
|
/// - **Flags**: System status indicators
|
|
/// - **Index Registers**: General-purpose register file
|
|
pub struct RegisterViewer {
|
|
/// Currently selected index register for detailed view (0-15)
|
|
selected_register: usize,
|
|
}
|
|
|
|
impl RegisterViewer {
|
|
/// Create a new register viewer with default configuration
|
|
///
|
|
/// Initializes the viewer with index register 0 selected and standard
|
|
/// display formatting optimized for the Intel 4004 architecture.
|
|
///
|
|
/// # Returns
|
|
/// A new `RegisterViewer` instance ready for CPU state display
|
|
pub fn new() -> Self {
|
|
Self {
|
|
selected_register: 0,
|
|
}
|
|
}
|
|
|
|
/// Render the register viewer interface
|
|
///
|
|
/// Creates a comprehensive register inspection interface with organized
|
|
/// display of all CPU state elements and interactive index register selection.
|
|
///
|
|
/// # Arguments
|
|
/// * `ui` - egui UI context for rendering
|
|
/// * `state` - Immutable reference to GUI state containing register data
|
|
///
|
|
/// # Layout Structure
|
|
/// ```text
|
|
/// ┌─────────────────────────────────────────────────┐
|
|
/// │ CPU Registers [─] [□] │
|
|
/// │ Index Register: [0] │
|
|
/// ├─────────────────────────────────────────────────┤
|
|
/// │ Register │ Value (Hex) │ Value (Dec) │
|
|
/// │ Accumulator │ 0F │ 15 │
|
|
/// │ Carry Flag │ 1 │ Set │
|
|
/// │ Program Counter│ 123 │ 291 │
|
|
/// │ Index R0 │ 2A │ 42 │
|
|
/// │ Stack Pointer │ 08 │ 8 │
|
|
/// └─────────────────────────────────────────────────┘
|
|
/// ```
|
|
pub fn render(&self, ui: &mut egui::Ui, state: &GuiState) {
|
|
ui.vertical(|ui| {
|
|
// Section header
|
|
ui.heading("CPU Registers");
|
|
|
|
// Index register selector
|
|
ui.horizontal(|ui| {
|
|
ui.label("Index Register:");
|
|
ui.add(
|
|
egui::DragValue::new(&mut self.selected_register.clone()).clamp_range(0..=15),
|
|
);
|
|
});
|
|
|
|
ui.separator();
|
|
|
|
// Register display grid
|
|
egui::Grid::new("register_grid")
|
|
.striped(true)
|
|
.show(ui, |ui| {
|
|
// Header row
|
|
ui.label("Register");
|
|
ui.label("Value (Hex)");
|
|
ui.label("Value (Dec)");
|
|
ui.end_row();
|
|
|
|
// Core CPU registers
|
|
ui.label("Accumulator");
|
|
ui.label(format!("{:02X}", state.register_state.accumulator));
|
|
ui.label(format!("{}", state.register_state.accumulator));
|
|
ui.end_row();
|
|
|
|
// System flags
|
|
ui.label("Carry Flag");
|
|
ui.label(if state.register_state.carry_flag {
|
|
"1"
|
|
} else {
|
|
"0"
|
|
});
|
|
ui.label(if state.register_state.carry_flag {
|
|
"Set"
|
|
} else {
|
|
"Clear"
|
|
});
|
|
ui.end_row();
|
|
|
|
// Program execution state
|
|
ui.label("Program Counter");
|
|
ui.label(format!("{:03X}", state.register_state.program_counter));
|
|
ui.label(format!("{}", state.register_state.program_counter));
|
|
ui.end_row();
|
|
|
|
// Selected index register (highlighted)
|
|
ui.label(format!("Index R{}", self.selected_register));
|
|
ui.label(format!(
|
|
"{:02X}",
|
|
state.register_state.index_registers[self.selected_register]
|
|
));
|
|
ui.label(format!(
|
|
"{}",
|
|
state.register_state.index_registers[self.selected_register]
|
|
));
|
|
ui.end_row();
|
|
|
|
// Stack management
|
|
ui.label("Stack Pointer");
|
|
ui.label(format!("{:02X}", state.register_state.stack_pointer));
|
|
ui.label(format!("{}", state.register_state.stack_pointer));
|
|
ui.end_row();
|
|
});
|
|
});
|
|
|
|
ui.separator();
|
|
}
|
|
}
|
|
|
|
/// ROM loader component for file dialog integration and program management
|
|
///
|
|
/// The ROM loader handles program file selection, loading, and management.
|
|
/// It provides the interface for users to load Intel 4001 ROM files and
|
|
/// binary programs into the emulator system.
|
|
///
|
|
/// ## Features
|
|
///
|
|
/// - **File Dialog Integration**: Native file browser for program selection
|
|
/// - **Program Validation**: Basic file format and size validation
|
|
/// - **Load Feedback**: Visual confirmation of successful loads
|
|
/// - **Error Handling**: Clear error messages for failed operations
|
|
/// - **Future Extensions**: Support for multiple ROM chips and formats
|
|
///
|
|
/// ## Supported Formats
|
|
///
|
|
/// - **Binary Files**: Raw binary program data (.bin)
|
|
/// - **Intel 4001 Format**: MCS-4 ROM file format (planned)
|
|
/// - **Configuration Files**: System configuration integration (planned)
|
|
///
|
|
/// ## Integration Notes
|
|
///
|
|
/// Currently shows placeholder for file dialog implementation.
|
|
/// Production version should integrate with native file dialogs using:
|
|
/// - **rfd** crate for cross-platform file dialogs
|
|
/// - **async** operations for non-blocking file I/O
|
|
/// - **Progress feedback** for large file operations
|
|
pub struct RomLoader {
|
|
/// Whether to show the file selection dialog
|
|
show_file_dialog: bool,
|
|
/// Currently selected file path (if any)
|
|
selected_file: Option<String>,
|
|
}
|
|
|
|
impl RomLoader {
|
|
/// Create a new ROM loader with default state
|
|
///
|
|
/// Initializes the loader with no file selected and dialog closed.
|
|
/// Ready to handle user file selection requests.
|
|
///
|
|
/// # Returns
|
|
/// A new `RomLoader` instance ready for file operations
|
|
pub fn new() -> Self {
|
|
Self {
|
|
show_file_dialog: false,
|
|
selected_file: None,
|
|
}
|
|
}
|
|
|
|
/// Render the ROM loader interface
|
|
///
|
|
/// Creates the file management interface with load button and
|
|
/// file selection dialog integration.
|
|
///
|
|
/// # Arguments
|
|
/// * `ui` - egui UI context for rendering
|
|
/// * `_state` - GUI state (currently unused but reserved for future integration)
|
|
///
|
|
/// # Layout Structure
|
|
/// ```text
|
|
/// ┌─────────────────────────────────────────────────┐
|
|
/// │ ROM Management [─] [□]│
|
|
/// │ [Load ROM File...] │
|
|
/// │ Selected: /path/to/program.bin │
|
|
/// │ │
|
|
/// │ [File Dialog Placeholder] │
|
|
/// └─────────────────────────────────────────────────┘
|
|
/// ```
|
|
pub fn render(&mut self, ui: &mut egui::Ui, _state: &mut GuiState) {
|
|
ui.vertical(|ui| {
|
|
ui.heading("ROM Management");
|
|
|
|
// Load button to trigger file selection
|
|
if ui.button("Load ROM File...").clicked() {
|
|
self.show_file_dialog = true;
|
|
}
|
|
|
|
// Display currently selected file
|
|
if let Some(ref file) = self.selected_file.clone() {
|
|
ui.label(format!("Selected: {}", file));
|
|
}
|
|
|
|
// File dialog implementation (placeholder)
|
|
if self.show_file_dialog {
|
|
// Placeholder for file dialog
|
|
ui.label("File dialog would open here");
|
|
if ui.button("Cancel").clicked() {
|
|
self.show_file_dialog = false;
|
|
}
|
|
}
|
|
});
|
|
|
|
ui.separator();
|
|
}
|
|
}
|
|
|
|
/// Status bar component for system status display and health monitoring
|
|
///
|
|
/// The status bar provides comprehensive system health information,
|
|
/// component status indicators, and real-time performance metrics.
|
|
/// It serves as the primary location for system state overview.
|
|
///
|
|
/// ## Features
|
|
///
|
|
/// - **System Status**: Running/stopped state with visual indicators
|
|
/// - **Performance Metrics**: Cycle count and execution speed
|
|
/// - **Component Health**: Individual component status monitoring
|
|
/// - **Error Display**: Real-time error message display
|
|
/// - **System Information**: CPU speed, component count, and configuration
|
|
///
|
|
/// ## Visual Design
|
|
///
|
|
/// - **Color Coding**: Green for healthy, red for errors/stopped
|
|
/// - **Layout Organization**: Status on left, errors on right
|
|
/// - **Real-time Updates**: Live status changes during operation
|
|
/// - **Compact Display**: Information-dense but readable layout
|
|
///
|
|
/// ## Component Status Indicators
|
|
///
|
|
/// Monitors the health of all major system components:
|
|
/// - **CPU**: Intel 4004 execution status
|
|
/// - **RAM**: Intel 4002 memory operations
|
|
/// - **ROM**: Intel 4001 program storage
|
|
/// - **CLK**: System clock generation
|
|
pub struct StatusBar;
|
|
|
|
impl StatusBar {
|
|
/// Create a new status bar component
|
|
///
|
|
/// Initializes a stateless status bar ready to display
|
|
/// current system health and performance information.
|
|
///
|
|
/// # Returns
|
|
/// A new `StatusBar` instance
|
|
pub fn new() -> Self {
|
|
Self
|
|
}
|
|
|
|
/// Render the status bar interface
|
|
///
|
|
/// Creates a comprehensive status display with system information,
|
|
/// component health indicators, and error reporting.
|
|
///
|
|
/// # Arguments
|
|
/// * `ui` - egui UI context for rendering
|
|
/// * `state` - Immutable reference to GUI state for status information
|
|
///
|
|
/// # Layout Structure
|
|
/// ```text
|
|
/// ┌─────────────────────────────────────────────────────────────┐
|
|
/// │ Status: ● Running │ Cycles: 12345 │ CPU: 0.7 MHz │
|
|
/// │ Components: 4 │ CPU RAM ROM CLK │ Error: Connection │
|
|
/// └─────────────────────────────────────────────────────────────┘
|
|
/// ```
|
|
pub fn render(&self, ui: &mut egui::Ui, state: &GuiState) {
|
|
ui.separator();
|
|
|
|
ui.horizontal(|ui| {
|
|
// Left side: Status information and metrics
|
|
ui.with_layout(egui::Layout::left_to_right(egui::Align::Center), |ui| {
|
|
// System running status
|
|
ui.label("Status:");
|
|
if state.system_running {
|
|
ui.colored_label(egui::Color32::GREEN, "● Running");
|
|
} else {
|
|
ui.colored_label(egui::Color32::RED, "● Stopped");
|
|
}
|
|
|
|
ui.separator();
|
|
|
|
// Performance metrics
|
|
ui.label(format!("Cycles: {}", state.cycle_count));
|
|
|
|
ui.separator();
|
|
|
|
// System information
|
|
if let Some(ref info) = state.system_info {
|
|
ui.label(format!("CPU: {:.1} MHz", info.cpu_speed / 1_000_000.0));
|
|
ui.label(format!("Components: {}", info.component_count));
|
|
}
|
|
|
|
ui.separator();
|
|
|
|
// Component status indicators
|
|
ui.label("Components:");
|
|
ui.colored_label(
|
|
if state.component_states.cpu_running {
|
|
egui::Color32::GREEN
|
|
} else {
|
|
egui::Color32::RED
|
|
},
|
|
"CPU",
|
|
);
|
|
ui.colored_label(
|
|
if state.component_states.ram_running {
|
|
egui::Color32::GREEN
|
|
} else {
|
|
egui::Color32::RED
|
|
},
|
|
"RAM",
|
|
);
|
|
ui.colored_label(
|
|
if state.component_states.rom_running {
|
|
egui::Color32::GREEN
|
|
} else {
|
|
egui::Color32::RED
|
|
},
|
|
"ROM",
|
|
);
|
|
ui.colored_label(
|
|
if state.component_states.clock_running {
|
|
egui::Color32::GREEN
|
|
} else {
|
|
egui::Color32::RED
|
|
},
|
|
"CLK",
|
|
);
|
|
});
|
|
|
|
// Right side: Error messages
|
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
|
if let Some(ref error) = state.last_error {
|
|
ui.colored_label(egui::Color32::RED, format!("Error: {}", error));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|