ass_editor/commands/style_commands/
create.rs1use crate::commands::{CommandResult, EditorCommand};
7use crate::core::{EditorDocument, Position, Range, Result, StyleBuilder};
8
9#[cfg(not(feature = "std"))]
10use alloc::{format, string::String};
11
12#[derive(Debug, Clone)]
14pub struct CreateStyleCommand {
15 pub style_name: String,
16 pub style_builder: StyleBuilder,
17 pub description: Option<String>,
18}
19
20impl CreateStyleCommand {
21 pub fn new(style_name: String, style_builder: StyleBuilder) -> Self {
23 Self {
24 style_name,
25 style_builder,
26 description: None,
27 }
28 }
29
30 #[must_use]
32 pub fn with_description(mut self, description: String) -> Self {
33 self.description = Some(description);
34 self
35 }
36}
37
38impl EditorCommand for CreateStyleCommand {
39 fn execute(&self, document: &mut EditorDocument) -> Result<CommandResult> {
40 let mut builder = self.style_builder.clone();
42 builder = builder.name(&self.style_name);
43 let style_line = builder.build()?;
44
45 let content = document.text();
47 let styles_section_pos = content
48 .find("[V4+ Styles]")
49 .or_else(|| content.find("[V4 Styles]"))
50 .or_else(|| content.find("[Styles]"));
51
52 if let Some(section_start) = styles_section_pos {
53 let section_content = &content[section_start..];
55 if let Some(format_line_end) = section_content.find('\n') {
56 let format_end_pos = section_start + format_line_end + 1;
57
58 let insert_pos = if let Some(next_line_start) = content[format_end_pos..].find('\n')
60 {
61 format_end_pos + next_line_start + 1
62 } else {
63 format_end_pos
64 };
65
66 let insert_text = format!("{style_line}\n");
68 document.insert(Position::new(insert_pos), &insert_text)?;
69
70 let end_pos = Position::new(insert_pos + insert_text.len());
71 return Ok(CommandResult::success_with_change(
72 Range::new(Position::new(insert_pos), end_pos),
73 end_pos,
74 )
75 .with_message(format!("Created style '{}'", self.style_name)));
76 }
77 }
78
79 let styles_section = format!(
81 "\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\n{style_line}\n"
82 );
83
84 let insert_pos = if let Some(events_pos) = content.find("[Events]") {
86 events_pos
87 } else {
88 content.len()
89 };
90
91 document.insert(Position::new(insert_pos), &styles_section)?;
92
93 let end_pos = Position::new(insert_pos + styles_section.len());
94 Ok(CommandResult::success_with_change(
95 Range::new(Position::new(insert_pos), end_pos),
96 end_pos,
97 )
98 .with_message(format!(
99 "Created styles section and style '{}'",
100 self.style_name
101 )))
102 }
103
104 fn description(&self) -> &str {
105 self.description.as_deref().unwrap_or("Create style")
106 }
107
108 fn memory_usage(&self) -> usize {
109 core::mem::size_of::<Self>()
110 + self.style_name.len()
111 + self.description.as_ref().map_or(0, |d| d.len())
112 + 200 }
114}