Skip to main content

edb_tui/panels/
mod.rs

1// EDB - Ethereum Debugger
2// Copyright (C) 2024 Zhuo Zhang and Wuqi Zhang
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Affero General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Affero General Public License for more details.
13//
14// You should have received a copy of the GNU Affero General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17//! Panel framework and implementations
18//!
19//! This module contains the panel trait and all panel implementations.
20
21use crate::data::DataManager;
22use crossterm::event::{KeyEvent, MouseEvent};
23use eyre::Result;
24use ratatui::{layout::Rect, Frame};
25use std::fmt::Debug;
26
27/// Panel types for identification
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
29pub enum PanelType {
30    /// Trace panel showing execution trace
31    Trace,
32    /// Code panel showing source code or opcodes
33    Code,
34    /// Display panel showing variables, stack, memory, etc.
35    Display,
36    /// Terminal panel for command input/output
37    Terminal,
38}
39
40/// Response from panel event handling
41#[derive(Debug)]
42pub enum EventResponse {
43    /// Event was handled, no further action needed
44    Handled,
45    /// Event was not handled, pass to next handler
46    NotHandled,
47    /// Request focus change to another panel
48    ChangeFocus(PanelType),
49    /// Request application exit
50    Exit,
51}
52
53/// Trait for UI panels
54pub trait PanelTr: Debug + Send {
55    /// Render the panel content
56    fn render(&mut self, frame: &mut Frame<'_>, area: Rect, data_manager: &mut DataManager);
57
58    /// Handle keyboard events
59    fn handle_key_event(
60        &mut self,
61        event: KeyEvent,
62        data_manager: &mut DataManager,
63    ) -> Result<EventResponse> {
64        let _ = event; // Suppress unused parameter warning
65        let _ = data_manager;
66        Ok(EventResponse::NotHandled)
67    }
68
69    /// Handle mouse events
70    fn _handle_mouse_event(
71        &mut self,
72        event: MouseEvent,
73        data_manager: &mut DataManager,
74    ) -> Result<EventResponse> {
75        let _ = event; // Suppress unused parameter warning
76        let _ = data_manager;
77        Ok(EventResponse::NotHandled)
78    }
79
80    /// Called when this panel gains focus
81    fn on_focus(&mut self) {}
82
83    /// Called when this panel loses focus
84    fn on_blur(&mut self) {}
85
86    /// Get the panel type
87    fn panel_type(&self) -> PanelType;
88
89    /// Get panel title for display
90    fn title(&self, _data_manager: &mut DataManager) -> String {
91        format!("{:?} Panel", self.panel_type())
92    }
93
94    /// Allow downcasting to concrete types
95    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
96}
97
98// Re-export all panel implementations
99pub mod code;
100pub mod display;
101pub mod help;
102pub mod terminal;
103pub mod trace;
104mod utils;
105
106pub use code::CodePanel;
107pub use display::DisplayPanel;
108pub use help::HelpOverlay;
109pub use terminal::TerminalPanel;
110pub use trace::TracePanel;
111
112#[derive(Debug)]
113pub enum Panel {
114    Code(CodePanel),
115    Display(DisplayPanel),
116    Terminal(TerminalPanel),
117    Trace(TracePanel),
118}
119
120impl PanelTr for Panel {
121    fn render(&mut self, frame: &mut Frame<'_>, area: Rect, data_manager: &mut DataManager) {
122        match self {
123            Self::Code(panel) => panel.render(frame, area, data_manager),
124            Self::Display(panel) => panel.render(frame, area, data_manager),
125            Self::Terminal(panel) => panel.render(frame, area, data_manager),
126            Self::Trace(panel) => panel.render(frame, area, data_manager),
127        }
128    }
129
130    fn handle_key_event(
131        &mut self,
132        event: KeyEvent,
133        data_manager: &mut DataManager,
134    ) -> Result<EventResponse> {
135        match self {
136            Self::Code(panel) => panel.handle_key_event(event, data_manager),
137            Self::Display(panel) => panel.handle_key_event(event, data_manager),
138            Self::Terminal(panel) => panel.handle_key_event(event, data_manager),
139            Self::Trace(panel) => panel.handle_key_event(event, data_manager),
140        }
141    }
142
143    fn _handle_mouse_event(
144        &mut self,
145        event: MouseEvent,
146        data_manager: &mut DataManager,
147    ) -> Result<EventResponse> {
148        match self {
149            Self::Code(panel) => panel._handle_mouse_event(event, data_manager),
150            Self::Display(panel) => panel._handle_mouse_event(event, data_manager),
151            Self::Terminal(panel) => panel._handle_mouse_event(event, data_manager),
152            Self::Trace(panel) => panel._handle_mouse_event(event, data_manager),
153        }
154    }
155
156    fn on_focus(&mut self) {
157        match self {
158            Self::Code(panel) => panel.on_focus(),
159            Self::Display(panel) => panel.on_focus(),
160            Self::Terminal(panel) => panel.on_focus(),
161            Self::Trace(panel) => panel.on_focus(),
162        }
163    }
164
165    fn on_blur(&mut self) {
166        match self {
167            Self::Code(panel) => panel.on_blur(),
168            Self::Display(panel) => panel.on_blur(),
169            Self::Terminal(panel) => panel.on_blur(),
170            Self::Trace(panel) => panel.on_blur(),
171        }
172    }
173
174    fn panel_type(&self) -> PanelType {
175        match self {
176            Self::Code(_) => PanelType::Code,
177            Self::Display(_) => PanelType::Display,
178            Self::Terminal(_) => PanelType::Terminal,
179            Self::Trace(_) => PanelType::Trace,
180        }
181    }
182
183    fn title(&self, _dm: &mut DataManager) -> String {
184        match self {
185            Self::Code(_) => "Code".to_string(),
186            Self::Display(_) => "Display".to_string(),
187            Self::Terminal(_) => "Terminal".to_string(),
188            Self::Trace(_) => "Trace".to_string(),
189        }
190    }
191
192    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
193        match self {
194            Self::Code(panel) => panel.as_any_mut(),
195            Self::Display(panel) => panel.as_any_mut(),
196            Self::Terminal(panel) => panel.as_any_mut(),
197            Self::Trace(panel) => panel.as_any_mut(),
198        }
199    }
200}