Files
Cagire/src/state/editor.rs
2026-03-05 22:14:28 +01:00

172 lines
3.9 KiB
Rust

use std::cell::Cell;
use std::ops::RangeInclusive;
use cagire_ratatui::Editor;
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub enum EditorTarget {
#[default]
Step,
Prelude,
BankPrelude,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum PatternField {
Length,
Speed,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ScriptField {
Speed,
Length,
}
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub enum PatternPropsField {
#[default]
Name,
Description,
Length,
Speed,
Quantization,
SyncMode,
FollowUp,
ChainBank,
ChainPattern,
}
impl PatternPropsField {
pub fn next(&self, follow_up_is_chain: bool) -> Self {
match self {
Self::Name => Self::Description,
Self::Description => Self::Length,
Self::Length => Self::Speed,
Self::Speed => Self::Quantization,
Self::Quantization => Self::SyncMode,
Self::SyncMode => Self::FollowUp,
Self::FollowUp if follow_up_is_chain => Self::ChainBank,
Self::FollowUp => Self::FollowUp,
Self::ChainBank => Self::ChainPattern,
Self::ChainPattern => Self::ChainPattern,
}
}
pub fn prev(&self, follow_up_is_chain: bool) -> Self {
match self {
Self::Name => Self::Name,
Self::Description => Self::Name,
Self::Length => Self::Description,
Self::Speed => Self::Length,
Self::Quantization => Self::Speed,
Self::SyncMode => Self::Quantization,
Self::FollowUp => Self::SyncMode,
Self::ChainBank => Self::FollowUp,
Self::ChainPattern if follow_up_is_chain => Self::ChainBank,
Self::ChainPattern => Self::FollowUp,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub enum EuclideanField {
#[default]
Pulses,
Steps,
Rotation,
}
impl EuclideanField {
pub fn next(&self) -> Self {
match self {
Self::Pulses => Self::Steps,
Self::Steps => Self::Rotation,
Self::Rotation => Self::Rotation,
}
}
pub fn prev(&self) -> Self {
match self {
Self::Pulses => Self::Pulses,
Self::Steps => Self::Pulses,
Self::Rotation => Self::Steps,
}
}
}
pub struct EditorContext {
pub bank: usize,
pub pattern: usize,
pub step: usize,
pub editor: Editor,
pub selection_anchor: Option<usize>,
pub copied_steps: Option<CopiedSteps>,
pub target: EditorTarget,
pub steps_per_page: Cell<usize>,
pub mouse_selecting: bool,
}
#[derive(Clone)]
pub struct CopiedSteps {
pub bank: usize,
pub pattern: usize,
pub steps: Vec<CopiedStepData>,
}
#[derive(Clone)]
pub struct CopiedStepData {
pub script: String,
pub active: bool,
pub source: Option<u8>,
pub original_index: usize,
pub name: Option<String>,
}
impl EditorContext {
pub fn selection_range(&self) -> Option<RangeInclusive<usize>> {
let anchor = self.selection_anchor?;
let a = anchor.min(self.step);
let b = anchor.max(self.step);
Some(a..=b)
}
pub fn clear_selection(&mut self) {
self.selection_anchor = None;
}
}
impl Default for EditorContext {
fn default() -> Self {
Self {
bank: 0,
pattern: 0,
step: 0,
editor: Editor::new(),
selection_anchor: None,
copied_steps: None,
target: EditorTarget::default(),
steps_per_page: Cell::new(32),
mouse_selecting: false,
}
}
}
pub struct ScriptEditorState {
pub editor: Editor,
pub dirty: bool,
pub focused: bool,
pub mouse_selecting: bool,
}
impl Default for ScriptEditorState {
fn default() -> Self {
Self {
editor: Editor::new(),
dirty: false,
focused: true,
mouse_selecting: false,
}
}
}