172 lines
3.9 KiB
Rust
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,
|
|
}
|
|
}
|
|
}
|