use egui::{Color32, TextStyle};
use std::ops::Range;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))]
pub enum Endianness {
Big,
Little,
}
impl Endianness {
pub fn iter() -> impl Iterator<Item = Endianness> {
vec![Endianness::Big, Endianness::Little].into_iter()
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))]
pub enum DataFormatType {
U8,
U16,
U32,
U64,
I8,
I16,
I32,
I64,
F32,
F64,
}
impl DataFormatType {
pub fn iter() -> impl Iterator<Item = DataFormatType> {
use DataFormatType::*;
vec![U8, U16, U32, U64, I8, I16, I32, I64, F32, F64].into_iter()
}
pub const fn bytes_to_read(&self) -> usize {
use DataFormatType::*;
match *self {
U8 | I8 => 1,
U16 | I16 => 2,
U32 | I32 | F32 => 4,
U64 | I64 | F64 => 8,
}
}
}
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "persistence", serde(default))]
pub struct DataPreviewOptions {
pub selected_endianness: Endianness,
pub selected_data_format: DataFormatType,
}
impl Default for DataPreviewOptions {
fn default() -> Self {
DataPreviewOptions {
selected_endianness: Endianness::Little,
selected_data_format: DataFormatType::U32,
}
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "persistence", serde(default))]
pub struct MemoryEditorOptions {
pub is_open: bool,
pub show_ascii_sidebar: bool,
pub show_zero_colour: bool,
pub data_preview_options: DataPreviewOptions,
pub column_count: usize,
pub zero_colour: Color32,
pub address_text_colour: Color32,
pub highlight_colour: Color32,
pub memory_editor_text_style: TextStyle,
pub memory_editor_address_text_style: TextStyle,
pub memory_editor_ascii_text_style: TextStyle,
pub(crate) selected_address_range: String,
}
impl Default for MemoryEditorOptions {
fn default() -> Self {
MemoryEditorOptions {
is_open: true,
data_preview_options: Default::default(),
show_ascii_sidebar: true,
show_zero_colour: true,
zero_colour: Color32::from_gray(80),
column_count: 16,
address_text_colour: Color32::from_rgb(125, 0, 125),
highlight_colour: Color32::from_rgb(0, 140, 140),
memory_editor_text_style: TextStyle::Monospace,
memory_editor_address_text_style: TextStyle::Monospace,
memory_editor_ascii_text_style: TextStyle::Monospace,
selected_address_range: "".to_string(),
}
}
}
#[derive(Debug, Default, Clone)]
pub(crate) struct BetweenFrameData {
pub previous_frame_editor_width: f32,
pub selected_edit_address: Option<usize>,
pub selected_edit_address_string: String,
pub selected_edit_address_request_focus: bool,
pub memory_range_combo_box_enabled: bool,
pub selected_highlight_address: Option<usize>,
pub show_additional_highlights: bool,
pub goto_address_string: String,
pub goto_address_line: Option<usize>,
}
impl BetweenFrameData {
pub fn set_highlight_address(&mut self, new_address: usize) {
self.selected_highlight_address = if matches!(self.selected_highlight_address, Some(current) if current == new_address) {
self.goto_address_string.clear();
None
} else {
self.goto_address_string = format!("{:X}", new_address);
Some(new_address)
};
}
pub fn set_selected_edit_address(&mut self, new_address: Option<usize>, address_space: &Range<usize>) {
self.selected_edit_address_string.clear();
if matches!(new_address, Some(address) if address_space.contains(&address)) {
self.set_highlight_address(new_address.unwrap());
self.selected_edit_address_request_focus = true;
self.selected_edit_address = new_address;
} else {
self.selected_edit_address = None;
}
}
#[inline]
pub fn should_highlight(&self, address: usize) -> bool {
self.selected_highlight_address.map_or(false, |addr| addr == address)
|| self.selected_edit_address.map_or(false, |addr| addr == address)
}
pub fn should_subtle_highlight(&self, address: usize, data_format: DataFormatType) -> bool {
self.show_additional_highlights && self.selected_highlight_address.map_or(false, |addr| {
(addr..addr+data_format.bytes_to_read()).contains(&address)
})
}
}