Some kind of refactoring
This commit is contained in:
220
src/services/clipboard.rs
Normal file
220
src/services/clipboard.rs
Normal file
@@ -0,0 +1,220 @@
|
||||
use crate::model::{Bank, Pattern, Project};
|
||||
use crate::state::{CopiedStepData, CopiedSteps};
|
||||
|
||||
fn annotate_copy_name(name: &Option<String>) -> Option<String> {
|
||||
match name {
|
||||
Some(n) if !n.ends_with(" (copy)") => Some(format!("{n} (copy)")),
|
||||
Some(n) => Some(n.clone()),
|
||||
None => Some("(copy)".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_pattern(project: &Project, bank: usize, pattern: usize) -> Pattern {
|
||||
project.banks[bank].patterns[pattern].clone()
|
||||
}
|
||||
|
||||
pub fn paste_pattern(
|
||||
project: &mut Project,
|
||||
bank: usize,
|
||||
pattern: usize,
|
||||
source: &Pattern,
|
||||
) {
|
||||
let mut pat = source.clone();
|
||||
pat.name = annotate_copy_name(&source.name);
|
||||
project.banks[bank].patterns[pattern] = pat;
|
||||
}
|
||||
|
||||
pub fn copy_bank(project: &Project, bank: usize) -> Bank {
|
||||
project.banks[bank].clone()
|
||||
}
|
||||
|
||||
pub fn paste_bank(project: &mut Project, bank: usize, source: &Bank) -> usize {
|
||||
let mut b = source.clone();
|
||||
b.name = annotate_copy_name(&source.name);
|
||||
project.banks[bank] = b;
|
||||
project.banks[bank].patterns.len()
|
||||
}
|
||||
|
||||
pub fn copy_steps(
|
||||
project: &Project,
|
||||
bank: usize,
|
||||
pattern: usize,
|
||||
indices: &[usize],
|
||||
) -> (CopiedSteps, Vec<String>) {
|
||||
let pat = project.pattern_at(bank, pattern);
|
||||
let mut steps = Vec::new();
|
||||
let mut scripts = Vec::new();
|
||||
|
||||
for &idx in indices {
|
||||
if let Some(step) = pat.step(idx) {
|
||||
let resolved = pat.resolve_script(idx).unwrap_or("").to_string();
|
||||
scripts.push(resolved.clone());
|
||||
steps.push(CopiedStepData {
|
||||
script: resolved,
|
||||
active: step.active,
|
||||
source: step.source,
|
||||
original_index: idx,
|
||||
name: step.name.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let copied = CopiedSteps {
|
||||
bank,
|
||||
pattern,
|
||||
steps,
|
||||
};
|
||||
(copied, scripts)
|
||||
}
|
||||
|
||||
pub struct PasteResult {
|
||||
pub count: usize,
|
||||
pub compile_targets: Vec<usize>,
|
||||
}
|
||||
|
||||
pub fn paste_steps(
|
||||
project: &mut Project,
|
||||
bank: usize,
|
||||
pattern: usize,
|
||||
cursor: usize,
|
||||
copied: &CopiedSteps,
|
||||
) -> PasteResult {
|
||||
let pat_len = project.pattern_at(bank, pattern).length;
|
||||
let same_pattern = copied.bank == bank && copied.pattern == pattern;
|
||||
let mut compile_targets = Vec::new();
|
||||
|
||||
for (i, data) in copied.steps.iter().enumerate() {
|
||||
let target = cursor + i;
|
||||
if target >= pat_len {
|
||||
break;
|
||||
}
|
||||
if let Some(step) = project.pattern_at_mut(bank, pattern).step_mut(target) {
|
||||
let source = if same_pattern { data.source } else { None };
|
||||
step.active = data.active;
|
||||
step.source = source;
|
||||
step.name = data.name.clone();
|
||||
if source.is_some() {
|
||||
step.script.clear();
|
||||
step.command = None;
|
||||
} else {
|
||||
step.script = data.script.clone();
|
||||
}
|
||||
}
|
||||
compile_targets.push(target);
|
||||
}
|
||||
|
||||
PasteResult {
|
||||
count: copied.steps.len(),
|
||||
compile_targets,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn link_paste_steps(
|
||||
project: &mut Project,
|
||||
bank: usize,
|
||||
pattern: usize,
|
||||
cursor: usize,
|
||||
copied: &CopiedSteps,
|
||||
) -> Option<usize> {
|
||||
if copied.bank != bank || copied.pattern != pattern {
|
||||
return None;
|
||||
}
|
||||
|
||||
let pat_len = project.pattern_at(bank, pattern).length;
|
||||
|
||||
for (i, data) in copied.steps.iter().enumerate() {
|
||||
let target = cursor + i;
|
||||
if target >= pat_len {
|
||||
break;
|
||||
}
|
||||
let source_idx = if data.source.is_some() {
|
||||
data.source
|
||||
} else {
|
||||
Some(data.original_index)
|
||||
};
|
||||
if source_idx == Some(target) {
|
||||
continue;
|
||||
}
|
||||
if let Some(step) = project.pattern_at_mut(bank, pattern).step_mut(target) {
|
||||
step.source = source_idx;
|
||||
step.script.clear();
|
||||
step.command = None;
|
||||
}
|
||||
}
|
||||
|
||||
Some(copied.steps.len())
|
||||
}
|
||||
|
||||
pub fn harden_steps(
|
||||
project: &mut Project,
|
||||
bank: usize,
|
||||
pattern: usize,
|
||||
indices: &[usize],
|
||||
) -> usize {
|
||||
let pat = project.pattern_at(bank, pattern);
|
||||
let resolutions: Vec<(usize, String)> = indices
|
||||
.iter()
|
||||
.filter_map(|&idx| {
|
||||
let step = pat.step(idx)?;
|
||||
step.source?;
|
||||
let script = pat.resolve_script(idx)?.to_string();
|
||||
Some((idx, script))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let count = resolutions.len();
|
||||
for (idx, script) in resolutions {
|
||||
if let Some(s) = project.pattern_at_mut(bank, pattern).step_mut(idx) {
|
||||
s.source = None;
|
||||
s.script = script;
|
||||
}
|
||||
}
|
||||
|
||||
count
|
||||
}
|
||||
|
||||
pub fn duplicate_steps(
|
||||
project: &mut Project,
|
||||
bank: usize,
|
||||
pattern: usize,
|
||||
indices: &[usize],
|
||||
) -> PasteResult {
|
||||
let pat = project.pattern_at(bank, pattern);
|
||||
let pat_len = pat.length;
|
||||
let paste_at = *indices.last().unwrap() + 1;
|
||||
|
||||
let dupe_data: Vec<(bool, String, Option<usize>)> = indices
|
||||
.iter()
|
||||
.filter_map(|&idx| {
|
||||
let step = pat.step(idx)?;
|
||||
let script = pat.resolve_script(idx).unwrap_or("").to_string();
|
||||
let source = step.source;
|
||||
Some((step.active, script, source))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut compile_targets = Vec::new();
|
||||
for (i, (active, script, source)) in dupe_data.into_iter().enumerate() {
|
||||
let target = paste_at + i;
|
||||
if target >= pat_len {
|
||||
break;
|
||||
}
|
||||
if let Some(step) = project.pattern_at_mut(bank, pattern).step_mut(target) {
|
||||
step.active = active;
|
||||
step.source = source;
|
||||
if source.is_some() {
|
||||
step.script.clear();
|
||||
step.command = None;
|
||||
} else {
|
||||
step.script = script;
|
||||
step.command = None;
|
||||
}
|
||||
}
|
||||
compile_targets.push(target);
|
||||
}
|
||||
|
||||
PasteResult {
|
||||
count: indices.len(),
|
||||
compile_targets,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user