WIP: half broken
This commit is contained in:
@@ -8,9 +8,9 @@ use crate::app::App;
|
||||
use crate::engine::{LinkState, SequencerSnapshot};
|
||||
use crate::model::SourceSpan;
|
||||
use crate::page::Page;
|
||||
use crate::state::{Modal, PatternField};
|
||||
use crate::state::{Modal, PanelFocus, PatternField, SidePanel};
|
||||
use crate::views::highlight::{self, highlight_line, highlight_line_with_runtime};
|
||||
use crate::widgets::{ConfirmModal, ModalFrame, TextInputModal};
|
||||
use crate::widgets::{ConfirmModal, ModalFrame, SampleBrowser, TextInputModal};
|
||||
|
||||
use super::{audio_view, doc_view, main_view, patterns_view, title_view};
|
||||
|
||||
@@ -55,17 +55,58 @@ pub fn render(frame: &mut Frame, app: &mut App, link: &LinkState, snapshot: &Seq
|
||||
|
||||
render_header(frame, app, link, snapshot, header_area);
|
||||
|
||||
let (page_area, panel_area) = if app.panel.visible && app.panel.side.is_some() {
|
||||
if body_area.width >= 120 {
|
||||
let panel_width = body_area.width * 35 / 100;
|
||||
let [main, side] = Layout::horizontal([
|
||||
Constraint::Fill(1),
|
||||
Constraint::Length(panel_width),
|
||||
])
|
||||
.areas(body_area);
|
||||
(main, Some(side))
|
||||
} else {
|
||||
let panel_height = body_area.height * 40 / 100;
|
||||
let [main, side] = Layout::vertical([
|
||||
Constraint::Fill(1),
|
||||
Constraint::Length(panel_height),
|
||||
])
|
||||
.areas(body_area);
|
||||
(main, Some(side))
|
||||
}
|
||||
} else {
|
||||
(body_area, None)
|
||||
};
|
||||
|
||||
match app.page {
|
||||
Page::Main => main_view::render(frame, app, snapshot, body_area),
|
||||
Page::Patterns => patterns_view::render(frame, app, snapshot, body_area),
|
||||
Page::Audio => audio_view::render(frame, app, link, body_area),
|
||||
Page::Doc => doc_view::render(frame, app, body_area),
|
||||
Page::Main => main_view::render(frame, app, snapshot, page_area),
|
||||
Page::Patterns => patterns_view::render(frame, app, snapshot, page_area),
|
||||
Page::Audio => audio_view::render(frame, app, link, page_area),
|
||||
Page::Doc => doc_view::render(frame, app, page_area),
|
||||
}
|
||||
|
||||
if let Some(side_area) = panel_area {
|
||||
render_side_panel(frame, app, side_area);
|
||||
}
|
||||
|
||||
render_footer(frame, app, footer_area);
|
||||
render_modal(frame, app, snapshot, term);
|
||||
}
|
||||
|
||||
fn render_side_panel(frame: &mut Frame, app: &App, area: Rect) {
|
||||
let focused = app.panel.focus == PanelFocus::Side;
|
||||
match &app.panel.side {
|
||||
Some(SidePanel::SampleBrowser(state)) => {
|
||||
let entries = state.entries();
|
||||
SampleBrowser::new(&entries, state.cursor)
|
||||
.scroll_offset(state.scroll_offset)
|
||||
.search(&state.search_query, state.search_active)
|
||||
.focused(focused)
|
||||
.render(frame, area);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_header(
|
||||
frame: &mut Frame,
|
||||
app: &App,
|
||||
@@ -373,11 +414,19 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
|
||||
.border_color(Color::Magenta)
|
||||
.render_centered(frame, term);
|
||||
}
|
||||
Modal::AddSamplePath(path) => {
|
||||
TextInputModal::new("Add Sample Path", path)
|
||||
.hint("Enter directory path containing samples")
|
||||
.width(60)
|
||||
Modal::AddSamplePath(state) => {
|
||||
use crate::widgets::FileBrowserModal;
|
||||
let entries: Vec<(String, bool)> = state
|
||||
.entries
|
||||
.iter()
|
||||
.map(|e| (e.name.clone(), e.is_dir))
|
||||
.collect();
|
||||
FileBrowserModal::new("Add Sample Path", &state.input, &entries)
|
||||
.selected(state.selected)
|
||||
.scroll_offset(state.scroll_offset)
|
||||
.border_color(Color::Magenta)
|
||||
.width(60)
|
||||
.height(18)
|
||||
.render_centered(frame, term);
|
||||
}
|
||||
Modal::Preview => {
|
||||
@@ -461,8 +510,6 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
|
||||
.border_color(border_color)
|
||||
.render_centered(frame, term);
|
||||
|
||||
let (cursor_row, cursor_col) = app.editor_ctx.text.cursor();
|
||||
|
||||
let trace = if app.ui.runtime_highlight && app.playback.playing {
|
||||
let source = app.current_edit_pattern().resolve_source(app.editor_ctx.step);
|
||||
snapshot.get_trace(app.editor_ctx.bank, app.editor_ctx.pattern, source)
|
||||
@@ -470,7 +517,7 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
|
||||
None
|
||||
};
|
||||
|
||||
let text_lines = app.editor_ctx.text.lines();
|
||||
let text_lines = app.editor_ctx.editor.lines();
|
||||
let mut line_offsets: Vec<usize> = Vec::with_capacity(text_lines.len());
|
||||
let mut offset = 0;
|
||||
for line in text_lines.iter() {
|
||||
@@ -478,68 +525,19 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
|
||||
offset += line.len() + 1;
|
||||
}
|
||||
|
||||
let lines: Vec<Line> = text_lines
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(row, line)| {
|
||||
let mut spans: Vec<Span> = Vec::new();
|
||||
let highlighter = |row: usize, line: &str| -> Vec<(Style, String)> {
|
||||
let line_start = line_offsets[row];
|
||||
let (exec, sel) = match trace {
|
||||
Some(t) => (
|
||||
adjust_spans_for_line(&t.executed_spans, line_start, line.len()),
|
||||
adjust_spans_for_line(&t.selected_spans, line_start, line.len()),
|
||||
),
|
||||
None => (Vec::new(), Vec::new()),
|
||||
};
|
||||
highlight::highlight_line_with_runtime(line, &exec, &sel)
|
||||
};
|
||||
|
||||
let line_start = line_offsets[row];
|
||||
let (exec_spans, sel_spans) = if let Some(t) = trace {
|
||||
(
|
||||
adjust_spans_for_line(&t.executed_spans, line_start, line.len()),
|
||||
adjust_spans_for_line(&t.selected_spans, line_start, line.len()),
|
||||
)
|
||||
} else {
|
||||
(Vec::new(), Vec::new())
|
||||
};
|
||||
|
||||
let tokens = highlight::highlight_line_with_runtime(line, &exec_spans, &sel_spans);
|
||||
|
||||
if row == cursor_row {
|
||||
let mut col = 0;
|
||||
for (style, text) in tokens {
|
||||
let text_len = text.chars().count();
|
||||
if cursor_col >= col && cursor_col < col + text_len {
|
||||
let before =
|
||||
text.chars().take(cursor_col - col).collect::<String>();
|
||||
let cursor_char = text.chars().nth(cursor_col - col).unwrap_or(' ');
|
||||
let after =
|
||||
text.chars().skip(cursor_col - col + 1).collect::<String>();
|
||||
|
||||
if !before.is_empty() {
|
||||
spans.push(Span::styled(before, style));
|
||||
}
|
||||
spans.push(Span::styled(
|
||||
cursor_char.to_string(),
|
||||
Style::default().bg(Color::White).fg(Color::Black),
|
||||
));
|
||||
if !after.is_empty() {
|
||||
spans.push(Span::styled(after, style));
|
||||
}
|
||||
} else {
|
||||
spans.push(Span::styled(text, style));
|
||||
}
|
||||
col += text_len;
|
||||
}
|
||||
if cursor_col >= col {
|
||||
spans.push(Span::styled(
|
||||
" ",
|
||||
Style::default().bg(Color::White).fg(Color::Black),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
for (style, text) in tokens {
|
||||
spans.push(Span::styled(text, style));
|
||||
}
|
||||
}
|
||||
|
||||
Line::from(spans)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let paragraph = Paragraph::new(lines);
|
||||
frame.render_widget(paragraph, inner);
|
||||
app.editor_ctx.editor.render(frame, inner, &highlighter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user