tabs scroll
This commit is contained in:
13
src/theme.rs
13
src/theme.rs
@@ -6,7 +6,6 @@ pub struct ColorPalette {
|
||||
pub bg_primary: egui::Color32, // Main background
|
||||
pub bg_secondary: egui::Color32, // Secondary panels
|
||||
pub bg_tertiary: egui::Color32, // Elevated elements
|
||||
pub bg_hover: egui::Color32, // Hover states
|
||||
|
||||
// Accent colors
|
||||
pub accent_primary: egui::Color32, // Primary purple accent
|
||||
@@ -20,14 +19,8 @@ pub struct ColorPalette {
|
||||
|
||||
// UI element colors
|
||||
pub selection: egui::Color32,
|
||||
pub highlight: egui::Color32,
|
||||
pub line_number: egui::Color32,
|
||||
pub border: egui::Color32,
|
||||
|
||||
// Status colors
|
||||
pub success: egui::Color32,
|
||||
pub warning: egui::Color32,
|
||||
pub error: egui::Color32,
|
||||
}
|
||||
|
||||
impl ColorPalette {
|
||||
@@ -37,7 +30,6 @@ impl ColorPalette {
|
||||
bg_primary: egui::Color32::from_rgb(24, 20, 32), // #18141F
|
||||
bg_secondary: egui::Color32::from_rgb(32, 26, 42), // #201A2A
|
||||
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
|
||||
accent_primary: egui::Color32::from_rgb(138, 98, 208), // #8A62D0
|
||||
@@ -51,14 +43,9 @@ impl ColorPalette {
|
||||
|
||||
// UI elements
|
||||
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
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,29 +13,75 @@ pub fn render_tabs_panel(
|
||||
}
|
||||
|
||||
egui::TopBottomPanel::top("tabs_panel").show(ctx, |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()))
|
||||
};
|
||||
// Get or initialize scroll offset from persistent storage
|
||||
let scroll_id = egui::Id::new("tabs_scroll_offset");
|
||||
let mut scroll_offset: f32 = ui.ctx().data_mut(|d| d.get_persisted(scroll_id).unwrap_or(0.0));
|
||||
|
||||
if ui.selectable_label(is_active, button_text).clicked() {
|
||||
*active_tab_index = idx;
|
||||
// Use horizontal ScrollArea for tabs with hidden scrollbar
|
||||
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);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user