Feat: WIP pattern view redesign
Some checks failed
Deploy Website / deploy (push) Failing after 4m50s

This commit is contained in:
2026-02-22 03:26:48 +01:00
parent 52406c7374
commit 003ee0518e
9 changed files with 636 additions and 127 deletions

View File

@@ -11,8 +11,6 @@ use crate::views::{dict_view, engine_view, help_view, main_view, patterns_view};
use super::InputContext;
const STEPS_PER_PAGE: usize = 32;
pub fn handle_mouse(ctx: &mut InputContext, mouse: MouseEvent, term: Rect) {
let kind = mouse.kind;
let col = mouse.column;
@@ -156,7 +154,7 @@ fn handle_scroll(ctx: &mut InputContext, col: u16, row: u16, term: Rect, up: boo
}
}
Page::Patterns => {
let [banks_area, _gap, patterns_area] = patterns_view::layout(body);
let [banks_area, patterns_area, _] = patterns_view::layout(body);
if contains(banks_area, col, row) {
if up {
@@ -304,13 +302,7 @@ fn handle_main_click(ctx: &mut InputContext, col: u16, row: u16, area: Rect) {
return;
}
let pattern = ctx.app.current_edit_pattern();
let has_viz = ctx.app.audio.config.show_scope
|| ctx.app.audio.config.show_spectrum
|| ctx.app.audio.config.show_preview;
let seq_h = main_view::sequencer_height(pattern.length, ctx.app.editor_ctx.step);
let (_, sequencer_area) =
main_view::viz_seq_split(main_area, ctx.app.audio.config.layout, has_viz, seq_h);
let sequencer_area = main_view::sequencer_rect(ctx.app, main_area);
if !contains(sequencer_area, col, row) {
return;
@@ -324,9 +316,10 @@ fn handle_main_click(ctx: &mut InputContext, col: u16, row: u16, area: Rect) {
fn hit_test_grid(ctx: &InputContext, col: u16, row: u16, area: Rect) -> Option<usize> {
let pattern = ctx.app.current_edit_pattern();
let length = pattern.length;
let page = ctx.app.editor_ctx.step / STEPS_PER_PAGE;
let page_start = page * STEPS_PER_PAGE;
let steps_on_page = (page_start + STEPS_PER_PAGE).min(length) - page_start;
let spp = ctx.app.editor_ctx.steps_per_page.get();
let page = ctx.app.editor_ctx.step / spp;
let page_start = page * spp;
let steps_on_page = (page_start + spp).min(length) - page_start;
for (tile_rect, step_offset) in main_view::grid_layout(area, steps_on_page) {
if contains(tile_rect, col, row) {
@@ -343,7 +336,7 @@ fn hit_test_grid(ctx: &InputContext, col: u16, row: u16, area: Rect) -> Option<u
// --- Patterns page ---
fn handle_patterns_click(ctx: &mut InputContext, col: u16, row: u16, area: Rect) {
let [banks_area, _gap, patterns_area] = patterns_view::layout(area);
let [banks_area, patterns_area, _] = patterns_view::layout(area);
if contains(banks_area, col, row) {
if let Some(bank) = hit_test_patterns_list(ctx, col, row, banks_area, true) {
@@ -366,9 +359,9 @@ fn hit_test_patterns_list(
is_banks: bool,
) -> Option<usize> {
use crate::model::{MAX_BANKS, MAX_PATTERNS};
use ratatui::widgets::{Block, Borders};
let [_title, inner] =
Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).areas(area);
let inner = Block::default().borders(Borders::ALL).inner(area);
let max_items = if is_banks { MAX_BANKS } else { MAX_PATTERNS };
let cursor = if is_banks {
@@ -377,7 +370,14 @@ fn hit_test_patterns_list(
ctx.app.patterns_nav.pattern_cursor
};
let max_visible = (inner.height as usize).max(1);
let available = inner.height as usize;
// Patterns column: cursor row takes 2 lines
let max_visible = if is_banks {
available.max(1)
} else {
available.saturating_sub(1).max(1)
};
let scroll_offset = if max_items <= max_visible {
0
} else {
@@ -387,19 +387,34 @@ fn hit_test_patterns_list(
};
let visible_count = max_items.min(max_visible);
let row_height = (inner.height / visible_count as u16).max(1);
if row < inner.y {
return None;
}
let relative_y = row - inner.y;
let visible_idx = (relative_y / row_height) as usize;
if visible_idx < visible_count {
let idx = scroll_offset + visible_idx;
if idx < max_items {
return Some(idx);
if is_banks {
let row_height = (inner.height / visible_count as u16).max(1);
let relative_y = row - inner.y;
let visible_idx = (relative_y / row_height) as usize;
if visible_idx < visible_count {
let idx = scroll_offset + visible_idx;
if idx < max_items {
return Some(idx);
}
}
} else {
let mut y = inner.y;
for visible_idx in 0..visible_count {
let idx = scroll_offset + visible_idx;
let row_h: u16 = if idx == cursor { 2 } else { 1 };
let actual_h = row_h.min(inner.y + inner.height - y);
if row >= y && row < y + actual_h {
return Some(idx);
}
y += actual_h;
if y >= inner.y + inner.height {
break;
}
}
}