use crate::model; use crate::services::clipboard; use crate::state::FlashKind; use super::App; impl App { pub fn copy_pattern(&mut self, bank: usize, pattern: usize) { self.copied_patterns = Some(vec![clipboard::copy_pattern( &self.project_state.project, bank, pattern, )]); self.ui.flash("Pattern copied", 150, FlashKind::Success); } pub fn paste_pattern(&mut self, bank: usize, pattern: usize) { if let Some(patterns) = self.copied_patterns.take() { if let Some(src) = patterns.first() { clipboard::paste_pattern(&mut self.project_state.project, bank, pattern, src); self.project_state.mark_dirty(bank, pattern); if self.editor_ctx.bank == bank && self.editor_ctx.pattern == pattern { self.load_step_to_editor(); } self.ui.flash("Pattern pasted", 150, FlashKind::Success); } self.copied_patterns = Some(patterns); } } pub fn copy_patterns(&mut self, bank: usize, patterns: &[usize]) { self.copied_patterns = Some(clipboard::copy_patterns( &self.project_state.project, bank, patterns, )); let n = patterns.len(); self.ui.flash( &format!("{n} pattern{} copied", if n == 1 { "" } else { "s" }), 150, FlashKind::Success, ); } pub fn paste_patterns(&mut self, bank: usize, start: usize) { if let Some(sources) = self.copied_patterns.take() { let count = clipboard::paste_patterns( &mut self.project_state.project, bank, start, &sources, ); self.copied_patterns = Some(sources); for i in 0..count { self.project_state.mark_dirty(bank, start + i); } if self.editor_ctx.bank == bank { self.load_step_to_editor(); } self.ui.flash( &format!("{count} pattern{} pasted", if count == 1 { "" } else { "s" }), 150, FlashKind::Success, ); } } pub fn shift_patterns_up(&mut self) { let bank = self.patterns_nav.bank_cursor; let patterns = self.patterns_nav.selected_patterns(); let start = *patterns.first().unwrap(); let end = *patterns.last().unwrap(); if let Some(dirty) = clipboard::shift_patterns_up( &mut self.project_state.project, bank, start..=end, ) { for (b, p) in &dirty { self.project_state.mark_dirty(*b, *p); } self.patterns_nav.pattern_cursor -= 1; if let Some(ref mut anchor) = self.patterns_nav.pattern_anchor { *anchor -= 1; } } } pub fn shift_patterns_down(&mut self) { let bank = self.patterns_nav.bank_cursor; let patterns = self.patterns_nav.selected_patterns(); let start = *patterns.first().unwrap(); let end = *patterns.last().unwrap(); if let Some(dirty) = clipboard::shift_patterns_down( &mut self.project_state.project, bank, start..=end, ) { for (b, p) in &dirty { self.project_state.mark_dirty(*b, *p); } self.patterns_nav.pattern_cursor += 1; if let Some(ref mut anchor) = self.patterns_nav.pattern_anchor { *anchor += 1; } } } pub fn copy_bank(&mut self, bank: usize) { self.copied_banks = Some(vec![clipboard::copy_bank( &self.project_state.project, bank, )]); self.ui.flash("Bank copied", 150, FlashKind::Success); } pub fn paste_bank(&mut self, bank: usize) { if let Some(banks) = self.copied_banks.take() { if let Some(src) = banks.first() { let pat_count = clipboard::paste_bank(&mut self.project_state.project, bank, src); for pattern in 0..pat_count { self.project_state.mark_dirty(bank, pattern); } if self.editor_ctx.bank == bank { self.load_step_to_editor(); } self.ui.flash("Bank pasted", 150, FlashKind::Success); } self.copied_banks = Some(banks); } } pub fn copy_banks(&mut self, banks: &[usize]) { self.copied_banks = Some(clipboard::copy_banks( &self.project_state.project, banks, )); let n = banks.len(); self.ui.flash( &format!("{n} bank{} copied", if n == 1 { "" } else { "s" }), 150, FlashKind::Success, ); } pub fn paste_banks(&mut self, start: usize) { if let Some(sources) = self.copied_banks.take() { let count = clipboard::paste_banks( &mut self.project_state.project, start, &sources, ); self.copied_banks = Some(sources); for i in 0..count { let bank = start + i; for pattern in 0..model::MAX_PATTERNS { self.project_state.mark_dirty(bank, pattern); } } if (start..start + count).contains(&self.editor_ctx.bank) { self.load_step_to_editor(); } self.ui.flash( &format!("{count} bank{} pasted", if count == 1 { "" } else { "s" }), 150, FlashKind::Success, ); } } pub fn harden_steps(&mut self) { let (bank, pattern) = self.current_bank_pattern(); let indices = self.selected_steps(); let count = clipboard::harden_steps(&mut self.project_state.project, bank, pattern, &indices); if count == 0 { self.ui.set_status("No linked steps to harden".to_string()); return; } self.project_state.mark_dirty(bank, pattern); self.load_step_to_editor(); self.editor_ctx.clear_selection(); if count == 1 { self.ui.flash("Step hardened", 150, FlashKind::Success); } else { self.ui .flash(&format!("{count} steps hardened"), 150, FlashKind::Success); } } pub fn copy_steps(&mut self) { let (bank, pattern) = self.current_bank_pattern(); let indices = self.selected_steps(); let copied = clipboard::copy_steps( &self.project_state.project, bank, pattern, &indices, ); let count = copied.steps.len(); if let Some(clip) = &mut self.clipboard { let text: String = copied.steps.iter().map(|s| s.script.as_str()).collect::>().join("\n"); let _ = clip.set_text(text); } self.editor_ctx.copied_steps = Some(copied); self.ui .flash(&format!("Copied {count} steps"), 150, FlashKind::Info); } pub fn paste_steps(&mut self, link: &crate::engine::LinkState) { let Some(copied) = self.editor_ctx.copied_steps.take() else { self.ui.set_status("Nothing copied".to_string()); return; }; let (bank, pattern) = self.current_bank_pattern(); let cursor = self.editor_ctx.step; let result = clipboard::paste_steps( &mut self.project_state.project, bank, pattern, cursor, &copied, ); self.editor_ctx.copied_steps = Some(copied); self.project_state.mark_dirty(bank, pattern); self.load_step_to_editor(); for &target in &result.compile_targets { let saved = self.editor_ctx.step; self.editor_ctx.step = target; self.compile_current_step(link); self.editor_ctx.step = saved; } self.editor_ctx.clear_selection(); self.ui.flash( &format!("Pasted {} steps", result.count), 150, FlashKind::Success, ); } pub fn link_paste_steps(&mut self) { let Some(copied) = self.editor_ctx.copied_steps.take() else { self.ui.set_status("Nothing copied".to_string()); return; }; let (bank, pattern) = self.current_bank_pattern(); let cursor = self.editor_ctx.step; let result = clipboard::link_paste_steps( &mut self.project_state.project, bank, pattern, cursor, &copied, ); self.editor_ctx.copied_steps = Some(copied); match result { None => { self.ui .set_status("Can only link within same pattern".to_string()); } Some(count) => { self.project_state.mark_dirty(bank, pattern); self.load_step_to_editor(); self.editor_ctx.clear_selection(); self.ui.flash( &format!("Linked {count} steps"), 150, FlashKind::Success, ); } } } pub fn duplicate_steps(&mut self, link: &crate::engine::LinkState) { let (bank, pattern) = self.current_bank_pattern(); let indices = self.selected_steps(); let result = clipboard::duplicate_steps( &mut self.project_state.project, bank, pattern, &indices, ); self.project_state.mark_dirty(bank, pattern); self.load_step_to_editor(); for &target in &result.compile_targets { let saved = self.editor_ctx.step; self.editor_ctx.step = target; self.compile_current_step(link); self.editor_ctx.step = saved; } self.editor_ctx.clear_selection(); self.ui.flash( &format!("Duplicated {} steps", result.count), 150, FlashKind::Success, ); } }