tabs scroll

This commit is contained in:
2025-12-09 18:28:31 +01:00
parent 225c5bdb91
commit e23323d0b4
2 changed files with 67 additions and 34 deletions

View File

@@ -6,7 +6,6 @@ pub struct ColorPalette {
pub bg_primary: egui::Color32, // Main background pub bg_primary: egui::Color32, // Main background
pub bg_secondary: egui::Color32, // Secondary panels pub bg_secondary: egui::Color32, // Secondary panels
pub bg_tertiary: egui::Color32, // Elevated elements pub bg_tertiary: egui::Color32, // Elevated elements
pub bg_hover: egui::Color32, // Hover states
// Accent colors // Accent colors
pub accent_primary: egui::Color32, // Primary purple accent pub accent_primary: egui::Color32, // Primary purple accent
@@ -20,14 +19,8 @@ pub struct ColorPalette {
// UI element colors // UI element colors
pub selection: egui::Color32, pub selection: egui::Color32,
pub highlight: egui::Color32,
pub line_number: egui::Color32, pub line_number: egui::Color32,
pub border: egui::Color32, pub border: egui::Color32,
// Status colors
pub success: egui::Color32,
pub warning: egui::Color32,
pub error: egui::Color32,
} }
impl ColorPalette { impl ColorPalette {
@@ -37,7 +30,6 @@ impl ColorPalette {
bg_primary: egui::Color32::from_rgb(24, 20, 32), // #18141F bg_primary: egui::Color32::from_rgb(24, 20, 32), // #18141F
bg_secondary: egui::Color32::from_rgb(32, 26, 42), // #201A2A bg_secondary: egui::Color32::from_rgb(32, 26, 42), // #201A2A
bg_tertiary: egui::Color32::from_rgb(42, 35, 54), // #2A2336 bg_tertiary: egui::Color32::from_rgb(42, 35, 54), // #2A2336
bg_hover: egui::Color32::from_rgba_premultiplied(90, 75, 115, 40),
// Purple accents - modern and vibrant // Purple accents - modern and vibrant
accent_primary: egui::Color32::from_rgb(138, 98, 208), // #8A62D0 accent_primary: egui::Color32::from_rgb(138, 98, 208), // #8A62D0
@@ -51,14 +43,9 @@ impl ColorPalette {
// UI elements // UI elements
selection: egui::Color32::from_rgb(108, 68, 178), // #6C44B2 selection: egui::Color32::from_rgb(108, 68, 178), // #6C44B2
highlight: egui::Color32::from_rgba_premultiplied(138, 98, 208, 60),
line_number: egui::Color32::from_rgb(110, 100, 130), // #6E6482 line_number: egui::Color32::from_rgb(110, 100, 130), // #6E6482
border: egui::Color32::from_rgb(60, 50, 75), // #3C324B border: egui::Color32::from_rgb(60, 50, 75), // #3C324B
// Status colors
success: egui::Color32::from_rgb(100, 200, 130), // #64C882
warning: egui::Color32::from_rgb(255, 180, 80), // #FFB450
error: egui::Color32::from_rgb(240, 100, 120), // #F06478
} }
} }
} }

View File

@@ -13,29 +13,75 @@ pub fn render_tabs_panel(
} }
egui::TopBottomPanel::top("tabs_panel").show(ctx, |ui| { egui::TopBottomPanel::top("tabs_panel").show(ctx, |ui| {
ui.horizontal(|ui| { // Get or initialize scroll offset from persistent storage
for (idx, tab) in tabs.iter().enumerate() { let scroll_id = egui::Id::new("tabs_scroll_offset");
let is_active = idx == *active_tab_index; let mut scroll_offset: f32 = ui.ctx().data_mut(|d| d.get_persisted(scroll_id).unwrap_or(0.0));
let button_text = if is_active {
egui::RichText::new(format!("📄 {}", tab.filename())).strong()
} else {
egui::RichText::new(format!("📄 {}", tab.filename()))
};
if ui.selectable_label(is_active, button_text).clicked() { // Use horizontal ScrollArea for tabs with hidden scrollbar
*active_tab_index = idx; let mut scroll_area = egui::ScrollArea::horizontal()
.auto_shrink([false; 2])
.scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden);
// Apply the stored scroll offset
scroll_area = scroll_area.horizontal_scroll_offset(scroll_offset);
let scroll_output = scroll_area.show(ui, |ui| {
ui.horizontal(|ui| {
for (idx, tab) in tabs.iter().enumerate() {
let is_active = idx == *active_tab_index;
let button_text = if is_active {
egui::RichText::new(format!("📄 {}", tab.filename())).strong()
} else {
egui::RichText::new(format!("📄 {}", tab.filename()))
};
if ui.selectable_label(is_active, button_text).clicked() {
*active_tab_index = idx;
}
if ui.small_button("").clicked() {
*on_close_tab = Some(idx);
}
ui.separator();
} }
})
if ui.small_button("").clicked() {
*on_close_tab = Some(idx);
}
ui.separator();
}
if let Some(tab) = tabs.get(*active_tab_index) {
ui.label(format!("({} lines)", tab.line_index.total_lines));
}
}); });
// Check if content overflows (tabs exceed screen width)
let content_width = scroll_output.content_size.x;
let viewport_width = scroll_output.inner_rect.width();
let content_overflows = content_width > viewport_width;
// Handle mouse wheel scrolling when hovering over tabs and content overflows
let mut should_update_offset = false;
if content_overflows && ui.rect_contains_pointer(scroll_output.inner_rect) {
// Get raw scroll delta outside of any closures
let raw_scroll_y = ui.input(|i| i.raw_scroll_delta.y);
// Check for raw mouse wheel events
if raw_scroll_y != 0.0 {
// Use vertical scroll (mouse wheel) for horizontal scrolling
let scroll_amount = -raw_scroll_y * 2.0;
scroll_offset = (scroll_offset + scroll_amount).max(0.0);
// Clamp to valid range
let max_offset = (content_width - viewport_width).max(0.0);
scroll_offset = scroll_offset.min(max_offset);
should_update_offset = true;
}
} else {
// Update offset from ScrollArea state (in case of other interactions)
scroll_offset = scroll_output.state.offset.x;
should_update_offset = true;
}
// Store the offset outside of any input closures
if should_update_offset {
ui.ctx().data_mut(|d| {
d.insert_persisted(scroll_id, scroll_offset);
});
}
}); });
} }