Merge pull request #930 from aniliashenko/text-edit-from-timeline
#637: double-clicking a layer's bar acts like its name; text layers edit their text # Conflicts: # crates/ui-egui/tests/ui_text_edit.rs
This commit is contained in:
commit
0d6adb07bf
|
|
@ -578,6 +578,18 @@ pub fn begin_rename(app: &mut EffectcraftApp, ctx: &egui::Context) {
|
|||
}
|
||||
}
|
||||
|
||||
/// What double-clicking a layer's name or bar does, as in After Effects: a precomp opens, footage
|
||||
/// and solids open in the Layer panel (paint happens there), text is edited in the viewer with the
|
||||
/// whole text selected. `None`: the name renames, the bar does nothing.
|
||||
fn double_click_action(layer: &Layer) -> Option<(String, serde_json::Value)> {
|
||||
match &layer.source {
|
||||
LayerSource::Comp { item } => Some(("comp.open".into(), json!({"comp": item.0}))),
|
||||
LayerSource::Footage { .. } | LayerSource::Solid { .. } => Some(("layer.openLayer".into(), json!({"layer": layer.id.0}))),
|
||||
LayerSource::Text => Some(("text.edit".into(), json!({"layer": layer.id.0}))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Open the rename field on layer `id`; it takes the keyboard focus on its first frame only.
|
||||
fn start_rename(ctx: &egui::Context, id: u64, name: &str) {
|
||||
ctx.data_mut(|d| {
|
||||
|
|
@ -1888,13 +1900,9 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
|||
}
|
||||
}
|
||||
if row_resp.double_clicked() {
|
||||
match &layer.source {
|
||||
LayerSource::Comp { item } => actions.push(("comp.open".into(), json!({"comp": item.0}))),
|
||||
// Footage and solids open in the Layer panel (paint happens there).
|
||||
LayerSource::Footage { .. } | LayerSource::Solid { .. } => {
|
||||
actions.push(("layer.openLayer".into(), json!({"layer": layer.id.0})));
|
||||
}
|
||||
_ => start_rename(&ctx, layer.id.0, &layer.name),
|
||||
match double_click_action(layer) {
|
||||
Some(a) => actions.push(a),
|
||||
None => start_rename(&ctx, layer.id.0, &layer.name),
|
||||
}
|
||||
}
|
||||
layer_context_menu(&row_resp, &comp, layer, &selected, &mut actions);
|
||||
|
|
@ -2098,6 +2106,11 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
|||
if lin.hovered() || lout.hovered() || lin.dragged() || lout.dragged() {
|
||||
ctx.set_cursor_icon(egui::CursorIcon::ResizeHorizontal);
|
||||
}
|
||||
if body.double_clicked()
|
||||
&& let Some(a) = double_click_action(layer)
|
||||
{
|
||||
actions.push(a);
|
||||
}
|
||||
let shift = ui.input(|i| i.modifiers.shift);
|
||||
if let Some(layers) = (body.clicked() && shift).then(|| shift_range(&ctx, cid, &comp, &rows, &selected, layer.id)).flatten() {
|
||||
// Shift-click: the layers from the last one clicked to this one, as in
|
||||
|
|
|
|||
|
|
@ -167,6 +167,18 @@ fn nested_comp_markers_show_on_the_precomp_bar() {
|
|||
assert!((h.state().session.time().seconds() - 1.0).abs() < 0.034, "{}", h.state().session.time().seconds());
|
||||
}
|
||||
|
||||
/// #637: double-clicking a precomp layer's bar opens its comp, as double-clicking its name does.
|
||||
#[test]
|
||||
fn double_clicking_a_precomp_bar_opens_its_comp() {
|
||||
let (mut h, pre, main) = harness();
|
||||
h.state_mut().session.execute("comp.open", json!({"comp": main})).unwrap();
|
||||
h.run_steps(4);
|
||||
let l = h.state().session.project.comp(ItemId(main)).unwrap().layers[0].id.0;
|
||||
let bar = rect(&h, &format!("timeline.layer.{l}.bar"));
|
||||
click_n(&mut h, bar.center(), 2);
|
||||
assert_eq!(h.state().session.active_comp_id(), Some(ItemId(pre)));
|
||||
}
|
||||
|
||||
/// Issue #46: a panel dragged by its panel-menu (hamburger) button onto the left edge of another
|
||||
/// group docks there as its own group; dragging the gap between panels resizes them.
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -438,3 +438,29 @@ fn layer_new_text_menu_and_shortcut_start_typing_into_source_text() {
|
|||
assert_eq!(s.active_comp().unwrap().layer(LayerId(lid)).unwrap().name, "My First Project", "the name follows the text");
|
||||
}
|
||||
}
|
||||
|
||||
/// Double-clicking a text layer in the Timeline, on its name or on its bar, edits its text in the
|
||||
/// Composition viewer with the whole text selected, as in After Effects (Enter renames).
|
||||
#[test]
|
||||
fn timeline_double_click_on_a_text_layer_edits_its_text() {
|
||||
for target in ["row", "bar"] {
|
||||
let mut s = Session::default();
|
||||
s.execute("comp.new", json!({"name": "Type", "width": 640, "height": 360, "duration": 2})).unwrap();
|
||||
let lid = s.execute("layer.newText", json!({"text": "alpha beta"})).unwrap()["layer"].as_u64().unwrap();
|
||||
let mut h = Harness::builder().with_size(egui::vec2(1600.0, 1000.0)).with_step_dt(1.0 / 60.0).build_eframe(move |_| EffectcraftApp::new(s));
|
||||
h.state_mut().show_panel(PanelKind::Composition);
|
||||
h.run_steps(3);
|
||||
let p = rect(&h, &format!("timeline.layer.{lid}.{target}")).center();
|
||||
click(&mut h, p, Modifiers::NONE);
|
||||
click(&mut h, p, Modifiers::NONE);
|
||||
let (layer, text, anchor, caret) = edited(&h);
|
||||
assert_eq!(layer, lid, "{target}");
|
||||
assert_eq!((anchor.min(caret), anchor.max(caret)), (0, 10), "everything selected ({target})");
|
||||
assert!(h.state().auto.find(&format!("timeline.layer.{lid}.nameEdit")).is_none(), "no rename field ({target})");
|
||||
assert_eq!(text, "alpha beta");
|
||||
type_text(&mut h, "gamma");
|
||||
key(&mut h, Key::Escape, Modifiers::NONE);
|
||||
assert!(h.state().session.state.text_edit.is_none(), "Escape commits ({target})");
|
||||
assert_eq!(layer_doc(&h.state().session, LayerId(lid)).unwrap().text, "gamma", "typing replaced the text ({target})");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue