mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 18:27:02 -06:00
Merge pull request #1127 from storytold/fix/1111-paragraph-align-shortcuts
#1111: Ctrl+Shift+L, C, R, J and F align paragraphs
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
@@ -189,6 +189,16 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
|
||||
("view.textThreads", "Hide Text Threads", "Cmd+Shift+Y", "{} toggle the thread lines between threaded text frames"),
|
||||
("view.gradientAnnotator", "Hide Gradient Annotator", "Cmd+Alt+G", "{} toggle the Gradient tool's annotator"),
|
||||
("type.hiddenCharacters", "Show Hidden Characters", "Cmd+Alt+I", "{} toggle markers for spaces, paragraph ends and story ends"),
|
||||
("type.alignLeft", "Align left", "Cmd+Shift+L", "{} align the selected type's paragraphs (or those the Type tool's selection touches) left"),
|
||||
(
|
||||
"type.alignCenter",
|
||||
"Align center",
|
||||
"Cmd+Shift+C",
|
||||
"{} align the selected type's paragraphs (or those the Type tool's selection touches) centred",
|
||||
),
|
||||
("type.alignRight", "Align right", "Cmd+Shift+R", "{} align the selected type's paragraphs (or those the Type tool's selection touches) right"),
|
||||
("type.justifyLeft", "Justify with last line aligned left", "Cmd+Shift+J", "{} justify the selected type's paragraphs, last line aligned left"),
|
||||
("type.justifyAll", "Justify all lines", "Cmd+Shift+F", "{} justify every line of the selected type's paragraphs"),
|
||||
(
|
||||
"type.bold",
|
||||
"Bold",
|
||||
@@ -994,6 +1004,9 @@ pub fn run_ui_command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<R
|
||||
"type.hiddenCharacters" => flag(&mut app.ui.view.hidden_chars),
|
||||
"type.bold" => crate::panels::character::toggle_face(app, Face::Bold),
|
||||
"type.italic" => crate::panels::character::toggle_face(app, Face::Italic),
|
||||
id if let Some((_, justify)) = crate::panels::paragraph::ALIGN_COMMANDS.iter().find(|c| c.0 == id) => {
|
||||
crate::panels::paragraph::align(app, justify)
|
||||
}
|
||||
"view.gradientAnnotator" => flag(&mut app.ui.view.gradient_annotator),
|
||||
"effect.last" => match app.last_effect.clone() {
|
||||
Some((e, params)) => {
|
||||
@@ -1876,6 +1889,7 @@ pub fn enabled(app: &VectorcraftApp, id: &str) -> bool {
|
||||
// Save is off for a clean document that already has its own file.
|
||||
"file.save" => app.session.active().is_some_and(|d| d.path.is_none() || d.converted || d.is_dirty()),
|
||||
"type.bold" | "type.italic" => crate::panels::character::text_style(app).is_some(),
|
||||
id if crate::panels::paragraph::ALIGN_COMMANDS.iter().any(|c| c.0 == id) => crate::panels::character::text_style(app).is_some(),
|
||||
"file.reveal" => app.services.reveal.is_some() && app.session.active().is_some_and(|d| d.path.is_some()),
|
||||
"file.place"
|
||||
| "file.export.svg"
|
||||
|
||||
@@ -28,6 +28,24 @@ fn format(app: &mut VectorcraftApp, p: Value) {
|
||||
para_cmd(app, "text.setFormat", p);
|
||||
}
|
||||
|
||||
/// The alignment shortcuts' commands (Cmd+Shift+L, C, R, J and F, as in page layout apps) and the
|
||||
/// `justify` each sets ([`align`]).
|
||||
pub const ALIGN_COMMANDS: [(&str, &str); 5] = [
|
||||
("type.alignLeft", "left"),
|
||||
("type.alignCenter", "center"),
|
||||
("type.alignRight", "right"),
|
||||
("type.justifyLeft", "justifyLeft"),
|
||||
("type.justifyAll", "justifyAll"),
|
||||
];
|
||||
|
||||
/// Align the paragraphs of the selected type, or those the Type tool's selection touches, as
|
||||
/// `justify` (an [`ALIGN_COMMANDS`] alignment, #1111).
|
||||
pub(crate) fn align(app: &mut VectorcraftApp, justify: &str) -> Result<Value, String> {
|
||||
text_style(app).ok_or("select some type first")?;
|
||||
para_cmd(app, "text.setStyle", json!({ "justify": justify }));
|
||||
Ok(Value::Null)
|
||||
}
|
||||
|
||||
fn para_cmd(app: &mut VectorcraftApp, cmd: &str, mut p: Value) {
|
||||
if let Some((id, a, b)) = super::character::text_editing(app) {
|
||||
super::character::end_typing(app);
|
||||
|
||||
@@ -511,6 +511,44 @@ mod tests {
|
||||
assert!(!app.ui.view.bounding_box);
|
||||
}
|
||||
|
||||
/// Cmd+Shift+L, C, R, J and F align paragraphs (#1111): every paragraph of the selected type,
|
||||
/// or while the Type tool edits text, those its selection touches.
|
||||
#[test]
|
||||
fn cmd_shift_letters_align_paragraphs() {
|
||||
use vectorcraft_doc::Justify;
|
||||
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
|
||||
app.session.execute("file.new", &json!({"width": 200, "height": 200})).unwrap();
|
||||
let id = app.session.execute("text.create", &json!({"x": 20, "y": 50, "text": "One\nTwo"})).unwrap()["id"].as_u64().unwrap();
|
||||
let chord =
|
||||
|key| egui::Event::Key { key, physical_key: None, pressed: true, repeat: false, modifiers: Modifiers::COMMAND | Modifiers::SHIFT };
|
||||
let paras = |app: &VectorcraftApp| match &app.session.active().unwrap().doc.node(vectorcraft_doc::NodeId(id)).unwrap().kind {
|
||||
vectorcraft_doc::NodeKind::Text(t) => (0..t.paragraph_count()).map(|i| t.para_at(i).justify).collect::<Vec<_>>(),
|
||||
_ => panic!("text"),
|
||||
};
|
||||
app.session.execute("select.set", &json!({"ids": [id]})).unwrap();
|
||||
for (key, want) in [
|
||||
(Key::C, Justify::Center),
|
||||
(Key::R, Justify::Right),
|
||||
(Key::J, Justify::JustifyLeft),
|
||||
(Key::F, Justify::JustifyAll),
|
||||
(Key::L, Justify::Left),
|
||||
] {
|
||||
frame(&mut app, vec![chord(key)]);
|
||||
assert_eq!(paras(&app), [want, want], "{key:?}");
|
||||
}
|
||||
// With the Type tool, only the paragraph its selection touches.
|
||||
app.select_tool("type");
|
||||
app.session.apply_actions(vec![vectorcraft_tools::Action::Notify("text.editNew".into())]).unwrap();
|
||||
app.session.set_tool_option("select", &json!({"start": 5, "end": 6}));
|
||||
assert!(app.session.tool_wants_text());
|
||||
frame(&mut app, vec![chord(Key::R)]);
|
||||
assert_eq!(paras(&app), [Justify::Left, Justify::Right]);
|
||||
// Nothing selected: nothing to align.
|
||||
app.select_tool("selection");
|
||||
app.session.execute("select.none", &json!({})).unwrap();
|
||||
assert!(!crate::menus::enabled(&app, "type.alignCenter"));
|
||||
}
|
||||
|
||||
/// Tab shows and hides the panels, and in the Type tool it types a tab, without moving the
|
||||
/// keyboard focus on to a field: the keys after it (a tool letter, the next letter typed) still
|
||||
/// work.
|
||||
|
||||
Reference in New Issue
Block a user