# Observer Pattern and UI Layout Configuration Implementation Plan ## Overview This plan implements two key improvements to the rusty_emu project: 1. **Observer Pattern**: Replace inefficient polling with event-driven state updates 2. **UI Layout Configuration**: Enable configurable GUI layouts from JSON config files ## Current Issues ### Performance Issues - Console polls system state at 100ms intervals (inefficient) - GUI uses `try_lock()` but still has potential contention - No way to configure GUI layout from JSON config ### Architecture Limitations - Tight coupling between components and UI - No standardized way to notify UI of state changes - Hardcoded UI layouts ## Solution Architecture ### Observer Pattern Implementation ```mermaid graph TD A[SystemObserver Trait] --> B[CPU Observer] A --> C[RAM Observer] A --> D[ROM Observer] B --> E[ConfigurableSystem] C --> E D --> E E --> F[Console UI] E --> G[GUI Interface] F --> H[Event-driven Updates] G --> H ``` ### UI Layout Configuration ```mermaid graph LR A[SystemConfig JSON] --> B[UI Layout Section] B --> C[Component Positions] B --> D[Component Sizes] B --> E[Display Options] C --> F[GUI Renderer] D --> F E --> F ``` ## Implementation Details ### 1. SystemObserver Trait (Fine-grained with Filtering) ```rust #[derive(Debug, Clone)] pub enum ObserverFilter { All, CpuOnly, MemoryOnly, StateChangesOnly, RegisterChangesOnly, } pub trait SystemObserver: Send + Sync { fn get_filter(&self) -> ObserverFilter { return ObserverFilter::All; } fn on_state_change(&self, component: &str, old_state: ComponentState, new_state: ComponentState); fn on_ram_change(&self, chip: &str, bank: usize, address: u8, old_value: u8, new_value: u8); fn on_rom_change(&self, chip: &str, address: u16, old_value: u8, new_value: u8); fn on_cpu_register_change(&self, cpu: &str, register: &str, old_value: u8, new_value: u8); fn on_cpu_pc_change(&self, cpu: &str, old_pc: u16, new_pc: u16); fn on_cpu_instruction_executed(&self, cpu: &str, instruction: u8, pc: u16); } ``` ### 2. Enhanced SystemConfig ```rust #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SystemConfig { pub name: String, pub description: String, pub version: String, pub metadata: HashMap, pub components: HashMap, pub connections: HashMap, pub layout: Option, // NEW: UI Layout configuration pub ui_layout: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UiLayoutConfig { pub console: Option, pub gui: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GuiLayoutConfig { pub components: HashMap, pub grid_size: Option<[usize; 2]>, pub refresh_rate_ms: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ComponentLayoutConfig { pub position: [usize; 2], pub size: [usize; 2], pub visible: Option, pub display_format: Option, } ``` ### 3. Observer Registration in ConfigurableSystem ```rust pub struct ConfigurableSystem { config: SystemConfig, components: HashMap>>>, is_running: Arc>, component_handles: Arc>>, // NEW: Observer registry observers: Arc>>>, } ``` ### 4. Component Integration Each component will notify observers of state changes: - **Intel4004 CPU**: Register changes, PC changes, instruction execution - **Intel4001 ROM**: Memory reads, address changes - **Intel4002 RAM**: Memory reads/writes, I/O changes ### 5. UI Updates #### Console Updates (Performance Target: 50% CPU reduction, sub-10ms responsiveness) - Replace 100ms polling with event-driven updates using observer pattern - Observer receives notifications and updates display immediately - Implement filtering to reduce unnecessary UI updates - Target: Reduce CPU usage by 50% compared to current polling - Target: Update responsiveness to under 10ms for state changes #### GUI Updates - Use layout configuration from JSON for component positioning/sizing - Position components according to config (basic implementation) - Show/hide components based on config visibility settings - Use observer pattern for real-time updates - Support configurable refresh rates from UI layout config ## Configuration Examples ### Enhanced JSON Config ```json { "name": "IntelMcs4", "description": "Basic MCS-4 System with CPU, Clock, 2 ROMs, and 1 RAM", "version": "1.0", "metadata": { "author": "RustyEmu", "created": "2024-01-01", "cpu_speed": 750000, "architecture": "mcs4", "rom_count": 2, "ram_count": 1 }, "components": { "CPU_4004": { "single": { "component_type": "intel_4004", "name": "CPU_4004", "properties": { "clock_speed": 750000 } } } // ... other components }, "connections": { // ... existing connections }, "layout": { "grid_size": [10, 10], "positions": { "cpu": [1, 1], "clock": [0, 0], "rom1": [2, 0], "rom2": [3, 0], "ram": [2, 2] } }, "ui_layout": { "console": { "refresh_rate_ms": 50, "show_ram": true, "show_registers": true, "show_system_info": true }, "gui": { "grid_size": [20, 20], "components": { "CPU_4004": { "position": [1, 1], "size": [20, 10], "visible": true, "display_format": "hex" }, "RAM_4002": { "position": [3, 2], "size": [25, 15], "visible": true, "display_format": "hex" }, "ROM_4001_1": { "position": [2, 0], "size": [20, 8], "visible": true, "display_format": "hex" } }, "refresh_rate_ms": 60 } } } ``` ## Benefits ### Performance Improvements - **Reduced CPU usage**: Event-driven vs polling - **Better responsiveness**: Immediate updates vs 100ms delays - **Less contention**: Observer pattern reduces lock contention ### User Experience - **Configurable layouts**: Users can customize UI arrangement - **Persistent settings**: Layouts saved in config files - **Flexible display options**: Show/hide components, change formats ### Architecture Benefits - **Loose coupling**: Components don't depend on UI - **Extensibility**: Easy to add new observers - **Maintainability**: Clear separation of concerns ## Implementation Steps 1. **Add SystemObserver trait** to `system_config.rs` 2. **Extend SystemConfig** with UI layout configuration 3. **Add observer registration** to `ConfigurableSystem` 4. **Implement observer notifications** in Intel4004 CPU 5. **Implement observer notifications** in Intel4001 ROM 6. **Implement observer notifications** in Intel4002 RAM 7. **Update console.rs** to use observer pattern 8. **Update GUI** to use observer pattern and layout configuration 9. **Add UI layout configuration** to existing JSON configs 10. **Test** the observer pattern and UI layout system 11. **Update documentation** with new features ## Testing Strategy ### Unit Tests - Test observer registration and notification - Test UI layout configuration parsing - Test component state change notifications ### Integration Tests - Test console with observer pattern - Test GUI with layout configuration - Test end-to-end state change propagation ### Performance Tests - Measure CPU usage reduction - Test responsiveness improvements - Validate lock contention reduction ## Backward Compatibility - Existing configs without `ui_layout` section will use defaults (console: 100ms, current GUI layout) - Observer pattern is additive - doesn't break existing code, components work without observers - ConfigurableSystem will handle missing `ui_layout` gracefully with sensible defaults - Gradual migration path: existing configs continue to work, new configs get enhanced features - No breaking changes to existing JSON configs - only additive new section ## Future Enhancements - **Multiple observer types**: Different observers for different concerns - **Layout templates**: Predefined layouts for different use cases - **Dynamic layout editing**: Runtime layout modification - **Observer filtering**: Selective notification based on component types