ass_editor/commands/event_commands/
toggle.rs1use super::helpers::collect_event_lines;
4use crate::commands::{CommandResult, EditorCommand};
5use crate::core::{EditorDocument, Position, Range, Result};
6
7#[cfg(not(feature = "std"))]
8use alloc::{
9 format,
10 string::{String, ToString},
11 vec,
12 vec::Vec,
13};
14
15#[derive(Debug, Clone)]
17pub struct ToggleEventTypeCommand {
18 pub event_indices: Vec<usize>,
19 pub description: Option<String>,
20}
21
22impl ToggleEventTypeCommand {
23 pub fn new(event_indices: Vec<usize>) -> Self {
25 Self {
26 event_indices,
27 description: None,
28 }
29 }
30
31 pub fn single(event_index: usize) -> Self {
33 Self::new(vec![event_index])
34 }
35
36 pub fn all() -> Self {
38 Self::new(Vec::new()) }
40
41 #[must_use]
43 pub fn with_description(mut self, description: String) -> Self {
44 self.description = Some(description);
45 self
46 }
47}
48
49impl EditorCommand for ToggleEventTypeCommand {
50 fn execute(&self, document: &mut EditorDocument) -> Result<CommandResult> {
51 let content = document.text();
52 let event_lines = collect_event_lines(&content)?;
53 let mut replacements = Vec::new();
54 let mut total_range: Option<Range> = None;
55
56 for event_line in event_lines {
57 let should_toggle =
58 self.event_indices.is_empty() || self.event_indices.contains(&event_line.index);
59
60 if !should_toggle {
61 continue;
62 }
63
64 let new_line = if event_line.line.starts_with("Dialogue:") {
65 event_line.line.replacen("Dialogue:", "Comment:", 1)
66 } else {
67 event_line.line.replacen("Comment:", "Dialogue:", 1)
68 };
69
70 let change_range = Range::new(
71 Position::new(event_line.start),
72 Position::new(event_line.start + new_line.len()),
73 );
74 total_range = Some(match total_range {
75 Some(existing) => existing.union(&change_range),
76 None => change_range,
77 });
78 replacements.push((event_line.start, event_line.end, new_line));
79 }
80
81 for (start, end, new_line) in replacements.iter().rev() {
82 let range = Range::new(Position::new(*start), Position::new(*end));
83 document.replace(range, new_line)?;
84 }
85
86 let changes_made = replacements.len();
87
88 if changes_made > 0 {
89 Ok(CommandResult::success_with_change(
90 total_range.unwrap_or(Range::new(Position::new(0), Position::new(0))),
91 Position::new(document.len_bytes()),
92 )
93 .with_message(format!("Toggled type for {changes_made} events")))
94 } else {
95 Ok(CommandResult::success().with_message("No events were toggled".to_string()))
96 }
97 }
98
99 fn description(&self) -> &str {
100 self.description.as_deref().unwrap_or("Toggle event type")
101 }
102
103 fn memory_usage(&self) -> usize {
104 core::mem::size_of::<Self>()
105 + self.event_indices.len() * core::mem::size_of::<usize>()
106 + self.description.as_ref().map_or(0, |d| d.len())
107 }
108}