Remove widgets built by methods on WidgetHolder

This commit is contained in:
Keavon Chambers 2023-07-31 23:36:12 -07:00
parent de27f2c006
commit 8e87e42f3e
21 changed files with 270 additions and 264 deletions

View File

@ -45,7 +45,7 @@ impl PropertyHolder for ExportDialogMessageHandler {
fn properties(&self) -> Layout { fn properties(&self) -> Layout {
let file_name = vec![ let file_name = vec![
TextLabel::new("File Name").table_align(true).widget_holder(), TextLabel::new("File Name").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextInput::new(&self.file_name) TextInput::new(&self.file_name)
.on_update(|text_input: &TextInput| ExportDialogMessage::FileName(text_input.value.clone()).into()) .on_update(|text_input: &TextInput| ExportDialogMessage::FileName(text_input.value.clone()).into())
.widget_holder(), .widget_holder(),
@ -58,7 +58,7 @@ impl PropertyHolder for ExportDialogMessageHandler {
let export_type = vec![ let export_type = vec![
TextLabel::new("File Type").table_align(true).widget_holder(), TextLabel::new("File Type").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new(entries).selected_index(self.file_type as u32).widget_holder(), RadioInput::new(entries).selected_index(self.file_type as u32).widget_holder(),
]; ];
@ -76,13 +76,13 @@ impl PropertyHolder for ExportDialogMessageHandler {
let export_area = vec![ let export_area = vec![
TextLabel::new("Bounds").table_align(true).widget_holder(), TextLabel::new("Bounds").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
DropdownInput::new(entries).selected_index(Some(index as u32)).widget_holder(), DropdownInput::new(entries).selected_index(Some(index as u32)).widget_holder(),
]; ];
let transparent_background = vec![ let transparent_background = vec![
TextLabel::new("Transparency").table_align(true).widget_holder(), TextLabel::new("Transparency").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
CheckboxInput::new(self.transparent_background) CheckboxInput::new(self.transparent_background)
.disabled(self.file_type == FileType::Jpg) .disabled(self.file_type == FileType::Jpg)
.on_update(move |value: &CheckboxInput| ExportDialogMessage::TransparentBackground(value.checked).into()) .on_update(move |value: &CheckboxInput| ExportDialogMessage::TransparentBackground(value.checked).into())
@ -91,7 +91,7 @@ impl PropertyHolder for ExportDialogMessageHandler {
let resolution = vec![ let resolution = vec![
TextLabel::new("Scale Factor").table_align(true).widget_holder(), TextLabel::new("Scale Factor").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(self.scale_factor)) NumberInput::new(Some(self.scale_factor))
.unit(" ") .unit(" ")
.min(0.) .min(0.)

View File

@ -55,7 +55,7 @@ impl PropertyHolder for NewDocumentDialogMessageHandler {
let name = vec![ let name = vec![
TextLabel::new("Name").table_align(true).widget_holder(), TextLabel::new("Name").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextInput::new(&self.name) TextInput::new(&self.name)
.on_update(|text_input: &TextInput| NewDocumentDialogMessage::Name(text_input.value.clone()).into()) .on_update(|text_input: &TextInput| NewDocumentDialogMessage::Name(text_input.value.clone()).into())
.widget_holder(), .widget_holder(),
@ -63,7 +63,7 @@ impl PropertyHolder for NewDocumentDialogMessageHandler {
let infinite = vec![ let infinite = vec![
TextLabel::new("Infinite Canvas").table_align(true).widget_holder(), TextLabel::new("Infinite Canvas").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
CheckboxInput::new(self.infinite) CheckboxInput::new(self.infinite)
.on_update(|checkbox_input: &CheckboxInput| NewDocumentDialogMessage::Infinite(checkbox_input.checked).into()) .on_update(|checkbox_input: &CheckboxInput| NewDocumentDialogMessage::Infinite(checkbox_input.checked).into())
.widget_holder(), .widget_holder(),
@ -71,7 +71,7 @@ impl PropertyHolder for NewDocumentDialogMessageHandler {
let scale = vec![ let scale = vec![
TextLabel::new("Dimensions").table_align(true).widget_holder(), TextLabel::new("Dimensions").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(self.dimensions.x as f64)) NumberInput::new(Some(self.dimensions.x as f64))
.label("W") .label("W")
.unit(" px") .unit(" px")
@ -81,7 +81,7 @@ impl PropertyHolder for NewDocumentDialogMessageHandler {
.min_width(100) .min_width(100)
.on_update(|number_input: &NumberInput| NewDocumentDialogMessage::DimensionsX(number_input.value.unwrap()).into()) .on_update(|number_input: &NumberInput| NewDocumentDialogMessage::DimensionsX(number_input.value.unwrap()).into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(self.dimensions.y as f64)) NumberInput::new(Some(self.dimensions.y as f64))
.label("H") .label("H")
.unit(" px") .unit(" px")

View File

@ -30,7 +30,7 @@ impl PreferencesDialogMessageHandler {
let zoom_with_scroll = vec![ let zoom_with_scroll = vec![
TextLabel::new("Input").min_width(60).italic(true).widget_holder(), TextLabel::new("Input").min_width(60).italic(true).widget_holder(),
TextLabel::new("Zoom with Scroll").table_align(true).widget_holder(), TextLabel::new("Zoom with Scroll").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
CheckboxInput::new(preferences.zoom_with_scroll) CheckboxInput::new(preferences.zoom_with_scroll)
.tooltip("Use the scroll wheel for zooming instead of vertically panning (not recommended for trackpads)") .tooltip("Use the scroll wheel for zooming instead of vertically panning (not recommended for trackpads)")
.on_update(|checkbox_input: &CheckboxInput| { .on_update(|checkbox_input: &CheckboxInput| {
@ -45,7 +45,7 @@ impl PreferencesDialogMessageHandler {
let imaginate_server_hostname = vec![ let imaginate_server_hostname = vec![
TextLabel::new("Imaginate").min_width(60).italic(true).widget_holder(), TextLabel::new("Imaginate").min_width(60).italic(true).widget_holder(),
TextLabel::new("Server Hostname").table_align(true).widget_holder(), TextLabel::new("Server Hostname").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextInput::new(&preferences.imaginate_server_hostname) TextInput::new(&preferences.imaginate_server_hostname)
.min_width(200) .min_width(200)
.on_update(|text_input: &TextInput| PreferencesMessage::ImaginateServerHostname { hostname: text_input.value.clone() }.into()) .on_update(|text_input: &TextInput| PreferencesMessage::ImaginateServerHostname { hostname: text_input.value.clone() }.into())
@ -55,7 +55,7 @@ impl PreferencesDialogMessageHandler {
let imaginate_refresh_frequency = vec![ let imaginate_refresh_frequency = vec![
TextLabel::new("").min_width(60).widget_holder(), TextLabel::new("").min_width(60).widget_holder(),
TextLabel::new("Refresh Frequency").table_align(true).widget_holder(), TextLabel::new("Refresh Frequency").table_align(true).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(preferences.imaginate_refresh_frequency)) NumberInput::new(Some(preferences.imaginate_refresh_frequency))
.unit(" seconds") .unit(" seconds")
.min(0.) .min(0.)

View File

@ -456,24 +456,10 @@ impl WidgetHolder {
pub fn new(widget: Widget) -> Self { pub fn new(widget: Widget) -> Self {
Self { widget_id: generate_uuid(), widget } Self { widget_id: generate_uuid(), widget }
} }
pub fn section_separator() -> Self {
Separator::new(SeparatorDirection::Horizontal, SeparatorType::Section).widget_holder()
}
pub fn unrelated_separator() -> Self {
Separator::new(SeparatorDirection::Horizontal, SeparatorType::Unrelated).widget_holder()
}
pub fn related_separator() -> Self {
Separator::new(SeparatorDirection::Horizontal, SeparatorType::Related).widget_holder()
}
pub fn text_widget(text: impl Into<String>) -> Self {
TextLabel::new(text).widget_holder()
}
pub fn bold_text(text: impl Into<String>) -> Self {
TextLabel::new(text).bold(true).widget_holder()
}
/// Diffing updates self (where self is old) based on new, updating the list of modifications as it does so. /// Diffing updates self (where self is old) based on new, updating the list of modifications as it does so.
pub fn diff(&mut self, new: Self, widget_path: &mut [usize], widget_diffs: &mut Vec<WidgetDiff>) { pub fn diff(&mut self, new: Self, widget_path: &mut [usize], widget_diffs: &mut Vec<WidgetDiff>) {
// If there have been changes to the acutal widget (not just the id) // If there have been changes to the actual widget (not just the id)
if self.widget != new.widget { if self.widget != new.widget {
// We should update to the new widget value as well as a new widget id // We should update to the new widget value as well as a new widget id
*self = new.clone(); *self = new.clone();

View File

@ -14,7 +14,6 @@ pub struct IconLabel {
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, WidgetBuilder, specta::Type)] #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, WidgetBuilder, specta::Type)]
pub struct Separator { pub struct Separator {
#[widget_builder(constructor)]
pub direction: SeparatorDirection, pub direction: SeparatorDirection,
#[serde(rename = "type")] #[serde(rename = "type")]

View File

@ -1609,9 +1609,9 @@ impl DocumentMessageHandler {
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextLabel::new(SnappingOptions::BoundingBoxes.to_string()).table_align(false).min_width(60).widget_holder(), TextLabel::new(SnappingOptions::BoundingBoxes.to_string()).table_align(false).min_width(60).widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
], ],
}, },
LayoutGroup::Row { LayoutGroup::Row {
@ -1627,25 +1627,25 @@ impl DocumentMessageHandler {
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextLabel::new(SnappingOptions::Points.to_string()).table_align(false).min_width(60).widget_holder(), TextLabel::new(SnappingOptions::Points.to_string()).table_align(false).min_width(60).widget_holder(),
], ],
}, },
]) ])
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
OptionalInput::new(true, "Grid") OptionalInput::new(true, "Grid")
.tooltip("Grid") .tooltip("Grid")
.on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(318) }.into()) .on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(318) }.into())
.widget_holder(), .widget_holder(),
PopoverButton::new("Grid", "Coming soon").widget_holder(), PopoverButton::new("Grid", "Coming soon").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
OptionalInput::new(self.overlays_visible, "Overlays") OptionalInput::new(self.overlays_visible, "Overlays")
.tooltip("Overlays") .tooltip("Overlays")
.on_update(|optional_input: &OptionalInput| DocumentMessage::SetOverlaysVisibility { visible: optional_input.checked }.into()) .on_update(|optional_input: &OptionalInput| DocumentMessage::SetOverlaysVisibility { visible: optional_input.checked }.into())
.widget_holder(), .widget_holder(),
PopoverButton::new("Overlays", "Coming soon").widget_holder(), PopoverButton::new("Overlays", "Coming soon").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new(vec![ RadioInput::new(vec![
RadioEntryData::default() RadioEntryData::default()
.value("normal") .value("normal")
@ -1669,7 +1669,7 @@ impl DocumentMessageHandler {
}) })
.widget_holder(), .widget_holder(),
PopoverButton::new("View Mode", "Coming soon").widget_holder(), PopoverButton::new("View Mode", "Coming soon").widget_holder(),
WidgetHolder::section_separator(), Separator::new(SeparatorType::Section).widget_holder(),
IconButton::new("ZoomIn", 24) IconButton::new("ZoomIn", 24)
.tooltip("Zoom In") .tooltip("Zoom In")
.tooltip_shortcut(action_keys!(NavigationMessageDiscriminant::IncreaseCanvasZoom)) .tooltip_shortcut(action_keys!(NavigationMessageDiscriminant::IncreaseCanvasZoom))
@ -1685,7 +1685,7 @@ impl DocumentMessageHandler {
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ZoomCanvasTo100Percent)) .tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ZoomCanvasTo100Percent))
.on_update(|_| NavigationMessage::SetCanvasZoom { zoom_factor: 1. }.into()) .on_update(|_| NavigationMessage::SetCanvasZoom { zoom_factor: 1. }.into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(self.navigation_handler.snapped_scale() * 100.)) NumberInput::new(Some(self.navigation_handler.snapped_scale() * 100.))
.unit("%") .unit("%")
.min(0.000001) .min(0.000001)
@ -1705,7 +1705,7 @@ impl DocumentMessageHandler {
let rotation_value = self.navigation_handler.snapped_angle() / (std::f64::consts::PI / 180.); let rotation_value = self.navigation_handler.snapped_angle() / (std::f64::consts::PI / 180.);
if rotation_value.abs() > 0.00001 { if rotation_value.abs() > 0.00001 {
widgets.extend([ widgets.extend([
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(rotation_value)) NumberInput::new(Some(rotation_value))
.unit("°") .unit("°")
.step(15.) .step(15.)
@ -1719,7 +1719,7 @@ impl DocumentMessageHandler {
]); ]);
} }
widgets.extend([ widgets.extend([
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
PopoverButton::new( PopoverButton::new(
"Canvas Navigation", "Canvas Navigation",
"Interactive options in this popover menu are coming soon.\nZoom with Shift + MMB Drag or Ctrl + Scroll Wheel Roll.\nRotate with Ctrl + MMB Drag.", "Interactive options in this popover menu are coming soon.\nZoom with Shift + MMB Drag or Ctrl + Scroll Wheel Roll.\nRotate with Ctrl + MMB Drag.",
@ -1744,7 +1744,7 @@ impl DocumentMessageHandler {
.draw_icon( true) .draw_icon( true)
.interactive( false) // TODO: set to true when dialogs are not spawned .interactive( false) // TODO: set to true when dialogs are not spawned
.widget_holder(), .widget_holder(),
WidgetHolder::section_separator(), Separator::new(SeparatorType::Section).widget_holder(),
], ],
}]); }]);
@ -1819,7 +1819,7 @@ impl DocumentMessageHandler {
.disabled(blend_mode.is_none() && !blend_mode_is_mixed) .disabled(blend_mode.is_none() && !blend_mode_is_mixed)
.draw_icon(false) .draw_icon(false)
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(opacity.map(|opacity| opacity * 100.)) NumberInput::new(opacity.map(|opacity| opacity * 100.))
.label("Opacity") .label("Opacity")
.unit("%") .unit("%")
@ -1838,7 +1838,7 @@ impl DocumentMessageHandler {
} }
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::section_separator(), Separator::new(SeparatorType::Section).widget_holder(),
IconButton::new("Folder", 24) IconButton::new("Folder", 24)
.tooltip("New Folder") .tooltip("New Folder")
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder)) .tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder))

View File

@ -197,7 +197,7 @@ impl NodeGraphMessageHandler {
self.widgets[0] = LayoutGroup::Row { self.widgets[0] = LayoutGroup::Row {
widgets: vec![ widgets: vec![
IconLabel::new(icon).tooltip(tooltip).widget_holder(), IconLabel::new(icon).tooltip(tooltip).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
BreadcrumbTrailButtons::new(path.clone()) BreadcrumbTrailButtons::new(path.clone())
.on_update(move |input: &u64| { .on_update(move |input: &u64| {
NodeGraphMessage::ExitNestedNetwork { NodeGraphMessage::ExitNestedNetwork {

View File

@ -18,7 +18,7 @@ use graphene_core::{Cow, Type, TypeDescriptor};
use glam::{DVec2, IVec2}; use glam::{DVec2, IVec2};
pub fn string_properties(text: impl Into<String>) -> Vec<LayoutGroup> { pub fn string_properties(text: impl Into<String>) -> Vec<LayoutGroup> {
let widget = WidgetHolder::text_widget(text); let widget = TextLabel::new(text).widget_holder();
vec![LayoutGroup::Row { widgets: vec![widget] }] vec![LayoutGroup::Row { widgets: vec![widget] }]
} }
@ -54,10 +54,10 @@ fn expose_widget(node_id: NodeId, index: usize, data_type: FrontendGraphDataType
fn add_blank_assist(widgets: &mut Vec<WidgetHolder>) { fn add_blank_assist(widgets: &mut Vec<WidgetHolder>) {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), // TODO: This last one is the separator after the 24px assist. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: This last one is the separator after the 24px assist.
]); ]);
} }
@ -65,8 +65,8 @@ fn start_widgets(document_node: &DocumentNode, node_id: NodeId, index: usize, na
let input = document_node.inputs.get(index).expect("A widget failed to be built because its node's input index is invalid."); let input = document_node.inputs.get(index).expect("A widget failed to be built because its node's input index is invalid.");
let mut widgets = vec![ let mut widgets = vec![
expose_widget(node_id, index, data_type, input.is_exposed()), expose_widget(node_id, index, data_type, input.is_exposed()),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::text_widget(name), TextLabel::new(name).widget_holder(),
]; ];
if blank_assist { if blank_assist {
add_blank_assist(&mut widgets); add_blank_assist(&mut widgets);
@ -84,7 +84,7 @@ fn text_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
} = &document_node.inputs[index] } = &document_node.inputs[index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextInput::new(x.clone()) TextInput::new(x.clone())
.on_update(update_value(|x: &TextInput| TaggedValue::String(x.value.clone()), node_id, index)) .on_update(update_value(|x: &TextInput| TaggedValue::String(x.value.clone()), node_id, index))
.widget_holder(), .widget_holder(),
@ -102,7 +102,7 @@ fn text_area_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
} = &document_node.inputs[index] } = &document_node.inputs[index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextAreaInput::new(x.clone()) TextAreaInput::new(x.clone())
.on_update(update_value(|x: &TextAreaInput| TaggedValue::String(x.value.clone()), node_id, index)) .on_update(update_value(|x: &TextAreaInput| TaggedValue::String(x.value.clone()), node_id, index))
.widget_holder(), .widget_holder(),
@ -120,7 +120,7 @@ fn bool_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
} = &document_node.inputs[index] } = &document_node.inputs[index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
CheckboxInput::new(*x) CheckboxInput::new(*x)
.on_update(update_value(|x: &CheckboxInput| TaggedValue::Bool(x.checked), node_id, index)) .on_update(update_value(|x: &CheckboxInput| TaggedValue::Bool(x.checked), node_id, index))
.widget_holder(), .widget_holder(),
@ -140,13 +140,13 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
} = document_node.inputs[index] } = document_node.inputs[index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(vec2.x)) NumberInput::new(Some(vec2.x))
.label(x) .label(x)
.unit(unit) .unit(unit)
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(input.value.unwrap(), vec2.y)), node_id, index)) .on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(input.value.unwrap(), vec2.y)), node_id, index))
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(vec2.y)) NumberInput::new(Some(vec2.y))
.label(y) .label(y)
.unit(unit) .unit(unit)
@ -161,14 +161,14 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
let update_x = move |input: &NumberInput| TaggedValue::IVec2(IVec2::new(input.value.unwrap() as i32, vec2.y)); let update_x = move |input: &NumberInput| TaggedValue::IVec2(IVec2::new(input.value.unwrap() as i32, vec2.y));
let update_y = move |input: &NumberInput| TaggedValue::IVec2(IVec2::new(vec2.x, input.value.unwrap() as i32)); let update_y = move |input: &NumberInput| TaggedValue::IVec2(IVec2::new(vec2.x, input.value.unwrap() as i32));
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(vec2.x as f64)) NumberInput::new(Some(vec2.x as f64))
.int() .int()
.label(x) .label(x)
.unit(unit) .unit(unit)
.on_update(update_value(update_x, node_id, index)) .on_update(update_value(update_x, node_id, index))
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(vec2.y as f64)) NumberInput::new(Some(vec2.y as f64))
.int() .int()
.label(y) .label(y)
@ -200,7 +200,7 @@ fn vec_f32_input(document_node: &DocumentNode, node_id: NodeId, index: usize, na
} = &document_node.inputs[index] } = &document_node.inputs[index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
text_props text_props
.value(x.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(", ")) .value(x.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(", "))
.on_update(optionally_update_value(move |x: &TextInput| from_string(&x.value), node_id, index)) .on_update(optionally_update_value(move |x: &TextInput| from_string(&x.value), node_id, index))
@ -221,18 +221,18 @@ fn font_inputs(document_node: &DocumentNode, node_id: NodeId, index: usize, name
} = &document_node.inputs[index] } = &document_node.inputs[index]
{ {
first_widgets.extend_from_slice(&[ first_widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
FontInput::new(font.font_family.clone(), font.font_style.clone()) FontInput::new(font.font_family.clone(), font.font_style.clone())
.on_update(update_value(from_font_input, node_id, index)) .on_update(update_value(from_font_input, node_id, index))
.widget_holder(), .widget_holder(),
]); ]);
second_widgets = Some(vec![ second_widgets = Some(vec![
TextLabel::new("").widget_holder(), TextLabel::new("").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
FontInput::new(font.font_family.clone(), font.font_style.clone()) FontInput::new(font.font_family.clone(), font.font_style.clone())
.is_style_picker(true) .is_style_picker(true)
.on_update(update_value(from_font_input, node_id, index)) .on_update(update_value(from_font_input, node_id, index))
@ -251,7 +251,7 @@ fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, na
} = document_node.inputs[index] } = document_node.inputs[index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
number_props number_props
.value(Some(x)) .value(Some(x))
.on_update(update_value(move |x: &NumberInput| TaggedValue::F64(x.value.unwrap()), node_id, index)) .on_update(update_value(move |x: &NumberInput| TaggedValue::F64(x.value.unwrap()), node_id, index))
@ -263,7 +263,7 @@ fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, na
} = document_node.inputs[index] } = document_node.inputs[index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
number_props number_props
.value(Some(x as f64)) .value(Some(x as f64))
.on_update(update_value(move |x: &NumberInput| TaggedValue::U32((x.value.unwrap()) as u32), node_id, index)) .on_update(update_value(move |x: &NumberInput| TaggedValue::U32((x.value.unwrap()) as u32), node_id, index))
@ -275,7 +275,7 @@ fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, na
} = document_node.inputs[index] } = document_node.inputs[index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
number_props number_props
.value(Some(x as f64)) .value(Some(x as f64))
.on_update(update_value(move |x: &NumberInput| TaggedValue::F32((x.value.unwrap()) as f32), node_id, index)) .on_update(update_value(move |x: &NumberInput| TaggedValue::F32((x.value.unwrap()) as f32), node_id, index))
@ -300,7 +300,10 @@ fn color_channel(document_node: &DocumentNode, node_id: u64, index: usize, name:
} }
let entries = vec![entries]; let entries = vec![entries];
widgets.extend_from_slice(&[WidgetHolder::unrelated_separator(), DropdownInput::new(entries).selected_index(Some(mode as u32)).widget_holder()]); widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
DropdownInput::new(entries).selected_index(Some(mode as u32)).widget_holder(),
]);
} }
LayoutGroup::Row { widgets }.with_tooltip("Color Channel") LayoutGroup::Row { widgets }.with_tooltip("Color Channel")
} }
@ -323,7 +326,10 @@ fn blend_mode(document_node: &DocumentNode, node_id: u64, index: usize, name: &s
}) })
.collect(); .collect();
widgets.extend_from_slice(&[WidgetHolder::unrelated_separator(), DropdownInput::new(entries).selected_index(Some(mode as u32)).widget_holder()]); widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
DropdownInput::new(entries).selected_index(Some(mode as u32)).widget_holder(),
]);
} }
LayoutGroup::Row { widgets }.with_tooltip("Formula used for blending") LayoutGroup::Row { widgets }.with_tooltip("Formula used for blending")
} }
@ -344,7 +350,7 @@ fn luminance_calculation(document_node: &DocumentNode, node_id: u64, index: usiz
let entries = vec![entries]; let entries = vec![entries];
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
DropdownInput::new(entries).selected_index(Some(calculation as u32)).widget_holder(), DropdownInput::new(entries).selected_index(Some(calculation as u32)).widget_holder(),
]); ]);
} }
@ -363,7 +369,10 @@ fn line_cap_widget(document_node: &DocumentNode, node_id: u64, index: usize, nam
.map(|(name, val)| RadioEntryData::new(name).on_update(update_value(move |_| TaggedValue::LineCap(val), node_id, index))) .map(|(name, val)| RadioEntryData::new(name).on_update(update_value(move |_| TaggedValue::LineCap(val), node_id, index)))
.collect(); .collect();
widgets.extend_from_slice(&[WidgetHolder::unrelated_separator(), RadioInput::new(entries).selected_index(line_cap as u32).widget_holder()]); widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new(entries).selected_index(line_cap as u32).widget_holder(),
]);
} }
LayoutGroup::Row { widgets } LayoutGroup::Row { widgets }
} }
@ -380,7 +389,10 @@ fn line_join_widget(document_node: &DocumentNode, node_id: u64, index: usize, na
.map(|(name, val)| RadioEntryData::new(name).on_update(update_value(move |_| TaggedValue::LineJoin(val), node_id, index))) .map(|(name, val)| RadioEntryData::new(name).on_update(update_value(move |_| TaggedValue::LineJoin(val), node_id, index)))
.collect(); .collect();
widgets.extend_from_slice(&[WidgetHolder::unrelated_separator(), RadioInput::new(entries).selected_index(line_join as u32).widget_holder()]); widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new(entries).selected_index(line_join as u32).widget_holder(),
]);
} }
LayoutGroup::Row { widgets } LayoutGroup::Row { widgets }
} }
@ -398,7 +410,7 @@ fn fill_type_widget(document_node: &DocumentNode, node_id: u64, index: usize) ->
]; ];
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new(entries) RadioInput::new(entries)
.selected_index(match fill_type { .selected_index(match fill_type {
FillType::None | FillType::Solid => 0, FillType::None | FillType::Solid => 0,
@ -422,7 +434,10 @@ fn gradient_type_widget(document_node: &DocumentNode, node_id: u64, index: usize
RadioEntryData::new("Radial").on_update(update_value(move |_| TaggedValue::GradientType(GradientType::Radial), node_id, index)), RadioEntryData::new("Radial").on_update(update_value(move |_| TaggedValue::GradientType(GradientType::Radial), node_id, index)),
]; ];
widgets.extend_from_slice(&[WidgetHolder::unrelated_separator(), RadioInput::new(entries).selected_index(gradient_type as u32).widget_holder()]); widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new(entries).selected_index(gradient_type as u32).widget_holder(),
]);
} }
LayoutGroup::Row { widgets } LayoutGroup::Row { widgets }
} }
@ -440,7 +455,7 @@ fn gradient_row(row: &mut Vec<WidgetHolder>, positions: &Vec<(f64, Option<Color>
}; };
let color = ColorInput::new(positions[index].1).on_update(update_value(on_update, node_id, input_index)); let color = ColorInput::new(positions[index].1).on_update(update_value(on_update, node_id, input_index));
add_blank_assist(row); add_blank_assist(row);
row.push(WidgetHolder::unrelated_separator()); row.push(Separator::new(SeparatorType::Unrelated).widget_holder());
row.push(color.widget_holder()); row.push(color.widget_holder());
let mut skip_separator = false; let mut skip_separator = false;
@ -456,7 +471,7 @@ fn gradient_row(row: &mut Vec<WidgetHolder>, positions: &Vec<(f64, Option<Color>
}; };
skip_separator = true; skip_separator = true;
row.push(WidgetHolder::related_separator()); row.push(Separator::new(SeparatorType::Related).widget_holder());
row.push( row.push(
IconButton::new("Remove", 16) IconButton::new("Remove", 16)
.tooltip("Remove this gradient stop") .tooltip("Remove this gradient stop")
@ -488,7 +503,7 @@ fn gradient_row(row: &mut Vec<WidgetHolder>, positions: &Vec<(f64, Option<Color>
}; };
if !skip_separator { if !skip_separator {
row.push(WidgetHolder::related_separator()); row.push(Separator::new(SeparatorType::Related).widget_holder());
} }
row.push( row.push(
IconButton::new("Add", 16) IconButton::new("Add", 16)
@ -501,7 +516,7 @@ fn gradient_row(row: &mut Vec<WidgetHolder>, positions: &Vec<(f64, Option<Color>
fn gradient_positions(rows: &mut Vec<LayoutGroup>, document_node: &DocumentNode, name: &str, node_id: u64, input_index: usize) { fn gradient_positions(rows: &mut Vec<LayoutGroup>, document_node: &DocumentNode, name: &str, node_id: u64, input_index: usize) {
let mut widgets = vec![expose_widget(node_id, input_index, FrontendGraphDataType::General, document_node.inputs[input_index].is_exposed())]; let mut widgets = vec![expose_widget(node_id, input_index, FrontendGraphDataType::General, document_node.inputs[input_index].is_exposed())];
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
if let NodeInput::Value { if let NodeInput::Value {
tagged_value: TaggedValue::GradientPositions(gradient_positions), tagged_value: TaggedValue::GradientPositions(gradient_positions),
exposed: false, exposed: false,
@ -532,7 +547,7 @@ fn gradient_positions(rows: &mut Vec<LayoutGroup>, document_node: &DocumentNode,
widgets.push(TextLabel::new("").widget_holder()); widgets.push(TextLabel::new("").widget_holder());
add_blank_assist(&mut widgets); add_blank_assist(&mut widgets);
} }
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(invert); widgets.push(invert);
rows.push(LayoutGroup::Row { widgets }); rows.push(LayoutGroup::Row { widgets });
@ -548,7 +563,7 @@ fn color_widget(document_node: &DocumentNode, node_id: u64, index: usize, name:
if let NodeInput::Value { tagged_value, exposed: false } = &document_node.inputs[index] { if let NodeInput::Value { tagged_value, exposed: false } = &document_node.inputs[index] {
if let &TaggedValue::Color(x) = tagged_value { if let &TaggedValue::Color(x) = tagged_value {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
color_props color_props
.value(Some(x as Color)) .value(Some(x as Color))
.on_update(update_value(|x: &ColorInput| TaggedValue::Color(x.value.unwrap()), node_id, index)) .on_update(update_value(|x: &ColorInput| TaggedValue::Color(x.value.unwrap()), node_id, index))
@ -556,7 +571,7 @@ fn color_widget(document_node: &DocumentNode, node_id: u64, index: usize, name:
]) ])
} else if let &TaggedValue::OptionalColor(x) = tagged_value { } else if let &TaggedValue::OptionalColor(x) = tagged_value {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
color_props color_props
.value(x) .value(x)
.on_update(update_value(|x: &ColorInput| TaggedValue::OptionalColor(x.value), node_id, index)) .on_update(update_value(|x: &ColorInput| TaggedValue::OptionalColor(x.value), node_id, index))
@ -568,7 +583,7 @@ fn color_widget(document_node: &DocumentNode, node_id: u64, index: usize, name:
} }
/// Properties for the input node, with information describing how frames work and a refresh button /// Properties for the input node, with information describing how frames work and a refresh button
pub fn input_properties(_document_node: &DocumentNode, _node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> { pub fn input_properties(_document_node: &DocumentNode, _node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let information = WidgetHolder::text_widget("The graph's input frame is the rasterized artwork under the layer"); let information = TextLabel::new("The graph's input frame is the rasterized artwork under the layer").widget_holder();
let layer_path = context.layer_path.to_vec(); let layer_path = context.layer_path.to_vec();
let refresh_button = TextButton::new("Refresh Input") let refresh_button = TextButton::new("Refresh Input")
.tooltip("Refresh the artwork under the layer") .tooltip("Refresh the artwork under the layer")
@ -656,7 +671,7 @@ pub fn output_properties(_document_node: &DocumentNode, _node_id: NodeId, contex
vec![ vec![
LayoutGroup::Row { widgets: vec![label] }, LayoutGroup::Row { widgets: vec![label] },
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![download_button, WidgetHolder::related_separator(), copy_button], widgets: vec![download_button, Separator::new(SeparatorType::Related).widget_holder(), copy_button],
}, },
] ]
} }
@ -746,7 +761,7 @@ pub fn adjust_channel_mixer_properties(document_node: &DocumentNode, node_id: No
// Output channel choice // Output channel choice
let output_channel_index = 18; let output_channel_index = 18;
let mut output_channel = vec![WidgetHolder::text_widget("Output Channel"), WidgetHolder::unrelated_separator()]; let mut output_channel = vec![TextLabel::new("Output Channel").widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder()];
add_blank_assist(&mut output_channel); add_blank_assist(&mut output_channel);
if let &NodeInput::Value { if let &NodeInput::Value {
tagged_value: TaggedValue::RedGreenBlue(choice), tagged_value: TaggedValue::RedGreenBlue(choice),
@ -802,7 +817,7 @@ pub fn adjust_channel_mixer_properties(document_node: &DocumentNode, node_id: No
pub fn adjust_selective_color_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> { pub fn adjust_selective_color_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
// Colors choice // Colors choice
let colors_index = 38; let colors_index = 38;
let mut colors = vec![WidgetHolder::text_widget("Colors"), WidgetHolder::unrelated_separator()]; let mut colors = vec![TextLabel::new("Colors").widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder()];
add_blank_assist(&mut colors); add_blank_assist(&mut colors);
if let &NodeInput::Value { if let &NodeInput::Value {
tagged_value: TaggedValue::SelectiveColorChoice(choice), tagged_value: TaggedValue::SelectiveColorChoice(choice),
@ -852,7 +867,7 @@ pub fn adjust_selective_color_properties(document_node: &DocumentNode, node_id:
// Mode // Mode
let mode_index = 1; let mode_index = 1;
let mut mode = start_widgets(document_node, node_id, mode_index, "Mode", FrontendGraphDataType::General, true); let mut mode = start_widgets(document_node, node_id, mode_index, "Mode", FrontendGraphDataType::General, true);
mode.push(WidgetHolder::unrelated_separator()); mode.push(Separator::new(SeparatorType::Unrelated).widget_holder());
if let &NodeInput::Value { if let &NodeInput::Value {
tagged_value: TaggedValue::RelativeAbsolute(relative_or_absolute), tagged_value: TaggedValue::RelativeAbsolute(relative_or_absolute),
exposed: false, exposed: false,
@ -934,7 +949,7 @@ pub fn transform_properties(document_node: &DocumentNode, node_id: NodeId, _cont
exposed: false, exposed: false,
} = document_node.inputs[pivot_index] } = document_node.inputs[pivot_index]
{ {
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push( widgets.push(
PivotAssist::new(pivot.into()) PivotAssist::new(pivot.into())
.on_update(|pivot_assist: &PivotAssist| PropertiesPanelMessage::SetPivot { new_position: pivot_assist.position }.into()) .on_update(|pivot_assist: &PivotAssist| PropertiesPanelMessage::SetPivot { new_position: pivot_assist.position }.into())
@ -957,7 +972,7 @@ pub fn transform_properties(document_node: &DocumentNode, node_id: NodeId, _cont
} = document_node.inputs[index] } = document_node.inputs[index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(val.to_degrees().into())) NumberInput::new(Some(val.to_degrees().into()))
.unit("°") .unit("°")
.mode(NumberInputMode::Range) .mode(NumberInputMode::Range)
@ -1024,15 +1039,15 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
let server_status = context.persistent_data.imaginate.server_status(); let server_status = context.persistent_data.imaginate.server_status();
let status_text = server_status.to_text(); let status_text = server_status.to_text();
let mut widgets = vec![ let mut widgets = vec![
WidgetHolder::text_widget("Server"), TextLabel::new("Server").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
IconButton::new("Settings", 24) IconButton::new("Settings", 24)
.tooltip("Preferences: Imaginate") .tooltip("Preferences: Imaginate")
.on_update(|_| DialogMessage::RequestPreferencesDialog.into()) .on_update(|_| DialogMessage::RequestPreferencesDialog.into())
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::bold_text(status_text), TextLabel::new(status_text).bold(true).widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
IconButton::new("Reload", 24) IconButton::new("Reload", 24)
.tooltip("Refresh connection status") .tooltip("Refresh connection status")
.on_update(|_| PortfolioMessage::ImaginateCheckServerStatus.into()) .on_update(|_| PortfolioMessage::ImaginateCheckServerStatus.into())
@ -1040,7 +1055,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
]; ];
if let ImaginateServerStatus::Unavailable | ImaginateServerStatus::Failed(_) = server_status { if let ImaginateServerStatus::Unavailable | ImaginateServerStatus::Failed(_) = server_status {
widgets.extend([ widgets.extend([
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextButton::new("Server Help") TextButton::new("Server Help")
.tooltip("Learn how to connect Imaginate to an image generation server") .tooltip("Learn how to connect Imaginate to an image generation server")
.on_update(|_| { .on_update(|_| {
@ -1079,13 +1094,13 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
let progress = { let progress = {
let status = imaginate_status.to_text(); let status = imaginate_status.to_text();
let widgets = vec![ let widgets = vec![
WidgetHolder::text_widget("Progress"), TextLabel::new("Progress").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::bold_text(status.as_ref()), TextLabel::new(status.as_ref()).bold(true).widget_holder(),
]; ];
LayoutGroup::Row { widgets }.with_tooltip(match imaginate_status { LayoutGroup::Row { widgets }.with_tooltip(match imaginate_status {
ImaginateStatus::Failed(_) => status.as_ref(), ImaginateStatus::Failed(_) => status.as_ref(),
@ -1094,12 +1109,12 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
}; };
let image_controls = { let image_controls = {
let mut widgets = vec![WidgetHolder::text_widget("Image"), WidgetHolder::unrelated_separator()]; let mut widgets = vec![TextLabel::new("Image").widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder()];
let assist_separators = [ let assist_separators = [
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
]; ];
match &imaginate_status { match &imaginate_status {
@ -1149,7 +1164,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
} }
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextButton::new("Generate") TextButton::new("Generate")
.tooltip("Fill layer frame by generating a new image") .tooltip("Fill layer frame by generating a new image")
.on_update({ .on_update({
@ -1161,7 +1176,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
} }
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
TextButton::new("Clear") TextButton::new("Clear")
.tooltip("Remove generated image from the layer frame") .tooltip("Remove generated image from the layer frame")
.disabled(!matches!(imaginate_status, ImaginateStatus::ReadyDone)) .disabled(!matches!(imaginate_status, ImaginateStatus::ReadyDone))
@ -1189,7 +1204,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
} = &document_node.inputs[seed_index] } = &document_node.inputs[seed_index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
IconButton::new("Regenerate", 24) IconButton::new("Regenerate", 24)
.tooltip("Set a new random seed") .tooltip("Set a new random seed")
.on_update({ .on_update({
@ -1205,7 +1220,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
} }
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(seed)) NumberInput::new(Some(seed))
.int() .int()
.min(-((1u64 << f64::MANTISSA_DIGITS) as f64)) .min(-((1u64 << f64::MANTISSA_DIGITS) as f64))
@ -1244,7 +1259,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
let layer_path = context.layer_path.to_vec(); let layer_path = context.layer_path.to_vec();
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
IconButton::new("Rescale", 24) IconButton::new("Rescale", 24)
.tooltip("Set the layer dimensions to this resolution") .tooltip("Set the layer dimensions to this resolution")
.on_update(move |_| { .on_update(move |_| {
@ -1255,7 +1270,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
CheckboxInput::new(!dimensions_is_auto || transform_not_connected) CheckboxInput::new(!dimensions_is_auto || transform_not_connected)
.icon("Edit12px") .icon("Edit12px")
.tooltip({ .tooltip({
@ -1277,7 +1292,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
resolution_index, resolution_index,
)) ))
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(vec2.x)) NumberInput::new(Some(vec2.x))
.label("W") .label("W")
.min(64.) .min(64.)
@ -1290,7 +1305,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
resolution_index, resolution_index,
)) ))
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(vec2.y)) NumberInput::new(Some(vec2.y))
.label("H") .label("H")
.min(64.) .min(64.)
@ -1334,7 +1349,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
let entries = vec![entries]; let entries = vec![entries];
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
DropdownInput::new(entries).selected_index(Some(sampling_method as u32)).widget_holder(), DropdownInput::new(entries).selected_index(Some(sampling_method as u32)).widget_holder(),
]); ]);
} }
@ -1400,7 +1415,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
let layer_reference_input_layer_name = layer_reference_input_layer.as_ref().map(|(layer_name, _)| layer_name); let layer_reference_input_layer_name = layer_reference_input_layer.as_ref().map(|(layer_name, _)| layer_name);
let layer_reference_input_layer_type = layer_reference_input_layer.as_ref().map(|(_, layer_type)| layer_type); let layer_reference_input_layer_type = layer_reference_input_layer.as_ref().map(|(_, layer_type)| layer_type);
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
if !transform_not_connected { if !transform_not_connected {
widgets.push( widgets.push(
LayerReferenceInput::new(layer_path.clone(), layer_reference_input_layer_name.cloned(), layer_reference_input_layer_type.cloned()) LayerReferenceInput::new(layer_path.clone(), layer_reference_input_layer_name.cloned(), layer_reference_input_layer_type.cloned())
@ -1445,7 +1460,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
} = &document_node.inputs[inpaint_index] } = &document_node.inputs[inpaint_index]
{ {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new( RadioInput::new(
[(true, "Inpaint"), (false, "Outpaint")] [(true, "Inpaint"), (false, "Outpaint")]
.into_iter() .into_iter()
@ -1487,7 +1502,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
let entries = vec![entries]; let entries = vec![entries];
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
DropdownInput::new(entries).selected_index(Some(starting_fill as u32)).widget_holder(), DropdownInput::new(entries).selected_index(Some(starting_fill as u32)).widget_holder(),
]); ]);
} }

View File

@ -69,11 +69,11 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
let options_bar = vec![LayoutGroup::Row { let options_bar = vec![LayoutGroup::Row {
widgets: vec![ widgets: vec![
IconLabel::new("NodeArtboard").tooltip("Artboard").widget_holder(), IconLabel::new("NodeArtboard").tooltip("Artboard").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextInput::new(layer.name.clone().unwrap_or_else(|| "Untitled Artboard".to_string())) TextInput::new(layer.name.clone().unwrap_or_else(|| "Untitled Artboard".to_string()))
.on_update(|text_input: &TextInput| PropertiesPanelMessage::ModifyName { name: text_input.value.clone() }.into()) .on_update(|text_input: &TextInput| PropertiesPanelMessage::ModifyName { name: text_input.value.clone() }.into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
PopoverButton::new("Additional Options", "Coming soon").widget_holder(), PopoverButton::new("Additional Options", "Coming soon").widget_holder(),
], ],
}]; }];
@ -91,11 +91,11 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Location").widget_holder(), TextLabel::new("Location").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(layer.transform.x() + pivot.x)) NumberInput::new(Some(layer.transform.x() + pivot.x))
.label("X") .label("X")
.unit(" px") .unit(" px")
@ -107,7 +107,7 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(layer.transform.y() + pivot.y)) NumberInput::new(Some(layer.transform.y() + pivot.y))
.label("Y") .label("Y")
.unit(" px") .unit(" px")
@ -124,15 +124,15 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Dimensions").widget_holder(), TextLabel::new("Dimensions").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
CheckboxInput::new(layer.preserve_aspect) CheckboxInput::new(layer.preserve_aspect)
.icon("Link") .icon("Link")
.tooltip("Preserve Aspect Ratio") .tooltip("Preserve Aspect Ratio")
.on_update(|input: &CheckboxInput| PropertiesPanelMessage::ModifyPreserveAspect { preserve_aspect: input.checked }.into()) .on_update(|input: &CheckboxInput| PropertiesPanelMessage::ModifyPreserveAspect { preserve_aspect: input.checked }.into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(layer.bounding_transform(&render_data).scale_x())) NumberInput::new(Some(layer.bounding_transform(&render_data).scale_x()))
.label("W") .label("W")
.unit(" px") .unit(" px")
@ -146,7 +146,7 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(layer.bounding_transform(&render_data).scale_y())) NumberInput::new(Some(layer.bounding_transform(&render_data).scale_y()))
.label("H") .label("H")
.unit(" px") .unit(" px")
@ -165,11 +165,11 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Background").widget_holder(), TextLabel::new("Background").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
ColorInput::new(Some(*color)) ColorInput::new(Some(*color))
.on_update(|text_input: &ColorInput| { .on_update(|text_input: &ColorInput| {
let fill = if let Some(value) = text_input.value { value } else { Color::TRANSPARENT }; let fill = if let Some(value) = text_input.value { value } else { Color::TRANSPARENT };
@ -208,11 +208,11 @@ pub fn register_artwork_layer_properties(
LayerDataType::Shape(_) => IconLabel::new("NodeShape").tooltip("Shape").widget_holder(), LayerDataType::Shape(_) => IconLabel::new("NodeShape").tooltip("Shape").widget_holder(),
LayerDataType::Layer(_) => IconLabel::new("Layer").tooltip("Layer").widget_holder(), LayerDataType::Layer(_) => IconLabel::new("Layer").tooltip("Layer").widget_holder(),
}, },
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextInput::new(layer.name.clone().unwrap_or_else(|| "Untitled Layer".to_string())) TextInput::new(layer.name.clone().unwrap_or_else(|| "Untitled Layer".to_string()))
.on_update(|text_input: &TextInput| PropertiesPanelMessage::ModifyName { name: text_input.value.clone() }.into()) .on_update(|text_input: &TextInput| PropertiesPanelMessage::ModifyName { name: text_input.value.clone() }.into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
PopoverButton::new("Additional Options", "Coming soon").widget_holder(), PopoverButton::new("Additional Options", "Coming soon").widget_holder(),
], ],
}]; }];
@ -266,11 +266,11 @@ pub fn register_document_graph_properties(mut context: NodePropertiesContext, no
let options_bar = vec![LayoutGroup::Row { let options_bar = vec![LayoutGroup::Row {
widgets: vec![ widgets: vec![
IconLabel::new("File").tooltip("Document").widget_holder(), IconLabel::new("File").tooltip("Document").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextInput::new(document_name) TextInput::new(document_name)
.on_update(|text_input| DocumentMessage::RenameDocument { new_name: text_input.value.clone() }.into()) .on_update(|text_input| DocumentMessage::RenameDocument { new_name: text_input.value.clone() }.into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
PopoverButton::new("Additional Options", "Coming soon").widget_holder(), PopoverButton::new("Additional Options", "Coming soon").widget_holder(),
], ],
}]; }];
@ -294,11 +294,11 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Location").widget_holder(), TextLabel::new("Location").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
PivotAssist::new(layer.pivot.into()) PivotAssist::new(layer.pivot.into())
.on_update(|pivot_assist: &PivotAssist| PropertiesPanelMessage::SetPivot { new_position: pivot_assist.position }.into()) .on_update(|pivot_assist: &PivotAssist| PropertiesPanelMessage::SetPivot { new_position: pivot_assist.position }.into())
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(layer.transform.x() + pivot.x)) NumberInput::new(Some(layer.transform.x() + pivot.x))
.label("X") .label("X")
.unit(" px") .unit(" px")
@ -310,7 +310,7 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(layer.transform.y() + pivot.y)) NumberInput::new(Some(layer.transform.y() + pivot.y))
.label("Y") .label("Y")
.unit(" px") .unit(" px")
@ -327,11 +327,11 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Rotation").widget_holder(), TextLabel::new("Rotation").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(layer.transform.rotation() * 180. / PI)) NumberInput::new(Some(layer.transform.rotation() * 180. / PI))
.unit("°") .unit("°")
.mode(NumberInputMode::Range) .mode(NumberInputMode::Range)
@ -350,15 +350,15 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Scale").widget_holder(), TextLabel::new("Scale").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
CheckboxInput::new(layer.preserve_aspect) CheckboxInput::new(layer.preserve_aspect)
.icon("Link") .icon("Link")
.tooltip("Preserve Aspect Ratio") .tooltip("Preserve Aspect Ratio")
.on_update(|input: &CheckboxInput| PropertiesPanelMessage::ModifyPreserveAspect { preserve_aspect: input.checked }.into()) .on_update(|input: &CheckboxInput| PropertiesPanelMessage::ModifyPreserveAspect { preserve_aspect: input.checked }.into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(layer.transform.scale_x())) NumberInput::new(Some(layer.transform.scale_x()))
.label("X") .label("X")
.unit("") .unit("")
@ -370,7 +370,7 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(layer.transform.scale_y())) NumberInput::new(Some(layer.transform.scale_y()))
.label("Y") .label("Y")
.unit("") .unit("")
@ -387,11 +387,11 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Dimensions").widget_holder(), TextLabel::new("Dimensions").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(layer.bounding_transform(&render_data).scale_x())) NumberInput::new(Some(layer.bounding_transform(&render_data).scale_x()))
.label("W") .label("W")
.unit(" px") .unit(" px")
@ -403,7 +403,7 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(layer.bounding_transform(&render_data).scale_y())) NumberInput::new(Some(layer.bounding_transform(&render_data).scale_y()))
.label("H") .label("H")
.unit(" px") .unit(" px")
@ -433,11 +433,11 @@ fn node_gradient_type(gradient: &Gradient) -> LayoutGroup {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Gradient Type").widget_holder(), TextLabel::new("Gradient Type").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new(vec![ RadioInput::new(vec![
RadioEntryData::new("linear") RadioEntryData::new("linear")
.label("Linear") .label("Linear")
@ -475,11 +475,11 @@ fn node_gradient_color(gradient: &Gradient, position: usize) -> LayoutGroup {
TextLabel::new(value) TextLabel::new(value)
.tooltip("Adjustable by dragging the gradient stops in the viewport with the Gradient tool active") .tooltip("Adjustable by dragging the gradient stops in the viewport with the Gradient tool active")
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
ColorInput::new(gradient_clone.positions[position].1) ColorInput::new(gradient_clone.positions[position].1)
.on_update(move |text_input: &ColorInput| { .on_update(move |text_input: &ColorInput| {
let mut new_gradient = (*gradient_clone).clone(); let mut new_gradient = (*gradient_clone).clone();
@ -499,7 +499,7 @@ fn node_gradient_color(gradient: &Gradient, position: usize) -> LayoutGroup {
}; };
skip_separator = true; skip_separator = true;
widgets.push(WidgetHolder::related_separator()); widgets.push(Separator::new(SeparatorType::Related).widget_holder());
widgets.push(IconButton::new("Remove", 16).tooltip("Remove this gradient stop").on_update(on_update).widget_holder()); widgets.push(IconButton::new("Remove", 16).tooltip("Remove this gradient stop").on_update(on_update).widget_holder());
} }
// Add button // Add button
@ -522,7 +522,7 @@ fn node_gradient_color(gradient: &Gradient, position: usize) -> LayoutGroup {
}; };
if !skip_separator { if !skip_separator {
widgets.push(WidgetHolder::related_separator()); widgets.push(Separator::new(SeparatorType::Related).widget_holder());
} }
widgets.push(IconButton::new("Add", 16).tooltip("Add a gradient stop after this").on_update(on_update).widget_holder()); widgets.push(IconButton::new("Add", 16).tooltip("Add a gradient stop after this").on_update(on_update).widget_holder());
} }
@ -539,11 +539,11 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutGroup> {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Color").widget_holder(), TextLabel::new("Color").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
ColorInput::new(if let Fill::Solid(color) = fill { Some(*color) } else { None }) ColorInput::new(if let Fill::Solid(color) = fill { Some(*color) } else { None })
.on_update(|text_input: &ColorInput| { .on_update(|text_input: &ColorInput| {
let fill = if let Some(value) = text_input.value { Fill::Solid(value) } else { Fill::None }; let fill = if let Some(value) = text_input.value { Fill::Solid(value) } else { Fill::None };
@ -555,11 +555,11 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutGroup> {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("").widget_holder(), TextLabel::new("").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextButton::new("Use Gradient") TextButton::new("Use Gradient")
.tooltip("Change this fill from a solid color to a gradient") .tooltip("Change this fill from a solid color to a gradient")
.on_update(move |_: &TextButton| { .on_update(move |_: &TextButton| {
@ -595,11 +595,11 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutGroup> {
layout.push(LayoutGroup::Row { layout.push(LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("").widget_holder(), TextLabel::new("").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextButton::new("Invert") TextButton::new("Invert")
.icon(Some("Swap".into())) .icon(Some("Swap".into()))
.tooltip("Reverse the order of each color stop") .tooltip("Reverse the order of each color stop")
@ -615,11 +615,11 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutGroup> {
layout.push(LayoutGroup::Row { layout.push(LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("").widget_holder(), TextLabel::new("").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextButton::new("Use Solid Color") TextButton::new("Use Solid Color")
.tooltip("Change this fill from a gradient to a solid color, keeping the 0% stop color") .tooltip("Change this fill from a gradient to a solid color, keeping the 0% stop color")
.on_update(move |_: &TextButton| { .on_update(move |_: &TextButton| {
@ -657,11 +657,11 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Color").widget_holder(), TextLabel::new("Color").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
ColorInput::new(stroke.color()) ColorInput::new(stroke.color())
.on_update(move |text_input: &ColorInput| { .on_update(move |text_input: &ColorInput| {
internal_stroke1 internal_stroke1
@ -675,11 +675,11 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Weight").widget_holder(), TextLabel::new("Weight").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(stroke.weight())) NumberInput::new(Some(stroke.weight()))
.is_integer(false) .is_integer(false)
.min(0.) .min(0.)
@ -696,11 +696,11 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Dash Lengths").widget_holder(), TextLabel::new("Dash Lengths").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
TextInput::new(stroke.dash_lengths()) TextInput::new(stroke.dash_lengths())
.centered(true) .centered(true)
.on_update(move |text_input: &TextInput| { .on_update(move |text_input: &TextInput| {
@ -715,11 +715,11 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Dash Offset").widget_holder(), TextLabel::new("Dash Offset").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(stroke.dash_offset())) NumberInput::new(Some(stroke.dash_offset()))
.is_integer(true) .is_integer(true)
.min(0.) .min(0.)
@ -736,11 +736,11 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Line Cap").widget_holder(), TextLabel::new("Line Cap").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new(vec![ RadioInput::new(vec![
RadioEntryData::new("Butt").on_update(move |_| { RadioEntryData::new("Butt").on_update(move |_| {
PropertiesPanelMessage::ModifyStroke { PropertiesPanelMessage::ModifyStroke {
@ -768,11 +768,11 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Line Join").widget_holder(), TextLabel::new("Line Join").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
RadioInput::new(vec![ RadioInput::new(vec![
RadioEntryData::new("Miter").on_update(move |_| { RadioEntryData::new("Miter").on_update(move |_| {
PropertiesPanelMessage::ModifyStroke { PropertiesPanelMessage::ModifyStroke {
@ -801,11 +801,11 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
LayoutGroup::Row { LayoutGroup::Row {
widgets: vec![ widgets: vec![
TextLabel::new("Miter Limit").widget_holder(), TextLabel::new("Miter Limit").widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
WidgetHolder::unrelated_separator(), // TODO: These three separators add up to 24px, Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
WidgetHolder::unrelated_separator(), // TODO: which is the width of the Assist area. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(stroke.line_join_miter_limit() as f64)) NumberInput::new(Some(stroke.line_join_miter_limit() as f64))
.is_integer(true) .is_integer(true)
.min(0.) .min(0.)

View File

@ -1,5 +1,5 @@
use crate::messages::layout::utility_types::layout_widget::WidgetCallback; use crate::messages::layout::utility_types::layout_widget::WidgetCallback;
use crate::messages::layout::utility_types::widget_prelude::{ColorInput, IconButton, RadioEntryData, RadioInput, TextLabel, WidgetHolder}; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::Message; use crate::messages::prelude::Message;
use graphene_core::Color; use graphene_core::Color;
@ -71,16 +71,16 @@ impl ToolColorOptions {
let mut widgets = vec![TextLabel::new(label_text).widget_holder()]; let mut widgets = vec![TextLabel::new(label_text).widget_holder()];
if !color_allow_none { if !color_allow_none {
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
} else { } else {
let reset = IconButton::new("CloseX", 12) let reset = IconButton::new("CloseX", 12)
.disabled(self.custom_color.is_none() && self.color_type == ToolColorType::Custom) .disabled(self.custom_color.is_none() && self.color_type == ToolColorType::Custom)
.tooltip("Clear Color") .tooltip("Clear Color")
.on_update(reset_callback); .on_update(reset_callback);
widgets.push(WidgetHolder::related_separator()); widgets.push(Separator::new(SeparatorType::Related).widget_holder());
widgets.push(reset.widget_holder()); widgets.push(reset.widget_holder());
widgets.push(WidgetHolder::related_separator()); widgets.push(Separator::new(SeparatorType::Related).widget_holder());
}; };
let entries = vec![ let entries = vec![
@ -97,7 +97,7 @@ impl ToolColorOptions {
.collect(); .collect();
let radio = RadioInput::new(entries).selected_index(self.color_type.clone() as u32).widget_holder(); let radio = RadioInput::new(entries).selected_index(self.color_type.clone() as u32).widget_holder();
widgets.push(radio); widgets.push(radio);
widgets.push(WidgetHolder::related_separator()); widgets.push(Separator::new(SeparatorType::Related).widget_holder());
let color_input = ColorInput::new(self.active_color()).allow_none(color_allow_none).on_update(color_callback); let color_input = ColorInput::new(self.active_color()).allow_none(color_allow_none).on_update(color_callback);
widgets.push(color_input.widget_holder()); widgets.push(color_input.widget_holder());

View File

@ -150,7 +150,7 @@ impl PropertyHolder for BrushTool {
.unit(" px") .unit(" px")
.on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Diameter(number_input.value.unwrap())).into()) .on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Diameter(number_input.value.unwrap())).into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(self.options.hardness)) NumberInput::new(Some(self.options.hardness))
.label("Hardness") .label("Hardness")
.min(0.) .min(0.)
@ -158,7 +158,7 @@ impl PropertyHolder for BrushTool {
.unit("%") .unit("%")
.on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Hardness(number_input.value.unwrap())).into()) .on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Hardness(number_input.value.unwrap())).into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(self.options.flow)) NumberInput::new(Some(self.options.flow))
.label("Flow") .label("Flow")
.min(1.) .min(1.)
@ -166,7 +166,7 @@ impl PropertyHolder for BrushTool {
.unit("%") .unit("%")
.on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Flow(number_input.value.unwrap())).into()) .on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Flow(number_input.value.unwrap())).into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(self.options.spacing)) NumberInput::new(Some(self.options.spacing))
.label("Spacing") .label("Spacing")
.min(1.) .min(1.)
@ -176,7 +176,7 @@ impl PropertyHolder for BrushTool {
.widget_holder(), .widget_holder(),
]; ];
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
let draw_mode_entries: Vec<_> = [DrawMode::Draw, DrawMode::Erase, DrawMode::Restore] let draw_mode_entries: Vec<_> = [DrawMode::Draw, DrawMode::Erase, DrawMode::Restore]
.into_iter() .into_iter()
@ -184,7 +184,7 @@ impl PropertyHolder for BrushTool {
.collect(); .collect();
widgets.push(RadioInput::new(draw_mode_entries).selected_index(self.options.draw_mode as u32).widget_holder()); widgets.push(RadioInput::new(draw_mode_entries).selected_index(self.options.draw_mode as u32).widget_holder());
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
widgets.append(&mut self.options.color.create_widgets( widgets.append(&mut self.options.color.create_widgets(
"Color", "Color",
@ -194,7 +194,7 @@ impl PropertyHolder for BrushTool {
|color: &ColorInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(color.value)).into(), |color: &ColorInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(color.value)).into(),
)); ));
widgets.push(WidgetHolder::related_separator()); widgets.push(Separator::new(SeparatorType::Related).widget_holder());
let blend_mode_entries: Vec<Vec<_>> = EXPOSED_BLEND_MODES let blend_mode_entries: Vec<Vec<_>> = EXPOSED_BLEND_MODES
.iter() .iter()

View File

@ -2,7 +2,7 @@ use crate::messages::frontend::utility_types::MouseCursorIcon;
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, MouseMotion}; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, MouseMotion};
use crate::messages::layout::utility_types::layout_widget::{Layout, LayoutGroup, PropertyHolder, WidgetCallback, WidgetLayout}; use crate::messages::layout::utility_types::layout_widget::{Layout, LayoutGroup, PropertyHolder, WidgetCallback, WidgetLayout};
use crate::messages::layout::utility_types::misc::LayoutTarget; use crate::messages::layout::utility_types::misc::LayoutTarget;
use crate::messages::layout::utility_types::widget_prelude::{ColorInput, NumberInput, WidgetHolder}; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils;
@ -101,7 +101,7 @@ impl PropertyHolder for EllipseTool {
|color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColor(color.value)).into(), |color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColor(color.value)).into(),
); );
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
widgets.append(&mut self.options.stroke.create_widgets( widgets.append(&mut self.options.stroke.create_widgets(
"Stroke", "Stroke",
@ -110,7 +110,7 @@ impl PropertyHolder for EllipseTool {
|color_type: ToolColorType| WidgetCallback::new(move |_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColorType(color_type.clone())).into()), |color_type: ToolColorType| WidgetCallback::new(move |_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColor(color.value)).into(), |color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColor(color.value)).into(),
)); ));
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight)); widgets.push(create_weight_widget(self.options.line_weight));
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }]))

View File

@ -105,7 +105,7 @@ impl PropertyHolder for FreehandTool {
|color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(color.value)).into(), |color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(color.value)).into(),
); );
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
widgets.append(&mut self.options.stroke.create_widgets( widgets.append(&mut self.options.stroke.create_widgets(
"Stroke", "Stroke",
@ -114,7 +114,7 @@ impl PropertyHolder for FreehandTool {
|color_type: ToolColorType| WidgetCallback::new(move |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColorType(color_type.clone())).into()), |color_type: ToolColorType| WidgetCallback::new(move |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(color.value)).into(), |color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(color.value)).into(),
)); ));
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight)); widgets.push(create_weight_widget(self.options.line_weight));
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }]))

View File

@ -99,7 +99,7 @@ impl PropertyHolder for LineTool {
|color_type: ToolColorType| WidgetCallback::new(move |_| LineToolMessage::UpdateOptions(LineOptionsUpdate::StrokeColorType(color_type.clone())).into()), |color_type: ToolColorType| WidgetCallback::new(move |_| LineToolMessage::UpdateOptions(LineOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorInput| LineToolMessage::UpdateOptions(LineOptionsUpdate::StrokeColor(color.value)).into(), |color: &ColorInput| LineToolMessage::UpdateOptions(LineOptionsUpdate::StrokeColor(color.value)).into(),
); );
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight)); widgets.push(create_weight_widget(self.options.line_weight));
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }]))

View File

@ -124,7 +124,7 @@ impl PropertyHolder for PenTool {
|color: &ColorInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::FillColor(color.value)).into(), |color: &ColorInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::FillColor(color.value)).into(),
); );
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
widgets.append(&mut self.options.stroke.create_widgets( widgets.append(&mut self.options.stroke.create_widgets(
"Stroke", "Stroke",
@ -133,7 +133,7 @@ impl PropertyHolder for PenTool {
|color_type: ToolColorType| WidgetCallback::new(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::StrokeColorType(color_type.clone())).into()), |color_type: ToolColorType| WidgetCallback::new(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::StrokeColor(color.value)).into(), |color: &ColorInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::StrokeColor(color.value)).into(),
)); ));
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight)); widgets.push(create_weight_widget(self.options.line_weight));
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }]))

View File

@ -87,7 +87,7 @@ impl PropertyHolder for RectangleTool {
|color: &ColorInput| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::FillColor(color.value)).into(), |color: &ColorInput| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::FillColor(color.value)).into(),
); );
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
widgets.append(&mut self.options.stroke.create_widgets( widgets.append(&mut self.options.stroke.create_widgets(
"Stroke", "Stroke",
@ -96,7 +96,7 @@ impl PropertyHolder for RectangleTool {
|color_type: ToolColorType| WidgetCallback::new(move |_| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::StrokeColorType(color_type.clone())).into()), |color_type: ToolColorType| WidgetCallback::new(move |_| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorInput| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::StrokeColor(color.value)).into(), |color: &ColorInput| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::StrokeColor(color.value)).into(),
)); ));
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight)); widgets.push(create_weight_widget(self.options.line_weight));
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }]))

View File

@ -133,13 +133,13 @@ impl PropertyHolder for SelectTool {
.selected_index(Some((self.tool_data.nested_selection_behavior == NestedSelectionBehavior::Shallowest) as u32)) .selected_index(Some((self.tool_data.nested_selection_behavior == NestedSelectionBehavior::Shallowest) as u32))
.tooltip("Choose if clicking nested layers directly selects the deepest, or selects the shallowest and deepens by double clicking") .tooltip("Choose if clicking nested layers directly selects the deepest, or selects the shallowest and deepens by double clicking")
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
// We'd like this widget to hide and show itself whenever the transformation cage is active or inactive (i.e. when no layers are selected) // We'd like this widget to hide and show itself whenever the transformation cage is active or inactive (i.e. when no layers are selected)
PivotAssist::new(self.tool_data.pivot.to_pivot_position()) PivotAssist::new(self.tool_data.pivot.to_pivot_position())
.disabled(deactivate_pivot) .disabled(deactivate_pivot)
.on_update(|pivot_assist: &PivotAssist| SelectToolMessage::SetPivot { position: pivot_assist.position }.into()) .on_update(|pivot_assist: &PivotAssist| SelectToolMessage::SetPivot { position: pivot_assist.position }.into())
.widget_holder(), .widget_holder(),
WidgetHolder::section_separator(), Separator::new(SeparatorType::Section).widget_holder(),
IconButton::new("AlignLeft", 24) IconButton::new("AlignLeft", 24)
.tooltip("Align Left") .tooltip("Align Left")
.disabled(deactivate_alignment) .disabled(deactivate_alignment)
@ -173,7 +173,7 @@ impl PropertyHolder for SelectTool {
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::unrelated_separator(), Separator::new(SeparatorType::Unrelated).widget_holder(),
IconButton::new("AlignTop", 24) IconButton::new("AlignTop", 24)
.tooltip("Align Top") .tooltip("Align Top")
.disabled(deactivate_alignment) .disabled(deactivate_alignment)
@ -207,9 +207,9 @@ impl PropertyHolder for SelectTool {
.into() .into()
}) })
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
PopoverButton::new("Align", "Coming soon").widget_holder(), PopoverButton::new("Align", "Coming soon").widget_holder(),
WidgetHolder::section_separator(), Separator::new(SeparatorType::Section).widget_holder(),
IconButton::new("FlipHorizontal", 24) IconButton::new("FlipHorizontal", 24)
.tooltip("Flip Horizontal") .tooltip("Flip Horizontal")
.on_update(|_| SelectToolMessage::FlipHorizontal.into()) .on_update(|_| SelectToolMessage::FlipHorizontal.into())
@ -218,9 +218,9 @@ impl PropertyHolder for SelectTool {
.tooltip("Flip Vertical") .tooltip("Flip Vertical")
.on_update(|_| SelectToolMessage::FlipVertical.into()) .on_update(|_| SelectToolMessage::FlipVertical.into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
PopoverButton::new("Flip", "Coming soon").widget_holder(), PopoverButton::new("Flip", "Coming soon").widget_holder(),
WidgetHolder::section_separator(), Separator::new(SeparatorType::Section).widget_holder(),
IconButton::new("BooleanUnion", 24) IconButton::new("BooleanUnion", 24)
.tooltip("Boolean Union (coming soon)") .tooltip("Boolean Union (coming soon)")
.on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(1091) }.into()) .on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(1091) }.into())
@ -241,7 +241,7 @@ impl PropertyHolder for SelectTool {
.tooltip("Boolean Difference (coming soon)") .tooltip("Boolean Difference (coming soon)")
.on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(1091) }.into()) .on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(1091) }.into())
.widget_holder(), .widget_holder(),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
PopoverButton::new("Boolean", "Coming soon").widget_holder(), PopoverButton::new("Boolean", "Coming soon").widget_holder(),
], ],
}])) }]))

View File

@ -125,11 +125,11 @@ impl PropertyHolder for ShapeTool {
fn properties(&self) -> Layout { fn properties(&self) -> Layout {
let mut widgets = vec![ let mut widgets = vec![
create_star_option_widget(self.options.primitive_shape_type), create_star_option_widget(self.options.primitive_shape_type),
WidgetHolder::related_separator(), Separator::new(SeparatorType::Related).widget_holder(),
create_sides_widget(self.options.vertices), create_sides_widget(self.options.vertices),
]; ];
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
widgets.append(&mut self.options.fill.create_widgets( widgets.append(&mut self.options.fill.create_widgets(
"Fill", "Fill",
@ -139,7 +139,7 @@ impl PropertyHolder for ShapeTool {
|color: &ColorInput| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::FillColor(color.value)).into(), |color: &ColorInput| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::FillColor(color.value)).into(),
)); ));
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
widgets.append(&mut self.options.stroke.create_widgets( widgets.append(&mut self.options.stroke.create_widgets(
"Stroke", "Stroke",
@ -148,7 +148,7 @@ impl PropertyHolder for ShapeTool {
|color_type: ToolColorType| WidgetCallback::new(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::StrokeColorType(color_type.clone())).into()), |color_type: ToolColorType| WidgetCallback::new(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorInput| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::StrokeColor(color.value)).into(), |color: &ColorInput| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::StrokeColor(color.value)).into(),
)); ));
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight)); widgets.push(create_weight_widget(self.options.line_weight));
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }]))

View File

@ -108,7 +108,7 @@ impl PropertyHolder for SplineTool {
|color: &ColorInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::FillColor(color.value)).into(), |color: &ColorInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::FillColor(color.value)).into(),
); );
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
widgets.append(&mut self.options.stroke.create_widgets( widgets.append(&mut self.options.stroke.create_widgets(
"Stroke", "Stroke",
@ -117,7 +117,7 @@ impl PropertyHolder for SplineTool {
|color_type: ToolColorType| WidgetCallback::new(move |_| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::StrokeColorType(color_type.clone())).into()), |color_type: ToolColorType| WidgetCallback::new(move |_| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::StrokeColorType(color_type.clone())).into()),
|color: &ColorInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::StrokeColor(color.value)).into(), |color: &ColorInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::StrokeColor(color.value)).into(),
)); ));
widgets.push(WidgetHolder::unrelated_separator()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(create_weight_widget(self.options.line_weight)); widgets.push(create_weight_widget(self.options.line_weight));
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }]))

