Skip to content

Commit b38f7fe

Browse files
Initial restructure of UI to make it more clear and easy to use
Signed-off-by: Cole Gentry <peapod2007@gmail.com>
1 parent c054b57 commit b38f7fe

12 files changed

Lines changed: 1980 additions & 491 deletions

src/app.rs

Lines changed: 95 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ use crate::analytics;
1616
use crate::computed::{ComputedChannel, ComputedChannelLibrary, FormulaEditorState};
1717
use crate::parsers::{Aim, EcuMaster, EcuType, Haltech, Link, Parseable, RomRaider, Speeduino};
1818
use crate::state::{
19-
ActiveTool, CacheKey, FontScale, LoadResult, LoadedFile, LoadingState, ScatterPlotConfig,
20-
ScatterPlotState, SelectedChannel, Tab, ToastType, CHART_COLORS, COLORBLIND_COLORS,
21-
MAX_CHANNELS,
19+
ActivePanel, ActiveTool, CacheKey, FontScale, LoadResult, LoadedFile, LoadingState,
20+
ScatterPlotConfig, ScatterPlotState, SelectedChannel, Tab, ToastType, CHART_COLORS,
21+
COLORBLIND_COLORS, MAX_CHANNELS,
2222
};
2323
use crate::units::UnitPreferences;
2424
use crate::updater::{DownloadResult, UpdateCheckResult, UpdateState};
@@ -92,6 +92,9 @@ pub struct UltraLogApp {
9292
// === Tool/View Selection ===
9393
/// Currently active tool/view
9494
pub(crate) active_tool: ActiveTool,
95+
// === Panel Selection ===
96+
/// Currently active side panel (activity bar selection)
97+
pub(crate) active_panel: ActivePanel,
9598
// === Tab Management ===
9699
/// Open tabs (one per log file being viewed)
97100
pub(crate) tabs: Vec<Tab>,
@@ -161,6 +164,7 @@ impl Default for UltraLogApp {
161164
norm_editor_custom_source: String::new(),
162165
norm_editor_custom_target: String::new(),
163166
active_tool: ActiveTool::default(),
167+
active_panel: ActivePanel::default(),
164168
tabs: Vec::new(),
165169
active_tab: None,
166170
update_state: UpdateState::default(),
@@ -1233,18 +1237,78 @@ impl UltraLogApp {
12331237

12341238
/// Handle keyboard shortcuts
12351239
fn handle_keyboard_shortcuts(&mut self, ctx: &egui::Context) {
1236-
// Only handle shortcuts when we have data loaded
1237-
if self.files.is_empty() || self.get_selected_channels().is_empty() {
1238-
return;
1239-
}
1240-
12411240
// Don't handle shortcuts when a text field or other widget has keyboard focus
12421241
if ctx.memory(|m| m.focused().is_some()) {
12431242
return;
12441243
}
12451244

1246-
// Spacebar to toggle play/pause
12471245
ctx.input(|i| {
1246+
let cmd = i.modifiers.command;
1247+
let shift = i.modifiers.shift;
1248+
1249+
// ⌘O - Open file
1250+
if cmd && i.key_pressed(egui::Key::O) {
1251+
if let Some(path) = rfd::FileDialog::new()
1252+
.add_filter("Log Files", crate::state::SUPPORTED_EXTENSIONS)
1253+
.pick_file()
1254+
{
1255+
self.start_loading_file(path);
1256+
}
1257+
return;
1258+
}
1259+
1260+
// ⌘W - Close current tab
1261+
if cmd && i.key_pressed(egui::Key::W) {
1262+
if let Some(tab_idx) = self.active_tab {
1263+
self.close_tab(tab_idx);
1264+
}
1265+
return;
1266+
}
1267+
1268+
// ⌘, - Open Settings panel
1269+
if cmd && i.key_pressed(egui::Key::Comma) {
1270+
self.active_panel = crate::state::ActivePanel::Settings;
1271+
return;
1272+
}
1273+
1274+
// ⌘1/2/3 - Switch tool modes
1275+
if cmd && !shift {
1276+
if i.key_pressed(egui::Key::Num1) {
1277+
self.active_tool = crate::state::ActiveTool::LogViewer;
1278+
return;
1279+
}
1280+
if i.key_pressed(egui::Key::Num2) {
1281+
self.active_tool = crate::state::ActiveTool::ScatterPlot;
1282+
return;
1283+
}
1284+
if i.key_pressed(egui::Key::Num3) {
1285+
self.active_tool = crate::state::ActiveTool::Histogram;
1286+
return;
1287+
}
1288+
}
1289+
1290+
// ⌘⇧F/C/T - Switch panels
1291+
if cmd && shift {
1292+
if i.key_pressed(egui::Key::F) {
1293+
self.active_panel = crate::state::ActivePanel::Files;
1294+
return;
1295+
}
1296+
if i.key_pressed(egui::Key::C) {
1297+
self.active_panel = crate::state::ActivePanel::Channels;
1298+
return;
1299+
}
1300+
if i.key_pressed(egui::Key::T) {
1301+
self.active_panel = crate::state::ActivePanel::Tools;
1302+
return;
1303+
}
1304+
}
1305+
1306+
// Playback shortcuts (require file loaded with channels selected)
1307+
if self.files.is_empty() || self.get_selected_channels().is_empty() {
1308+
return;
1309+
}
1310+
1311+
// Spacebar to toggle play/pause
12481312
if i.key_pressed(egui::Key::Space) {
12491313
self.is_playing = !self.is_playing;
12501314
if self.is_playing {
@@ -1347,41 +1411,38 @@ impl eframe::App for UltraLogApp {
13471411
self.render_tool_switcher(ui);
13481412
});
13491413

1350-
// Panel background color (matches drop zone card)
1414+
// Panel background color
13511415
let panel_bg = egui::Color32::from_rgb(45, 45, 45);
13521416
let panel_frame = egui::Frame::NONE
13531417
.fill(panel_bg)
13541418
.inner_margin(egui::Margin::symmetric(10, 10));
13551419

1356-
// Left sidebar panel (always visible)
1357-
egui::SidePanel::left("files_panel")
1358-
.default_width(200.0)
1420+
// Activity bar (far left, narrow icon strip)
1421+
let activity_bar_bg = egui::Color32::from_rgb(35, 35, 35);
1422+
let activity_bar_frame = egui::Frame::NONE
1423+
.fill(activity_bar_bg)
1424+
.inner_margin(egui::Margin::symmetric(4, 8));
1425+
1426+
egui::SidePanel::left("activity_bar")
1427+
.exact_width(crate::ui::activity_bar::ACTIVITY_BAR_WIDTH)
1428+
.resizable(false)
1429+
.frame(activity_bar_frame)
1430+
.show(ctx, |ui| {
1431+
self.render_activity_bar(ui);
1432+
});
1433+
1434+
// Side panel (context-sensitive based on activity bar selection)
1435+
egui::SidePanel::left("side_panel")
1436+
.default_width(crate::ui::side_panel::SIDE_PANEL_WIDTH)
1437+
.min_width(crate::ui::side_panel::SIDE_PANEL_MIN_WIDTH)
13591438
.resizable(true)
13601439
.frame(panel_frame)
13611440
.show(ctx, |ui| {
1362-
self.render_sidebar(ui);
1441+
self.render_side_panel(ui);
13631442
});
13641443

1365-
// Right panel for channel selection (only in Log Viewer mode)
1366-
if self.active_tool == ActiveTool::LogViewer {
1367-
egui::SidePanel::right("channels_panel")
1368-
.default_width(300.0)
1369-
.min_width(200.0)
1370-
.resizable(true)
1371-
.frame(panel_frame)
1372-
.show(ctx, |ui| {
1373-
self.render_channel_selection(ui);
1374-
});
1375-
}
1376-
1377-
// Bottom panel for timeline scrubber (Log Viewer and Histogram modes)
1378-
let show_timeline = match self.active_tool {
1379-
ActiveTool::LogViewer => {
1380-
self.get_time_range().is_some() && !self.get_selected_channels().is_empty()
1381-
}
1382-
ActiveTool::Histogram => self.get_time_range().is_some(),
1383-
ActiveTool::ScatterPlot => false,
1384-
};
1444+
// Bottom panel for timeline scrubber (always visible when file loaded)
1445+
let show_timeline = self.get_time_range().is_some();
13851446

13861447
if show_timeline {
13871448
egui::TopBottomPanel::bottom("timeline_panel")

src/state.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,42 @@ impl ActiveTool {
195195
}
196196
}
197197

198+
/// The currently active side panel in the activity bar
199+
#[derive(Clone, Copy, PartialEq, Eq, Default)]
200+
pub enum ActivePanel {
201+
/// Files panel - file management, loading, file list
202+
#[default]
203+
Files,
204+
/// Channels panel - channel selection and selected channels
205+
Channels,
206+
/// Tools panel - analysis tools, computed channels, export
207+
Tools,
208+
/// Settings panel - all preferences consolidated
209+
Settings,
210+
}
211+
212+
impl ActivePanel {
213+
/// Get the display name for this panel
214+
pub fn name(&self) -> &'static str {
215+
match self {
216+
ActivePanel::Files => "Files",
217+
ActivePanel::Channels => "Channels",
218+
ActivePanel::Tools => "Tools",
219+
ActivePanel::Settings => "Settings",
220+
}
221+
}
222+
223+
/// Get the icon character for this panel (using Unicode symbols)
224+
pub fn icon(&self) -> &'static str {
225+
match self {
226+
ActivePanel::Files => "\u{1F4C1}", // Folder icon
227+
ActivePanel::Channels => "\u{1F4CA}", // Chart icon
228+
ActivePanel::Tools => "\u{1F527}", // Wrench icon
229+
ActivePanel::Settings => "\u{2699}", // Gear icon
230+
}
231+
}
232+
}
233+
198234
/// Font scale preference for UI elements
199235
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
200236
pub enum FontScale {

0 commit comments

Comments
 (0)