mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-14 19:26:56 -04:00
Fix #835: a recent colour recolours the selected gradient stop
In the gradient stop popover (and the Color panel), clicking a recent colour replaced the whole gradient with that colour, while the sliders, spectrum and Black and White chips recoloured the selected stop. The recent colours now go through the Color panel's target like the chips. The Swatches panel's recent colours still paint the fill or stroke, as its swatches do. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
97318c188b
commit
79c81d754c
3 files changed
+45
-8
No files matched your search
@@ -496,7 +496,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
(Some(c), _) => components(mode, &c),
|
||||
(None, _) => vec![0.0; mode.labels().len()],
|
||||
};
|
||||
super::recent_colors_row(app, ui);
|
||||
let recent = super::recent_colors_row(app, ui);
|
||||
widgets::divider(ui);
|
||||
// An edit of the active colour with its displayed components (`new`), or a colour clicked with
|
||||
// Alt held for the inactive proxy (`behind`).
|
||||
@@ -585,6 +585,10 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
*new = Some((c, phase, components(mode, &c)));
|
||||
}
|
||||
};
|
||||
// A recent colour, like the chips, recolours the selected gradient stop (or point).
|
||||
if let Some(c) = recent {
|
||||
pick(c, Live::Released, &mut new);
|
||||
}
|
||||
// None / Black / White chips and the hex field.
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 0.0;
|
||||
@@ -691,12 +695,23 @@ mod tests {
|
||||
/// Run the panel for one frame with `events` and `modifiers`; returns the spectrum's rect (when
|
||||
/// the options are shown) and the panel's height.
|
||||
fn frame(app: &mut VectorcraftApp, ctx: &egui::Context, events: Vec<egui::Event>, modifiers: egui::Modifiers) -> (Option<Rect>, f32) {
|
||||
frame_with(app, ctx, events, modifiers, "color-spectrum")
|
||||
}
|
||||
|
||||
/// [`frame`] returning the rect of the panel's widget `id` instead of the spectrum's.
|
||||
fn frame_with(
|
||||
app: &mut VectorcraftApp,
|
||||
ctx: &egui::Context,
|
||||
events: Vec<egui::Event>,
|
||||
modifiers: egui::Modifiers,
|
||||
id: impl std::hash::Hash + std::fmt::Debug,
|
||||
) -> (Option<Rect>, f32) {
|
||||
let mut out = (None, 0.0);
|
||||
let events = std::iter::once(egui::Event::ModifiersChanged(modifiers)).chain(events).collect();
|
||||
let input = egui::RawInput { events, ..Default::default() };
|
||||
let mut full = ctx.run_ui(input, |ui| {
|
||||
show(app, ui);
|
||||
out = (ctx.read_response(ui.id().with("color-spectrum")).map(|r| r.rect), ui.min_rect().height());
|
||||
out = (ctx.read_response(ui.id().with(&id)).map(|r| r.rect), ui.min_rect().height());
|
||||
});
|
||||
full.textures_delta.clear();
|
||||
out
|
||||
@@ -712,6 +727,27 @@ mod tests {
|
||||
frame(app, ctx, vec![], egui::Modifiers::NONE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_recent_colour_recolours_the_selected_gradient_stop() {
|
||||
// #835: it replaced the whole gradient with the colour.
|
||||
let mut app = app();
|
||||
app.run("paint.setFill", json!({"color": "#ff0000"})).unwrap();
|
||||
let stops = json!([{"offset": 0, "color": "#ffffff"}, {"offset": 1, "color": "#000000"}]);
|
||||
app.run("paint.setFill", json!({"gradient": {"stops": stops, "start": [10, 35], "end": [60, 35]}})).unwrap();
|
||||
app.select_tool("gradient");
|
||||
app.run("gradient.selectStop", json!({"index": 1})).unwrap();
|
||||
let red = app.session.recent_colors.iter().position(|c| c.to_hex() == "#ff0000").expect("red is a recent colour");
|
||||
let ctx = egui::Context::default();
|
||||
let none = egui::Modifiers::NONE;
|
||||
let chip = frame_with(&mut app, &ctx, vec![], none, ("recent", red)).0.expect("the chip is drawn").center();
|
||||
let button = |pressed| egui::Event::PointerButton { pos: chip, button: egui::PointerButton::Primary, pressed, modifiers: none };
|
||||
frame(&mut app, &ctx, vec![egui::Event::PointerMoved(chip), button(true)], none);
|
||||
frame(&mut app, &ctx, vec![button(false)], none);
|
||||
let Paint::Gradient(g) = crate::panels::current_paints(&app).0 else { panic!("still a gradient") };
|
||||
let hex: Vec<String> = g.gradient.stops.iter().map(|s| s.color.to_hex()).collect();
|
||||
assert_eq!(hex, ["#ffffff", "#ff0000"]);
|
||||
}
|
||||
|
||||
fn paints_hex(app: &VectorcraftApp) -> (String, String) {
|
||||
let (f, s) = crate::panels::current_paints(app);
|
||||
(f.color().map(|c| c.to_hex()).unwrap_or_default(), s.color().map(|c| c.to_hex()).unwrap_or_default())
|
||||
|
||||
@@ -412,8 +412,8 @@ pub(crate) fn label_or_name(s: &str, built_in: bool) -> &str {
|
||||
}
|
||||
|
||||
/// "Recent Colors" header + a row of chips (the Session's recent colours, which every paint
|
||||
/// command feeds); clicking one applies it to the active proxy (Alt: the inactive one).
|
||||
pub(crate) fn recent_colors_row(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
/// command feeds); returns the one clicked, for the caller to apply.
|
||||
pub(crate) fn recent_colors_row(app: &VectorcraftApp, ui: &mut Ui) -> Option<Color> {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
crate::widgets::subheader(ui, "Recent Colors");
|
||||
let (r, _) = ui.allocate_exact_size(vec2(ui.available_width(), 22.0), Sense::hover());
|
||||
@@ -430,9 +430,7 @@ pub(crate) fn recent_colors_row(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
chosen = Some(*c);
|
||||
}
|
||||
}
|
||||
if let Some(c) = chosen {
|
||||
apply_click(app, ui, json!({"color": color_json(&c)}));
|
||||
}
|
||||
chosen
|
||||
}
|
||||
|
||||
/// A colour as command JSON, keeping its model.
|
||||
|
||||
@@ -642,7 +642,10 @@ fn body(app: &mut VectorcraftApp, ui: &mut Ui, salt: &'static str) {
|
||||
}
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
super::recent_colors_row(app, ui);
|
||||
// A recent colour paints the active proxy (Alt: the inactive one), as a swatch does.
|
||||
if let Some(c) = super::recent_colors_row(app, ui) {
|
||||
super::apply_click(app, ui, json!({"color": super::color_json(&c)}));
|
||||
}
|
||||
widgets::divider(ui);
|
||||
widgets::subheader(ui, tl!("Swatch Tiles"));
|
||||
let query = if pstate(ui.ctx(), "swatch-show-find") { widgets::search_field(ui, find_id(), tl!("Find")) } else { String::new() };
|
||||
|
||||
Reference in new issue
Block a user