mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-11 22:21:58 +00:00
Merge main into #1735
This commit is contained in:
+2
-1
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@
|
||||
//! await figcraft.execute("node.create", {kind: "frame", name: "Home"}) // engine command → its result
|
||||
//! await figcraft.request("document.inspect") // control method → its result
|
||||
//! await figcraft.commands() // command list
|
||||
//! const {base64} = await figcraft.screenshot() // the canvas as PNG (base64)
|
||||
//! const {data} = await figcraft.screenshot() // the canvas as PNG (base64)
|
||||
//! await figcraft.openFile("home.fig", bytes) // `file.open` with the bytes
|
||||
//! figcraft.captureDownloads(true) // saves stay in the page…
|
||||
//! figcraft.files(); await figcraft.readFile("home.figcraft") // …to be read back
|
||||
|
||||
@@ -233,12 +233,12 @@ pub fn show(app: &mut FigApp, ctx: &Context) {
|
||||
fn panel_windows(app: &mut FigApp, ctx: &Context) {
|
||||
let t = Tokens::get(ctx);
|
||||
let right = ctx.content_rect().right() - 252.0;
|
||||
// (plugin, what was used; None: closed)
|
||||
// (plugin, what was used, in order; None: closed)
|
||||
let mut actions: Vec<(String, Option<Used>)> = Vec::new();
|
||||
for (i, open) in app.session.plugins.panels.iter().enumerate() {
|
||||
let id = open.manifest.id.as_str();
|
||||
let mut keep = true;
|
||||
let mut used = None;
|
||||
let mut used = Vec::new();
|
||||
// Side by side leftwards from the properties panel, three to a row.
|
||||
let at = egui::pos2(right - PANEL_STEP * (i % 3) as f32, 52.0 + 28.0 * (i / 3) as f32);
|
||||
floating(open.title(), ctx).id(Id::unique(("plugin_panel", id))).pivot(Align2::RIGHT_TOP).default_pos(at).open(&mut keep).show(ctx, |ui| {
|
||||
@@ -247,8 +247,8 @@ fn panel_windows(app: &mut FigApp, ctx: &Context) {
|
||||
});
|
||||
if !keep {
|
||||
actions.push((id.to_string(), None));
|
||||
} else if used.is_some() {
|
||||
actions.push((id.to_string(), used));
|
||||
} else {
|
||||
actions.extend(used.into_iter().map(|u| (id.to_string(), Some(u))));
|
||||
}
|
||||
}
|
||||
for (id, used) in actions {
|
||||
@@ -580,12 +580,13 @@ fn form_window(app: &mut FigApp, ctx: &Context) {
|
||||
let title = if label.contains(name.as_str()) { label.to_string() } else { format!("{name}: {label}") };
|
||||
window(&title, ctx).id(Id::unique("plugin_form")).open(&mut open).show(ctx, |ui| {
|
||||
ui.set_width(320.0);
|
||||
match controls(ui, &format!("{}/{}", form.id, form.command), &command.params, &form.values, &t) {
|
||||
Some(Used::Set(name, v)) => {
|
||||
form.values.insert(name, v);
|
||||
for used in controls(ui, &format!("{}/{}", form.id, form.command), &command.params, &form.values, &t) {
|
||||
match used {
|
||||
Used::Set(name, v) => {
|
||||
form.values.insert(name, v);
|
||||
}
|
||||
Used::Pick(control) => pick = Some(control),
|
||||
}
|
||||
Some(Used::Pick(control)) => pick = Some(control),
|
||||
None => {}
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
ui.horizontal(|ui| {
|
||||
@@ -604,8 +605,10 @@ fn form_window(app: &mut FigApp, ctx: &Context) {
|
||||
|
||||
/// Parameters or panel controls in two columns (label, field); buttons in a row share one line,
|
||||
/// the first button filled. Returns what the user did to which control.
|
||||
fn controls(ui: &mut Ui, salt: &str, params: &[Param], values: &Map<String, Value>, t: &Tokens) -> Option<Used> {
|
||||
let mut changed = None;
|
||||
fn controls(ui: &mut Ui, salt: &str, params: &[Param], values: &Map<String, Value>, t: &Tokens) -> Vec<Used> {
|
||||
// In order: a tap's press and release share a frame, so a field that loses the keyboard
|
||||
// commits in the same frame as the button that took it.
|
||||
let mut used = Vec::new();
|
||||
let mut first_button = true;
|
||||
egui::Grid::new(("plugin_controls", salt)).num_columns(2).spacing([12.0, 8.0]).show(ui, |ui| {
|
||||
for row in params.chunk_by(|a, b| a.kind == ParamKind::Button && b.kind == ParamKind::Button) {
|
||||
@@ -643,13 +646,11 @@ fn controls(ui: &mut Ui, salt: &str, params: &[Param], values: &Map<String, Valu
|
||||
field(ui, Id::unique(("plugin_control", salt, &p.name)), p, ¤t)
|
||||
}
|
||||
};
|
||||
if hit.is_some() {
|
||||
changed = hit;
|
||||
}
|
||||
used.extend(hit);
|
||||
ui.end_row();
|
||||
}
|
||||
});
|
||||
changed
|
||||
used
|
||||
}
|
||||
|
||||
/// Panel images decoded lately, by their `data` (None: it couldn't be shown); the oldest go past
|
||||
|
||||
@@ -183,3 +183,29 @@ fn a_slider_calls_the_plugin_back_once_when_let_go() {
|
||||
let value = u.app.session.plugins.panel("org.test.panel").unwrap().values["opacity"].as_f64().unwrap();
|
||||
assert!((value - live).abs() < 1e-9, "the plugin got the dragged value: {value}");
|
||||
}
|
||||
|
||||
/// A trackpad or touch tap sends its press and release in one frame: the field it takes the
|
||||
/// keyboard from commits in the frame the button is clicked, and the plugin gets both, in order.
|
||||
#[test]
|
||||
fn a_tap_on_a_button_keeps_what_was_typed_in_a_field() {
|
||||
let mut u = Ui::new(session());
|
||||
u.ctx.enable_accesskit();
|
||||
u.frame(vec![]);
|
||||
let at = |u: &mut Ui, label: &str| {
|
||||
let nodes = u.frame_output(vec![]).platform_output.accesskit_update.unwrap().nodes;
|
||||
let b = nodes.into_iter().map(|(_, n)| n).find(|n| n.label() == Some(label)).and_then(|n| n.bounds()).unwrap();
|
||||
Pos2::new(((b.x0 + b.x1) / 2.0) as f32, ((b.y0 + b.y1) / 2.0) as f32)
|
||||
};
|
||||
let size = at(&mut u, "Size");
|
||||
u.button(size, true);
|
||||
u.button(size, false);
|
||||
u.frame(vec![]);
|
||||
u.frame(vec![egui::Event::Text("33".into())]);
|
||||
let go = at(&mut u, "Go");
|
||||
let press = |pressed| egui::Event::PointerButton { pos: go, button: egui::PointerButton::Primary, pressed, modifiers: egui::Modifiers::NONE };
|
||||
let before = layers(&u);
|
||||
u.frame(vec![egui::Event::PointerMoved(go), press(true), press(false)]);
|
||||
u.frame(vec![]);
|
||||
assert_eq!(u.app.session.plugins.panel("org.test.panel").unwrap().values["size"], 33.0, "the field's value arrived");
|
||||
assert_eq!(layers(&u), before + 2, "the field's commit and the button each called the plugin");
|
||||
}
|
||||
|
||||
+2
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user