Skip to content

Commit ec8c8d6

Browse files
authored
Polish and add aborting to several input widgets: no Esc closing parent menus; color picker axis align; repeat on arrow buttons (#2276)
* Remove color input outline; reduce antialiasing compositing artifacts in color widgets * Rename ColorButton to ColorInput * Add features and aborting to several other widgets - Prevent Esc from closing parent floating menus when aborting - Fix missing icon regression - Gutter resizing abort - Color picker aborts, Shift axis alignment, improve click/drag behavior for gradient spectrum - Scrollbar abort, repeat when held, fix directional arrows when viewport is zoomed - Number input abort, repeat when held * Move ColorInput into the inputs folder * Fix tiny logo
1 parent 0037f51 commit ec8c8d6

38 files changed

+1028
-449
lines changed

editor/src/messages/layout/layout_message_handler.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl LayoutMessageHandler {
8080
};
8181
responses.add(callback_message);
8282
}
83-
Widget::ColorButton(color_button) => {
83+
Widget::ColorInput(color_button) => {
8484
let callback_message = match action {
8585
WidgetValueAction::Commit => (color_button.on_commit.callback)(&()),
8686
WidgetValueAction::Update => {
@@ -99,7 +99,7 @@ impl LayoutMessageHandler {
9999
};
100100

101101
(|| {
102-
let update_value = value.as_object().expect("ColorButton update was not of type: object");
102+
let update_value = value.as_object().expect("ColorInput update was not of type: object");
103103

104104
// None
105105
let is_none = update_value.get("none").and_then(|x| x.as_bool());
@@ -139,7 +139,7 @@ impl LayoutMessageHandler {
139139
return (color_button.on_update.callback)(color_button);
140140
}
141141

142-
panic!("ColorButton update was not able to be parsed with color data: {color_button:?}");
142+
panic!("ColorInput update was not able to be parsed with color data: {color_button:?}");
143143
})()
144144
}
145145
};

editor/src/messages/layout/utility_types/layout_widget.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ impl LayoutGroup {
327327
for widget in &mut widgets {
328328
let val = match &mut widget.widget {
329329
Widget::CheckboxInput(x) => &mut x.tooltip,
330-
Widget::ColorButton(x) => &mut x.tooltip,
330+
Widget::ColorInput(x) => &mut x.tooltip,
331331
Widget::CurveInput(x) => &mut x.tooltip,
332332
Widget::DropdownInput(x) => &mut x.tooltip,
333333
Widget::FontInput(x) => &mut x.tooltip,
@@ -498,7 +498,7 @@ impl<T> Default for WidgetCallback<T> {
498498
pub enum Widget {
499499
BreadcrumbTrailButtons(BreadcrumbTrailButtons),
500500
CheckboxInput(CheckboxInput),
501-
ColorButton(ColorButton),
501+
ColorInput(ColorInput),
502502
CurveInput(CurveInput),
503503
DropdownInput(DropdownInput),
504504
FontInput(FontInput),
@@ -571,7 +571,7 @@ impl DiffUpdate {
571571
let mut tooltip_shortcut = match &mut widget_holder.widget {
572572
Widget::BreadcrumbTrailButtons(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
573573
Widget::CheckboxInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
574-
Widget::ColorButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
574+
Widget::ColorInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
575575
Widget::DropdownInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
576576
Widget::FontInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
577577
Widget::IconButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),

editor/src/messages/layout/utility_types/widgets/button_widgets.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ pub struct ImageButton {
148148

149149
#[derive(Clone, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder, specta::Type)]
150150
#[derivative(Debug, PartialEq, Default)]
151-
pub struct ColorButton {
151+
pub struct ColorInput {
152152
#[widget_builder(constructor)]
153153
pub value: FillChoice,
154154

@@ -174,7 +174,7 @@ pub struct ColorButton {
174174
// Callbacks
175175
#[serde(skip)]
176176
#[derivative(Debug = "ignore", PartialEq = "ignore")]
177-
pub on_update: WidgetCallback<ColorButton>,
177+
pub on_update: WidgetCallback<ColorInput>,
178178

179179
#[serde(skip)]
180180
#[derivative(Debug = "ignore", PartialEq = "ignore")]

editor/src/messages/portfolio/document/navigation/navigation_message.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub enum NavigationMessage {
1111
BeginCanvasTilt { was_dispatched_from_menu: bool },
1212
BeginCanvasZoom,
1313
CanvasPan { delta: DVec2 },
14+
CanvasPanAbortPrepare { x_not_y_axis: bool },
15+
CanvasPanAbort { x_not_y_axis: bool },
1416
CanvasPanByViewportFraction { delta: DVec2 },
1517
CanvasPanMouseWheel { use_y_as_x: bool },
1618
CanvasTiltResetAndZoomTo100Percent,

editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub struct NavigationMessageHandler {
2929
navigation_operation: NavigationOperation,
3030
mouse_position: ViewportPosition,
3131
finish_operation_with_click: bool,
32+
abortable_pan_start: Option<f64>,
3233
}
3334

3435
impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for NavigationMessageHandler {
@@ -141,6 +142,28 @@ impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for Navigation
141142
responses.add(BroadcastEvent::CanvasTransformed);
142143
responses.add(DocumentMessage::PTZUpdate);
143144
}
145+
NavigationMessage::CanvasPanAbortPrepare { x_not_y_axis } => {
146+
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
147+
log::error!("Could not get PTZ in CanvasPanAbortPrepare");
148+
return;
149+
};
150+
self.abortable_pan_start = Some(if x_not_y_axis { ptz.pan.x } else { ptz.pan.y });
151+
}
152+
NavigationMessage::CanvasPanAbort { x_not_y_axis } => {
153+
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
154+
log::error!("Could not get PTZ in CanvasPanAbort");
155+
return;
156+
};
157+
if let Some(abortable_pan_start) = self.abortable_pan_start {
158+
if x_not_y_axis {
159+
ptz.pan.x = abortable_pan_start;
160+
} else {
161+
ptz.pan.y = abortable_pan_start;
162+
}
163+
}
164+
self.abortable_pan_start = None;
165+
responses.add(DocumentMessage::PTZUpdate);
166+
}
144167
NavigationMessage::CanvasPanByViewportFraction { delta } => {
145168
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
146169
log::error!("Could not get node graph PTZ in CanvasPanByViewportFraction");

editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3303,7 +3303,7 @@ fn static_input_properties() -> InputProperties {
33033303
"assign_colors_gradient".to_string(),
33043304
Box::new(|node_id, index, context| {
33053305
let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?;
3306-
let gradient_row = node_properties::color_widget(document_node, node_id, index, input_name, ColorButton::default().allow_none(false), true);
3306+
let gradient_row = node_properties::color_widget(document_node, node_id, index, input_name, ColorInput::default().allow_none(false), true);
33073307
Ok(vec![gradient_row])
33083308
}),
33093309
);
@@ -3329,7 +3329,7 @@ fn static_input_properties() -> InputProperties {
33293329
"mask_stencil".to_string(),
33303330
Box::new(|node_id, index, context| {
33313331
let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?;
3332-
let mask = node_properties::color_widget(document_node, node_id, index, input_name, ColorButton::default(), true);
3332+
let mask = node_properties::color_widget(document_node, node_id, index, input_name, ColorInput::default(), true);
33333333
Ok(vec![mask])
33343334
}),
33353335
);
@@ -3403,7 +3403,7 @@ fn static_input_properties() -> InputProperties {
34033403
node_id,
34043404
index,
34053405
input_name,
3406-
ColorButton::default().allow_none(false),
3406+
ColorInput::default().allow_none(false),
34073407
true,
34083408
)])
34093409
}),

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,7 +1822,7 @@ impl NodeGraphMessageHandler {
18221822
// If only one node is selected then show the preview or stop previewing button
18231823
if let Some(node_id) = previewing {
18241824
let button = TextButton::new("End Preview")
1825-
.icon(Some("Rescale".to_string()))
1825+
.icon(Some("FrameAll".to_string()))
18261826
.tooltip("Restore preview to the graph output")
18271827
.on_update(move |_| NodeGraphMessage::TogglePreview { node_id }.into())
18281828
.widget_holder();
@@ -1834,7 +1834,7 @@ impl NodeGraphMessageHandler {
18341834
.any(|export| matches!(export, NodeInput::Node { node_id: export_node_id, .. } if *export_node_id == node_id));
18351835
if selection_is_not_already_the_output && no_other_selections {
18361836
let button = TextButton::new("Preview")
1837-
.icon(Some("Rescale".to_string()))
1837+
.icon(Some("FrameAll".to_string()))
18381838
.tooltip("Preview selected node/layer (Shortcut: Alt-click node/layer)")
18391839
.on_update(move |_| NodeGraphMessage::TogglePreview { node_id }.into())
18401840
.widget_holder();

editor/src/messages/portfolio/document/node_graph/node_properties.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ pub(crate) fn property_from_type(node_id: NodeId, index: usize, ty: &Type, numbe
140140
Some(x) if x == TypeId::of::<u32>() => number_widget(document_node, node_id, index, name, number_input.int().min(min(0.)).max(max(f64::from(u32::MAX))), true).into(),
141141
Some(x) if x == TypeId::of::<u64>() => number_widget(document_node, node_id, index, name, number_input.int().min(min(0.)), true).into(),
142142
Some(x) if x == TypeId::of::<String>() => text_widget(document_node, node_id, index, name, true).into(),
143-
Some(x) if x == TypeId::of::<Color>() => color_widget(document_node, node_id, index, name, ColorButton::default().allow_none(false), true),
144-
Some(x) if x == TypeId::of::<Option<Color>>() => color_widget(document_node, node_id, index, name, ColorButton::default().allow_none(true), true),
143+
Some(x) if x == TypeId::of::<Color>() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(false), true),
144+
Some(x) if x == TypeId::of::<Option<Color>>() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(true), true),
145145
Some(x) if x == TypeId::of::<DVec2>() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", None, add_blank_assist),
146146
Some(x) if x == TypeId::of::<UVec2>() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", Some(0.), add_blank_assist),
147147
Some(x) if x == TypeId::of::<IVec2>() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", None, add_blank_assist),
@@ -152,7 +152,7 @@ pub(crate) fn property_from_type(node_id: NodeId, index: usize, ty: &Type, numbe
152152
font_widgets.into_iter().chain(style_widgets.unwrap_or_default()).collect::<Vec<_>>().into()
153153
}
154154
Some(x) if x == TypeId::of::<Curve>() => curves_widget(document_node, node_id, index, name, true),
155-
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(document_node, node_id, index, name, ColorButton::default().allow_none(false), true),
155+
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(false), true),
156156
Some(x) if x == TypeId::of::<VectorDataTable>() => vector_widget(document_node, node_id, index, name, true).into(),
157157
Some(x) if x == TypeId::of::<RasterFrame>() || x == TypeId::of::<ImageFrameTable<Color>>() || x == TypeId::of::<TextureFrame>() => {
158158
raster_widget(document_node, node_id, index, name, true).into()
@@ -1067,7 +1067,7 @@ pub fn line_join_widget(document_node: &DocumentNode, node_id: NodeId, index: us
10671067
LayoutGroup::Row { widgets }
10681068
}
10691069

1070-
pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, color_button: ColorButton, blank_assist: bool) -> LayoutGroup {
1070+
pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, color_button: ColorInput, blank_assist: bool) -> LayoutGroup {
10711071
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
10721072

10731073
// Return early with just the label if the input is exposed to the graph, meaning we don't want to show the color picker widget in the Properties panel
@@ -1080,7 +1080,7 @@ pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
10801080
TaggedValue::Color(color) => widgets.push(
10811081
color_button
10821082
.value(FillChoice::Solid(*color))
1083-
.on_update(update_value(|x: &ColorButton| TaggedValue::Color(x.value.as_solid().unwrap_or_default()), node_id, index))
1083+
.on_update(update_value(|x: &ColorInput| TaggedValue::Color(x.value.as_solid().unwrap_or_default()), node_id, index))
10841084
.on_commit(commit_value)
10851085
.widget_holder(),
10861086
),
@@ -1090,15 +1090,15 @@ pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
10901090
Some(color) => FillChoice::Solid(*color),
10911091
None => FillChoice::None,
10921092
})
1093-
.on_update(update_value(|x: &ColorButton| TaggedValue::OptionalColor(x.value.as_solid()), node_id, index))
1093+
.on_update(update_value(|x: &ColorInput| TaggedValue::OptionalColor(x.value.as_solid()), node_id, index))
10941094
.on_commit(commit_value)
10951095
.widget_holder(),
10961096
),
10971097
TaggedValue::GradientStops(ref x) => widgets.push(
10981098
color_button
10991099
.value(FillChoice::Gradient(x.clone()))
11001100
.on_update(update_value(
1101-
|x: &ColorButton| TaggedValue::GradientStops(x.value.as_gradient().cloned().unwrap_or_default()),
1101+
|x: &ColorInput| TaggedValue::GradientStops(x.value.as_gradient().cloned().unwrap_or_default()),
11021102
node_id,
11031103
index,
11041104
))
@@ -1776,7 +1776,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
17761776
// if let Some(&TaggedValue::F64(seed)) = &input.as_non_exposed_value() {
17771777
// widgets.extend_from_slice(&[
17781778
// Separator::new(SeparatorType::Unrelated).widget_holder(),
1779-
// IconButton::new("Regenerate", 24)
1779+
// IconButton::new("Resync", 24)
17801780
// .tooltip("Set a new random seed")
17811781
// .on_update({
17821782
// let imaginate_node = imaginate_node.clone();
@@ -1856,7 +1856,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
18561856

18571857
// widgets.extend_from_slice(&[
18581858
// Separator::new(SeparatorType::Unrelated).widget_holder(),
1859-
// IconButton::new("Rescale", 24)
1859+
// IconButton::new("FrameAll", 24)
18601860
// .tooltip("Set the layer dimensions to this resolution")
18611861
// .on_update(move |_| DialogMessage::RequestComingSoonDialog { issue: None }.into())
18621862
// .widget_holder(),
@@ -2211,9 +2211,9 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
22112211

22122212
widgets_first_row.push(Separator::new(SeparatorType::Unrelated).widget_holder());
22132213
widgets_first_row.push(
2214-
ColorButton::default()
2214+
ColorInput::default()
22152215
.value(fill.clone().into())
2216-
.on_update(move |x: &ColorButton| {
2216+
.on_update(move |x: &ColorInput| {
22172217
Message::Batched(Box::new([
22182218
match &fill2 {
22192219
Fill::None => NodeGraphMessage::SetInputValue {
@@ -2380,7 +2380,7 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
23802380
let line_join_index = 6;
23812381
let miter_limit_index = 7;
23822382

2383-
let color = color_widget(document_node, node_id, color_index, "Color", ColorButton::default(), true);
2383+
let color = color_widget(document_node, node_id, color_index, "Color", ColorInput::default(), true);
23842384
let weight = number_widget(document_node, node_id, weight_index, "Weight", NumberInput::default().unit(" px").min(0.), true);
23852385

23862386
let dash_lengths_val = match &document_node.inputs[dash_lengths_index].as_value() {

editor/src/messages/portfolio/document/overlays/grid_overlays.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
229229
})
230230
};
231231
let update_color = |grid, update: fn(&mut GridSnapping) -> Option<&mut Color>| {
232-
update_val::<ColorButton>(grid, move |grid, color| {
232+
update_val::<ColorInput>(grid, move |grid, color| {
233233
if let FillChoice::Solid(color) = color.value {
234234
if let Some(update_color) = update(grid) {
235235
*update_color = color;
@@ -280,7 +280,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
280280
Separator::new(SeparatorType::Related).widget_holder(),
281281
]);
282282
color_widgets.push(
283-
ColorButton::new(FillChoice::Solid(grid.grid_color))
283+
ColorInput::new(FillChoice::Solid(grid.grid_color))
284284
.tooltip("Grid display color")
285285
.allow_none(false)
286286
.on_update(update_color(grid, |grid| Some(&mut grid.grid_color)))

editor/src/messages/tool/common_functionality/color_selector.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl ToolColorOptions {
7979
color_allow_none: bool,
8080
reset_callback: impl Fn(&IconButton) -> Message + 'static + Send + Sync,
8181
radio_callback: fn(ToolColorType) -> WidgetCallback<()>,
82-
color_callback: impl Fn(&ColorButton) -> Message + 'static + Send + Sync,
82+
color_callback: impl Fn(&ColorInput) -> Message + 'static + Send + Sync,
8383
) -> Vec<WidgetHolder> {
8484
let mut widgets = vec![TextLabel::new(label_text).widget_holder()];
8585

@@ -112,7 +112,7 @@ impl ToolColorOptions {
112112
widgets.push(radio);
113113
widgets.push(Separator::new(SeparatorType::Related).widget_holder());
114114

115-
let color_button = ColorButton::new(FillChoice::from_optional_color(self.active_color()))
115+
let color_button = ColorInput::new(FillChoice::from_optional_color(self.active_color()))
116116
.allow_none(color_allow_none)
117117
.on_update(color_callback);
118118
widgets.push(color_button.widget_holder());

0 commit comments

Comments
 (0)