View File

@ -125,14 +125,20 @@ fn create_text_widgets(tool: &TextTool) -> Vec<WidgetHolder> {
.min(1.) .min(1.)
.on_update(|number_input: &NumberInput| TextToolMessage::UpdateOptions(TextOptionsUpdate::FontSize(number_input.value.unwrap() as u32)).into()) .on_update(|number_input: &NumberInput| TextToolMessage::UpdateOptions(TextOptionsUpdate::FontSize(number_input.value.unwrap() as u32)).into())
.widget_holder(); .widget_holder();
vec![font, WidgetHolder::related_separator(), style, WidgetHolder::related_separator(), size] vec![
font,
Separator::new(SeparatorType::Related).widget_holder(),
style,
Separator::new(SeparatorType::Related).widget_holder(),
size,
]
} }
impl PropertyHolder for TextTool { impl PropertyHolder for TextTool {
fn properties(&self) -> Layout { fn properties(&self) -> Layout {
let mut widgets = create_text_widgets(self); let mut widgets = create_text_widgets(self);
widgets.push(WidgetHolder::section_separator()); widgets.push(Separator::new(SeparatorType::Section).widget_holder());
widgets.append(&mut self.options.fill.create_widgets( widgets.append(&mut self.options.fill.create_widgets(
"Fill", "Fill",

View File

@ -256,7 +256,7 @@ impl PropertyHolder for ToolData {
} }
}).collect::<Vec<_>>()) }).collect::<Vec<_>>())
.flat_map(|group| { .flat_map(|group| {
let separator = std::iter::once(Separator::new(SeparatorDirection::Vertical, SeparatorType::Section).widget_holder()); let separator = std::iter::once(Separator::new(SeparatorType::Section).direction(SeparatorDirection::Vertical).widget_holder());
let buttons = group.into_iter().map(|ToolEntry { tooltip, tooltip_shortcut, tool_type, icon_name }| { let buttons = group.into_iter().map(|ToolEntry { tooltip, tooltip_shortcut, tool_type, icon_name }| {
IconButton::new(icon_name, 32) IconButton::new(icon_name, 32)
.disabled( false) .disabled( false)