Skip to content

Polish and add aborting to several input widgets: no Esc closing parent menus; color picker axis align; repeat on arrow buttons #2276

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions editor/src/messages/layout/layout_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl LayoutMessageHandler {
};
responses.add(callback_message);
}
Widget::ColorButton(color_button) => {
Widget::ColorInput(color_button) => {
let callback_message = match action {
WidgetValueAction::Commit => (color_button.on_commit.callback)(&()),
WidgetValueAction::Update => {
Expand All @@ -99,7 +99,7 @@ impl LayoutMessageHandler {
};

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

// None
let is_none = update_value.get("none").and_then(|x| x.as_bool());
Expand Down Expand Up @@ -139,7 +139,7 @@ impl LayoutMessageHandler {
return (color_button.on_update.callback)(color_button);
}

panic!("ColorButton update was not able to be parsed with color data: {color_button:?}");
panic!("ColorInput update was not able to be parsed with color data: {color_button:?}");
})()
}
};
Expand Down
6 changes: 3 additions & 3 deletions editor/src/messages/layout/utility_types/layout_widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ impl LayoutGroup {
for widget in &mut widgets {
let val = match &mut widget.widget {
Widget::CheckboxInput(x) => &mut x.tooltip,
Widget::ColorButton(x) => &mut x.tooltip,
Widget::ColorInput(x) => &mut x.tooltip,
Widget::CurveInput(x) => &mut x.tooltip,
Widget::DropdownInput(x) => &mut x.tooltip,
Widget::FontInput(x) => &mut x.tooltip,
Expand Down Expand Up @@ -498,7 +498,7 @@ impl<T> Default for WidgetCallback<T> {
pub enum Widget {
BreadcrumbTrailButtons(BreadcrumbTrailButtons),
CheckboxInput(CheckboxInput),
ColorButton(ColorButton),
ColorInput(ColorInput),
CurveInput(CurveInput),
DropdownInput(DropdownInput),
FontInput(FontInput),
Expand Down Expand Up @@ -571,7 +571,7 @@ impl DiffUpdate {
let mut tooltip_shortcut = match &mut widget_holder.widget {
Widget::BreadcrumbTrailButtons(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
Widget::CheckboxInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
Widget::ColorButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
Widget::ColorInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
Widget::DropdownInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
Widget::FontInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
Widget::IconButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ pub struct ImageButton {

#[derive(Clone, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder, specta::Type)]
#[derivative(Debug, PartialEq, Default)]
pub struct ColorButton {
pub struct ColorInput {
#[widget_builder(constructor)]
pub value: FillChoice,

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

#[serde(skip)]
#[derivative(Debug = "ignore", PartialEq = "ignore")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub enum NavigationMessage {
BeginCanvasTilt { was_dispatched_from_menu: bool },
BeginCanvasZoom,
CanvasPan { delta: DVec2 },
CanvasPanAbortPrepare { x_not_y_axis: bool },
CanvasPanAbort { x_not_y_axis: bool },
CanvasPanByViewportFraction { delta: DVec2 },
CanvasPanMouseWheel { use_y_as_x: bool },
CanvasTiltResetAndZoomTo100Percent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct NavigationMessageHandler {
navigation_operation: NavigationOperation,
mouse_position: ViewportPosition,
finish_operation_with_click: bool,
abortable_pan_start: Option<f64>,
}

impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for NavigationMessageHandler {
Expand Down Expand Up @@ -141,6 +142,28 @@ impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for Navigation
responses.add(BroadcastEvent::CanvasTransformed);
responses.add(DocumentMessage::PTZUpdate);
}
NavigationMessage::CanvasPanAbortPrepare { x_not_y_axis } => {
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
log::error!("Could not get PTZ in CanvasPanAbortPrepare");
return;
};
self.abortable_pan_start = Some(if x_not_y_axis { ptz.pan.x } else { ptz.pan.y });
}
NavigationMessage::CanvasPanAbort { x_not_y_axis } => {
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
log::error!("Could not get PTZ in CanvasPanAbort");
return;
};
if let Some(abortable_pan_start) = self.abortable_pan_start {
if x_not_y_axis {
ptz.pan.x = abortable_pan_start;
} else {
ptz.pan.y = abortable_pan_start;
}
}
self.abortable_pan_start = None;
responses.add(DocumentMessage::PTZUpdate);
}
NavigationMessage::CanvasPanByViewportFraction { delta } => {
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
log::error!("Could not get node graph PTZ in CanvasPanByViewportFraction");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3303,7 +3303,7 @@ fn static_input_properties() -> InputProperties {
"assign_colors_gradient".to_string(),
Box::new(|node_id, index, context| {
let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?;
let gradient_row = node_properties::color_widget(document_node, node_id, index, input_name, ColorButton::default().allow_none(false), true);
let gradient_row = node_properties::color_widget(document_node, node_id, index, input_name, ColorInput::default().allow_none(false), true);
Ok(vec![gradient_row])
}),
);
Expand All @@ -3329,7 +3329,7 @@ fn static_input_properties() -> InputProperties {
"mask_stencil".to_string(),
Box::new(|node_id, index, context| {
let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?;
let mask = node_properties::color_widget(document_node, node_id, index, input_name, ColorButton::default(), true);
let mask = node_properties::color_widget(document_node, node_id, index, input_name, ColorInput::default(), true);
Ok(vec![mask])
}),
);
Expand Down Expand Up @@ -3403,7 +3403,7 @@ fn static_input_properties() -> InputProperties {
node_id,
index,
input_name,
ColorButton::default().allow_none(false),
ColorInput::default().allow_none(false),
true,
)])
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1822,7 +1822,7 @@ impl NodeGraphMessageHandler {
// If only one node is selected then show the preview or stop previewing button
if let Some(node_id) = previewing {
let button = TextButton::new("End Preview")
.icon(Some("Rescale".to_string()))
.icon(Some("FrameAll".to_string()))
.tooltip("Restore preview to the graph output")
.on_update(move |_| NodeGraphMessage::TogglePreview { node_id }.into())
.widget_holder();
Expand All @@ -1834,7 +1834,7 @@ impl NodeGraphMessageHandler {
.any(|export| matches!(export, NodeInput::Node { node_id: export_node_id, .. } if *export_node_id == node_id));
if selection_is_not_already_the_output && no_other_selections {
let button = TextButton::new("Preview")
.icon(Some("Rescale".to_string()))
.icon(Some("FrameAll".to_string()))
.tooltip("Preview selected node/layer (Shortcut: Alt-click node/layer)")
.on_update(move |_| NodeGraphMessage::TogglePreview { node_id }.into())
.widget_holder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ pub(crate) fn property_from_type(node_id: NodeId, index: usize, ty: &Type, numbe
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(),
Some(x) if x == TypeId::of::<u64>() => number_widget(document_node, node_id, index, name, number_input.int().min(min(0.)), true).into(),
Some(x) if x == TypeId::of::<String>() => text_widget(document_node, node_id, index, name, true).into(),
Some(x) if x == TypeId::of::<Color>() => color_widget(document_node, node_id, index, name, ColorButton::default().allow_none(false), true),
Some(x) if x == TypeId::of::<Option<Color>>() => color_widget(document_node, node_id, index, name, ColorButton::default().allow_none(true), true),
Some(x) if x == TypeId::of::<Color>() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(false), true),
Some(x) if x == TypeId::of::<Option<Color>>() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(true), true),
Some(x) if x == TypeId::of::<DVec2>() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", None, add_blank_assist),
Some(x) if x == TypeId::of::<UVec2>() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", Some(0.), add_blank_assist),
Some(x) if x == TypeId::of::<IVec2>() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", None, add_blank_assist),
Expand All @@ -152,7 +152,7 @@ pub(crate) fn property_from_type(node_id: NodeId, index: usize, ty: &Type, numbe
font_widgets.into_iter().chain(style_widgets.unwrap_or_default()).collect::<Vec<_>>().into()
}
Some(x) if x == TypeId::of::<Curve>() => curves_widget(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(document_node, node_id, index, name, ColorButton::default().allow_none(false), true),
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(false), true),
Some(x) if x == TypeId::of::<VectorDataTable>() => vector_widget(document_node, node_id, index, name, true).into(),
Some(x) if x == TypeId::of::<RasterFrame>() || x == TypeId::of::<ImageFrameTable<Color>>() || x == TypeId::of::<TextureFrame>() => {
raster_widget(document_node, node_id, index, name, true).into()
Expand Down Expand Up @@ -1067,7 +1067,7 @@ pub fn line_join_widget(document_node: &DocumentNode, node_id: NodeId, index: us
LayoutGroup::Row { widgets }
}

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

// 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
Expand All @@ -1080,7 +1080,7 @@ pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
TaggedValue::Color(color) => widgets.push(
color_button
.value(FillChoice::Solid(*color))
.on_update(update_value(|x: &ColorButton| TaggedValue::Color(x.value.as_solid().unwrap_or_default()), node_id, index))
.on_update(update_value(|x: &ColorInput| TaggedValue::Color(x.value.as_solid().unwrap_or_default()), node_id, index))
.on_commit(commit_value)
.widget_holder(),
),
Expand All @@ -1090,15 +1090,15 @@ pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
Some(color) => FillChoice::Solid(*color),
None => FillChoice::None,
})
.on_update(update_value(|x: &ColorButton| TaggedValue::OptionalColor(x.value.as_solid()), node_id, index))
.on_update(update_value(|x: &ColorInput| TaggedValue::OptionalColor(x.value.as_solid()), node_id, index))
.on_commit(commit_value)
.widget_holder(),
),
TaggedValue::GradientStops(ref x) => widgets.push(
color_button
.value(FillChoice::Gradient(x.clone()))
.on_update(update_value(
|x: &ColorButton| TaggedValue::GradientStops(x.value.as_gradient().cloned().unwrap_or_default()),
|x: &ColorInput| TaggedValue::GradientStops(x.value.as_gradient().cloned().unwrap_or_default()),
node_id,
index,
))
Expand Down Expand Up @@ -1776,7 +1776,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
// if let Some(&TaggedValue::F64(seed)) = &input.as_non_exposed_value() {
// widgets.extend_from_slice(&[
// Separator::new(SeparatorType::Unrelated).widget_holder(),
// IconButton::new("Regenerate", 24)
// IconButton::new("Resync", 24)
// .tooltip("Set a new random seed")
// .on_update({
// let imaginate_node = imaginate_node.clone();
Expand Down Expand Up @@ -1856,7 +1856,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties

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

widgets_first_row.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets_first_row.push(
ColorButton::default()
ColorInput::default()
.value(fill.clone().into())
.on_update(move |x: &ColorButton| {
.on_update(move |x: &ColorInput| {
Message::Batched(Box::new([
match &fill2 {
Fill::None => NodeGraphMessage::SetInputValue {
Expand Down Expand Up @@ -2380,7 +2380,7 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
let line_join_index = 6;
let miter_limit_index = 7;

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

let dash_lengths_val = match &document_node.inputs[dash_lengths_index].as_value() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
})
};
let update_color = |grid, update: fn(&mut GridSnapping) -> Option<&mut Color>| {
update_val::<ColorButton>(grid, move |grid, color| {
update_val::<ColorInput>(grid, move |grid, color| {
if let FillChoice::Solid(color) = color.value {
if let Some(update_color) = update(grid) {
*update_color = color;
Expand Down Expand Up @@ -280,7 +280,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
Separator::new(SeparatorType::Related).widget_holder(),
]);
color_widgets.push(
ColorButton::new(FillChoice::Solid(grid.grid_color))
ColorInput::new(FillChoice::Solid(grid.grid_color))
.tooltip("Grid display color")
.allow_none(false)
.on_update(update_color(grid, |grid| Some(&mut grid.grid_color)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl ToolColorOptions {
color_allow_none: bool,
reset_callback: impl Fn(&IconButton) -> Message + 'static + Send + Sync,
radio_callback: fn(ToolColorType) -> WidgetCallback<()>,
color_callback: impl Fn(&ColorButton) -> Message + 'static + Send + Sync,
color_callback: impl Fn(&ColorInput) -> Message + 'static + Send + Sync,
) -> Vec<WidgetHolder> {
let mut widgets = vec![TextLabel::new(label_text).widget_holder()];

Expand Down Expand Up @@ -112,7 +112,7 @@ impl ToolColorOptions {
widgets.push(radio);
widgets.push(Separator::new(SeparatorType::Related).widget_holder());

let color_button = ColorButton::new(FillChoice::from_optional_color(self.active_color()))
let color_button = ColorInput::new(FillChoice::from_optional_color(self.active_color()))
.allow_none(color_allow_none)
.on_update(color_callback);
widgets.push(color_button.widget_holder());
Expand Down
2 changes: 1 addition & 1 deletion editor/src/messages/tool/tool_messages/brush_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl LayoutHolder for BrushTool {
false,
|_| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(None)).into(),
|color_type: ToolColorType| WidgetCallback::new(move |_| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::ColorType(color_type.clone())).into()),
|color: &ColorButton| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(color.value.as_solid())).into(),
|color: &ColorInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(color.value.as_solid())).into(),
));

widgets.push(Separator::new(SeparatorType::Related).widget_holder());
Expand Down
4 changes: 2 additions & 2 deletions editor/src/messages/tool/tool_messages/ellipse_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl LayoutHolder for EllipseTool {
true,
|_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColor(None)).into(),
|color_type: ToolColorType| WidgetCallback::new(move |_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColorType(color_type.clone())).into()),
|color: &ColorButton| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColor(color.value.as_solid())).into(),
|color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColor(color.value.as_solid())).into(),
);

widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
Expand All @@ -101,7 +101,7 @@ impl LayoutHolder for EllipseTool {
true,
|_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColor(None)).into(),
|color_type: ToolColorType| WidgetCallback::new(move |_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorButton| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColor(color.value.as_solid())).into(),
|color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColor(color.value.as_solid())).into(),
));
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight));
Expand Down
4 changes: 2 additions & 2 deletions editor/src/messages/tool/tool_messages/freehand_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl LayoutHolder for FreehandTool {
true,
|_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(None)).into(),
|color_type: ToolColorType| WidgetCallback::new(move |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColorType(color_type.clone())).into()),
|color: &ColorButton| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(color.value.as_solid())).into(),
|color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(color.value.as_solid())).into(),
);

widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
Expand All @@ -109,7 +109,7 @@ impl LayoutHolder for FreehandTool {
true,
|_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(None)).into(),
|color_type: ToolColorType| WidgetCallback::new(move |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorButton| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(color.value.as_solid())).into(),
|color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(color.value.as_solid())).into(),
));
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight));
Expand Down
2 changes: 1 addition & 1 deletion editor/src/messages/tool/tool_messages/line_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl LayoutHolder for LineTool {
true,
|_| LineToolMessage::UpdateOptions(LineOptionsUpdate::StrokeColor(None)).into(),
|color_type: ToolColorType| WidgetCallback::new(move |_| LineToolMessage::UpdateOptions(LineOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorButton| LineToolMessage::UpdateOptions(LineOptionsUpdate::StrokeColor(color.value.as_solid())).into(),
|color: &ColorInput| LineToolMessage::UpdateOptions(LineOptionsUpdate::StrokeColor(color.value.as_solid())).into(),
);
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight));
Expand Down
Loading