give secondary music panes a shared pane selection bar

This commit is contained in:
Skyler Lehmkuhl 2026-03-01 10:47:46 -05:00
parent ae7ea1bb46
commit 4ab6fe0504
1 changed files with 118 additions and 3 deletions

View File

@ -5979,13 +5979,128 @@ fn render_pane(
} }
}); });
// Secondary tab selector for music/instrument panes
let secondary_tab_types = [
PaneType::VirtualPiano,
PaneType::PianoRoll,
PaneType::NodeEditor,
];
let show_secondary_tabs = pane_type
.map(|pt| secondary_tab_types.contains(&pt))
.unwrap_or(false);
let tab_size = 24.0;
let secondary_selector_extra_width = if show_secondary_tabs {
8.0 + 3.0 * tab_size + 8.0
} else {
0.0
};
if show_secondary_tabs {
let n = secondary_tab_types.len();
let selector_start_x = icon_button_rect.max.x + 8.0;
let corner_r = 4.0_f32;
let selector_rect = egui::Rect::from_min_size(
egui::pos2(selector_start_x, header_rect.min.y + icon_padding),
egui::vec2(n as f32 * tab_size, tab_size),
);
// Shared background
ui.painter().rect_filled(
selector_rect,
corner_r,
egui::Color32::from_rgba_premultiplied(50, 50, 50, 200),
);
for (i, &tab_type) in secondary_tab_types.iter().enumerate() {
let tab_x = selector_start_x + i as f32 * tab_size;
let tab_rect = egui::Rect::from_min_size(
egui::pos2(tab_x, header_rect.min.y + icon_padding),
egui::vec2(tab_size, tab_size),
);
let is_active = pane_type == Some(tab_type);
// Active tab highlight with per-corner rounding
if is_active {
let cr = corner_r as u8;
let rounding = egui::Rounding {
nw: if i == 0 { cr } else { 0 },
sw: if i == 0 { cr } else { 0 },
ne: if i == n - 1 { cr } else { 0 },
se: if i == n - 1 { cr } else { 0 },
};
ui.painter().rect_filled(
tab_rect,
rounding,
egui::Color32::from_rgba_premultiplied(60, 90, 150, 230),
);
}
// Divider lines between tabs
if i > 0 {
let divider_color = if is_active || pane_type == Some(secondary_tab_types[i - 1]) {
egui::Color32::from_rgba_premultiplied(80, 110, 170, 180)
} else {
egui::Color32::from_gray(70)
};
ui.painter().vline(
tab_x,
tab_rect.y_range(),
egui::Stroke::new(1.0, divider_color),
);
}
// Icon
if let Some(icon) = ctx.icon_cache.get_or_load(tab_type, ui.ctx()) {
let icon_texture_id = icon.id();
ui.painter().image(
icon_texture_id,
tab_rect.shrink(3.0),
egui::Rect::from_min_max(egui::pos2(0.0, 0.0), egui::pos2(1.0, 1.0)),
egui::Color32::WHITE,
);
}
// Interaction
let tab_id = ui.id().with(("secondary_tab", path, i));
let tab_response = ui.interact(tab_rect, tab_id, egui::Sense::click());
if tab_response.hovered() && !is_active {
ui.painter().rect_filled(
tab_rect,
egui::Rounding {
nw: if i == 0 { corner_r as u8 } else { 0 },
sw: if i == 0 { corner_r as u8 } else { 0 },
ne: if i == n - 1 { corner_r as u8 } else { 0 },
se: if i == n - 1 { corner_r as u8 } else { 0 },
},
egui::Color32::from_rgba_premultiplied(70, 70, 70, 180),
);
}
if tab_response.clicked() {
*pane_name = tab_type.to_name().to_string();
}
}
// Outer border
ui.painter().rect_stroke(
selector_rect,
corner_r,
egui::Stroke::new(1.0, egui::Color32::from_gray(80)),
egui::StrokeKind::Middle,
);
}
// Draw pane title in header // Draw pane title in header
let title_text = if let Some(pane_type) = pane_type { let title_text = if let Some(pane_type) = pane_type {
pane_type.display_name() pane_type.display_name()
} else { } else {
pane_name.as_str() pane_name.as_str()
}; };
let title_pos = header_rect.min + egui::vec2(icon_padding * 2.0 + icon_size + 8.0, header_height / 2.0); let title_x_start = icon_padding * 2.0 + icon_size + 8.0 + secondary_selector_extra_width;
let title_pos = header_rect.min + egui::vec2(title_x_start, header_height / 2.0);
ui.painter().text( ui.painter().text(
title_pos, title_pos,
egui::Align2::LEFT_CENTER, egui::Align2::LEFT_CENTER,
@ -5997,8 +6112,8 @@ fn render_pane(
// Create header controls area (positioned after title) // Create header controls area (positioned after title)
let title_width = 150.0; // Approximate width for title let title_width = 150.0; // Approximate width for title
let header_controls_rect = egui::Rect::from_min_size( let header_controls_rect = egui::Rect::from_min_size(
header_rect.min + egui::vec2(icon_padding * 2.0 + icon_size + 8.0 + title_width, 0.0), header_rect.min + egui::vec2(title_x_start + title_width, 0.0),
egui::vec2(header_rect.width() - (icon_padding * 2.0 + icon_size + 8.0 + title_width), header_height), egui::vec2(header_rect.width() - (title_x_start + title_width), header_height),
); );
// Render pane-specific header controls (if pane has them) // Render pane-specific header controls (if pane has them)