Add support for clicking checkboxes via their labels (#2667)
This commit is contained in:
parent
80f38d91c0
commit
c4678336e5
|
|
@ -143,12 +143,14 @@ impl LayoutHolder for ExportDialogMessageHandler {
|
|||
DropdownInput::new(entries).selected_index(Some(index as u32)).widget_holder(),
|
||||
];
|
||||
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
let transparent_background = vec![
|
||||
TextLabel::new("Transparency").table_align(true).min_width(100).widget_holder(),
|
||||
TextLabel::new("Transparency").table_align(true).min_width(100).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
CheckboxInput::new(self.transparent_background)
|
||||
.disabled(self.file_type == FileType::Jpg)
|
||||
.on_update(move |value: &CheckboxInput| ExportDialogMessage::TransparentBackground(value.checked).into())
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -77,11 +77,13 @@ impl LayoutHolder for NewDocumentDialogMessageHandler {
|
|||
.widget_holder(),
|
||||
];
|
||||
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
let infinite = vec![
|
||||
TextLabel::new("Infinite Canvas").table_align(true).min_width(90).widget_holder(),
|
||||
TextLabel::new("Infinite Canvas").table_align(true).min_width(90).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
CheckboxInput::new(self.infinite)
|
||||
.on_update(|checkbox_input: &CheckboxInput| NewDocumentDialogMessage::Infinite(checkbox_input.checked).into())
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ impl PreferencesDialogMessageHandler {
|
|||
.widget_holder(),
|
||||
];
|
||||
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
let zoom_with_scroll_tooltip = "Use the scroll wheel for zooming instead of vertically panning (not recommended for trackpads)";
|
||||
let zoom_with_scroll = vec![
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
|
|
@ -78,8 +79,13 @@ impl PreferencesDialogMessageHandler {
|
|||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Zoom with Scroll")
|
||||
.table_align(true)
|
||||
.tooltip(zoom_with_scroll_tooltip)
|
||||
.for_checkbox(&mut checkbox_id)
|
||||
.widget_holder(),
|
||||
TextLabel::new("Zoom with Scroll").table_align(true).tooltip(zoom_with_scroll_tooltip).widget_holder(),
|
||||
];
|
||||
|
||||
// =======
|
||||
|
|
@ -161,6 +167,7 @@ impl PreferencesDialogMessageHandler {
|
|||
graph_wire_style,
|
||||
];
|
||||
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
let vello_tooltip = "Use the experimental Vello renderer (your browser must support WebGPU)";
|
||||
let use_vello = vec![
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
|
|
@ -169,14 +176,17 @@ impl PreferencesDialogMessageHandler {
|
|||
.tooltip(vello_tooltip)
|
||||
.disabled(!preferences.supports_wgpu())
|
||||
.on_update(|checkbox_input: &CheckboxInput| PreferencesMessage::UseVello { use_vello: checkbox_input.checked }.into())
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Vello Renderer")
|
||||
.table_align(true)
|
||||
.tooltip(vello_tooltip)
|
||||
.disabled(!preferences.supports_wgpu())
|
||||
.for_checkbox(&mut checkbox_id)
|
||||
.widget_holder(),
|
||||
];
|
||||
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
let vector_mesh_tooltip = "Allow tools to produce vector meshes, where more than two segments can connect to an anchor point.\n\nCurrently this does not properly handle line joins and fills.";
|
||||
let vector_meshes = vec![
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
|
|
@ -184,8 +194,13 @@ impl PreferencesDialogMessageHandler {
|
|||
CheckboxInput::new(preferences.vector_meshes)
|
||||
.tooltip(vector_mesh_tooltip)
|
||||
.on_update(|checkbox_input: &CheckboxInput| PreferencesMessage::VectorMeshes { enabled: checkbox_input.checked }.into())
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Vector Meshes")
|
||||
.table_align(true)
|
||||
.tooltip(vector_mesh_tooltip)
|
||||
.for_checkbox(&mut checkbox_id)
|
||||
.widget_holder(),
|
||||
TextLabel::new("Vector Meshes").table_align(true).tooltip(vector_mesh_tooltip).widget_holder(),
|
||||
];
|
||||
|
||||
// TODO: Reenable when Imaginate is restored
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ use graphene_core::Color;
|
|||
use graphene_core::raster::curve::Curve;
|
||||
use graphene_std::transform::ReferencePoint;
|
||||
use graphite_proc_macros::WidgetBuilder;
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder, specta::Type)]
|
||||
#[derivative(Debug, PartialEq)]
|
||||
|
|
@ -18,6 +20,9 @@ pub struct CheckboxInput {
|
|||
|
||||
pub tooltip: String,
|
||||
|
||||
#[serde(rename = "forLabel", skip_serializing_if = "checkbox_id_is_empty")]
|
||||
pub for_label: CheckboxId,
|
||||
|
||||
#[serde(skip)]
|
||||
pub tooltip_shortcut: Option<ActionKeys>,
|
||||
|
||||
|
|
@ -39,12 +44,51 @@ impl Default for CheckboxInput {
|
|||
icon: "Checkmark".into(),
|
||||
tooltip: Default::default(),
|
||||
tooltip_shortcut: Default::default(),
|
||||
for_label: CheckboxId::default(),
|
||||
on_update: Default::default(),
|
||||
on_commit: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug, Eq, PartialEq)]
|
||||
pub struct CheckboxId(Arc<OnceCell<u64>>);
|
||||
|
||||
impl CheckboxId {
|
||||
pub fn fill(&mut self) {
|
||||
let _ = self.0.set(graphene_core::uuid::generate_uuid());
|
||||
}
|
||||
}
|
||||
impl specta::Type for CheckboxId {
|
||||
fn inline(_type_map: &mut specta::TypeCollection, _generics: specta::Generics) -> specta::datatype::DataType {
|
||||
// TODO: This might not be right, but it works for now. We just need the type `bigint | undefined`.
|
||||
specta::datatype::DataType::Primitive(specta::datatype::PrimitiveType::u64)
|
||||
}
|
||||
}
|
||||
impl serde::Serialize for CheckboxId {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
self.0.get().copied().serialize(serializer)
|
||||
}
|
||||
}
|
||||
impl<'a> serde::Deserialize<'a> for CheckboxId {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'a>,
|
||||
{
|
||||
let id = u64::deserialize(deserializer)?;
|
||||
let checkbox_id = CheckboxId(OnceCell::new().into());
|
||||
checkbox_id.0.set(id).map_err(serde::de::Error::custom)?;
|
||||
Ok(checkbox_id)
|
||||
}
|
||||
}
|
||||
|
||||
fn checkbox_id_is_empty(id: &CheckboxId) -> bool {
|
||||
id.0.get().is_none()
|
||||
}
|
||||
|
||||
#[derive(Clone, serde::Serialize, serde::Deserialize, Derivative, WidgetBuilder, specta::Type)]
|
||||
#[derivative(Debug, PartialEq, Default)]
|
||||
pub struct DropdownInput {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use super::input_widgets::CheckboxId;
|
||||
use derivative::*;
|
||||
use graphite_proc_macros::WidgetBuilder;
|
||||
|
||||
|
|
@ -56,9 +57,21 @@ pub struct TextLabel {
|
|||
|
||||
pub tooltip: String,
|
||||
|
||||
#[serde(rename = "checkboxId")]
|
||||
#[widget_builder(skip)]
|
||||
pub checkbox_id: CheckboxId,
|
||||
|
||||
// Body
|
||||
#[widget_builder(constructor)]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
impl TextLabel {
|
||||
pub fn for_checkbox(mut self, id: &mut CheckboxId) -> Self {
|
||||
id.fill();
|
||||
self.checkbox_id = id.clone();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add UserInputLabel
|
||||
|
|
|
|||
|
|
@ -2141,165 +2141,212 @@ impl DocumentMessageHandler {
|
|||
widgets: vec![TextLabel::new("General").widget_holder()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.artboard_name)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::ArtboardName),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Artboard Name".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.artboard_name)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::ArtboardName),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Artboard Name".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.transform_measurement)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::TransformMeasurement),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("G/R/S Measurement".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.transform_measurement)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::TransformMeasurement),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("G/R/S Measurement".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Select Tool").widget_holder()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.quick_measurement)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::QuickMeasurement),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Quick Measurement".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.quick_measurement)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::QuickMeasurement),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Quick Measurement".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.transform_cage)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::TransformCage),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Transform Cage".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.transform_cage)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::TransformCage),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Transform Cage".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.compass_rose)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::CompassRose),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Transform Dial".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.compass_rose)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::CompassRose),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Transform Dial".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.pivot)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::Pivot),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Transform Pivot".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.pivot)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::Pivot),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Transform Pivot".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.hover_outline)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::HoverOutline),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Hover Outline".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.hover_outline)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::HoverOutline),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Hover Outline".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.selection_outline)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::SelectionOutline),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Selection Outline".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.selection_outline)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::SelectionOutline),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Selection Outline".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Pen & Path Tools").widget_holder()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.path)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::Path),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Path".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.path)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::Path),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Path".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.anchors)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::Anchors),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Anchors".to_string()).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.anchors)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::Anchors),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Anchors".to_string()).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.handles)
|
||||
.disabled(!self.overlays_visibility_settings.anchors)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::Handles),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
TextLabel::new("Handles".to_string()).disabled(!self.overlays_visibility_settings.anchors).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(self.overlays_visibility_settings.handles)
|
||||
.disabled(!self.overlays_visibility_settings.anchors)
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
overlays_type: Some(OverlaysType::Handles),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new("Handles".to_string())
|
||||
.disabled(!self.overlays_visibility_settings.anchors)
|
||||
.for_checkbox(&mut checkbox_id)
|
||||
.widget_holder(),
|
||||
]
|
||||
},
|
||||
},
|
||||
])
|
||||
.widget_holder(),
|
||||
|
|
@ -2328,25 +2375,45 @@ impl DocumentMessageHandler {
|
|||
]
|
||||
.into_iter()
|
||||
.chain(SNAP_FUNCTIONS_FOR_BOUNDING_BOXES.into_iter().map(|(name, closure, tooltip)| LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(*closure(&mut snapping_state))
|
||||
.on_update(move |input: &CheckboxInput| DocumentMessage::SetSnapping { closure: Some(closure), snapping_state: input.checked }.into())
|
||||
.tooltip(tooltip)
|
||||
.widget_holder(),
|
||||
TextLabel::new(name).tooltip(tooltip).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(*closure(&mut snapping_state))
|
||||
.on_update(move |input: &CheckboxInput| {
|
||||
DocumentMessage::SetSnapping {
|
||||
closure: Some(closure),
|
||||
snapping_state: input.checked,
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.tooltip(tooltip)
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new(name).tooltip(tooltip).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
}))
|
||||
.chain([LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new(SnappingOptions::Paths.to_string()).widget_holder()],
|
||||
}])
|
||||
.chain(SNAP_FUNCTIONS_FOR_PATHS.into_iter().map(|(name, closure, tooltip)| LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
CheckboxInput::new(*closure(&mut snapping_state2))
|
||||
.on_update(move |input: &CheckboxInput| DocumentMessage::SetSnapping { closure: Some(closure), snapping_state: input.checked }.into())
|
||||
.tooltip(tooltip)
|
||||
.widget_holder(),
|
||||
TextLabel::new(name).tooltip(tooltip).widget_holder(),
|
||||
],
|
||||
widgets: {
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
vec![
|
||||
CheckboxInput::new(*closure(&mut snapping_state2))
|
||||
.on_update(move |input: &CheckboxInput| {
|
||||
DocumentMessage::SetSnapping {
|
||||
closure: Some(closure),
|
||||
snapping_state: input.checked,
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.tooltip(tooltip)
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder(),
|
||||
TextLabel::new(name).tooltip(tooltip).for_checkbox(&mut checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
}))
|
||||
.collect(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1851,11 +1851,6 @@ impl NodeGraphMessageHandler {
|
|||
//
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
//
|
||||
IconButton::new("NewLayer", 24)
|
||||
.tooltip("New Layer")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder))
|
||||
.on_update(|_| DocumentMessage::CreateEmptyFolder.into())
|
||||
.widget_holder(),
|
||||
IconButton::new("Folder", 24)
|
||||
.tooltip("Group Selected")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::GroupSelectedLayers))
|
||||
|
|
@ -1865,6 +1860,11 @@ impl NodeGraphMessageHandler {
|
|||
})
|
||||
.disabled(!has_selection)
|
||||
.widget_holder(),
|
||||
IconButton::new("NewLayer", 24)
|
||||
.tooltip("New Layer")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder))
|
||||
.on_update(|_| DocumentMessage::CreateEmptyFolder.into())
|
||||
.widget_holder(),
|
||||
IconButton::new("Trash", 24)
|
||||
.tooltip("Delete Selected")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::DeleteSelectedLayers))
|
||||
|
|
|
|||
|
|
@ -339,6 +339,7 @@
|
|||
// resolution_index,
|
||||
// ))
|
||||
// .on_commit(commit_value)
|
||||
// .for_label(checkbox_id.clone())
|
||||
// .widget_holder(),
|
||||
// Separator::new(SeparatorType::Related).widget_holder(),
|
||||
// NumberInput::new(Some(vec2.x))
|
||||
|
|
@ -438,7 +439,7 @@
|
|||
// LayoutGroup::Row { widgets }.with_tooltip("A negative text prompt can be used to list things like objects or colors to avoid")
|
||||
// };
|
||||
// let base_image = {
|
||||
// let widgets = bool_widget(document_node, node_id, base_img_index, "Adapt Input Image", CheckboxInput::default(), true);
|
||||
// let widgets = bool_widget(document_node, node_id, base_img_index, "Adapt Input Image", CheckboxInput::default().for_label(checkbox_id.clone()), true);
|
||||
// LayoutGroup::Row { widgets }.with_tooltip("Generate an image based upon the bitmap data plugged into this node")
|
||||
// };
|
||||
// let image_creativity = {
|
||||
|
|
@ -529,7 +530,7 @@
|
|||
// // }
|
||||
|
||||
// let improve_faces = {
|
||||
// let widgets = bool_widget(document_node, node_id, faces_index, "Improve Faces", CheckboxInput::default(), true);
|
||||
// let widgets = bool_widget(document_node, node_id, faces_index, "Improve Faces", CheckboxInput::default().for_label(checkbox_id.clone()), true);
|
||||
// LayoutGroup::Row { widgets }.with_tooltip(
|
||||
// "Postprocess human (or human-like) faces to look subtly less distorted.\n\
|
||||
// \n\
|
||||
|
|
@ -537,7 +538,7 @@
|
|||
// )
|
||||
// };
|
||||
// let tiling = {
|
||||
// let widgets = bool_widget(document_node, node_id, tiling_index, "Tiling", CheckboxInput::default(), true);
|
||||
// let widgets = bool_widget(document_node, node_id, tiling_index, "Tiling", CheckboxInput::default().for_label(checkbox_id.clone()), true);
|
||||
// LayoutGroup::Row { widgets }.with_tooltip("Generate the image so its edges loop seamlessly to make repeatable patterns or textures")
|
||||
// };
|
||||
// layout.extend_from_slice(&[improve_faces, tiling]);
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ impl LayoutHolder for PathTool {
|
|||
})
|
||||
// TODO: Remove `unwrap_or_default` once checkboxes are capable of displaying a mixed state
|
||||
.unwrap_or_default();
|
||||
let mut checkbox_id = CheckboxId::default();
|
||||
let colinear_handle_checkbox = CheckboxInput::new(colinear_handles_state)
|
||||
.disabled(!self.tool_data.can_toggle_colinearity)
|
||||
.on_update(|&CheckboxInput { checked, .. }| {
|
||||
|
|
@ -191,10 +192,12 @@ impl LayoutHolder for PathTool {
|
|||
}
|
||||
})
|
||||
.tooltip(colinear_handles_tooltip)
|
||||
.for_label(checkbox_id.clone())
|
||||
.widget_holder();
|
||||
let colinear_handles_label = TextLabel::new("Colinear Handles")
|
||||
.disabled(!self.tool_data.can_toggle_colinearity)
|
||||
.tooltip(colinear_handles_tooltip)
|
||||
.for_checkbox(&mut checkbox_id)
|
||||
.widget_holder();
|
||||
|
||||
let path_overlay_mode_widget = RadioInput::new(vec![
|
||||
|
|
|
|||
|
|
@ -549,8 +549,10 @@
|
|||
|
||||
// Layer hierarchy
|
||||
.list-area {
|
||||
margin: 4px 0;
|
||||
position: relative;
|
||||
margin-top: 4px;
|
||||
// Combine with the bottom bar to avoid a double border
|
||||
margin-bottom: -1px;
|
||||
|
||||
.layer {
|
||||
flex: 0 0 auto;
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@
|
|||
export let disabled = false;
|
||||
export let icon: IconName = "Checkmark";
|
||||
export let tooltip: string | undefined = undefined;
|
||||
export let forLabel: bigint | undefined = undefined;
|
||||
|
||||
let inputElement: HTMLInputElement | undefined;
|
||||
|
||||
let id = String(Math.random()).substring(2);
|
||||
const backupId = String(Math.random()).substring(2);
|
||||
|
||||
$: id = forLabel !== undefined ? String(forLabel) : backupId;
|
||||
$: displayIcon = (!checked && icon === "Checkmark" ? "Empty12px" : icon) as IconName;
|
||||
|
||||
export function isChecked() {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
export let minWidth = 0;
|
||||
export let multiline = false;
|
||||
export let tooltip: string | undefined = undefined;
|
||||
export let checkboxId: bigint | undefined = undefined;
|
||||
|
||||
$: extraClasses = Object.entries(classes)
|
||||
.flatMap(([className, stateName]) => (stateName ? [className] : []))
|
||||
|
|
@ -22,7 +23,7 @@
|
|||
.join(" ");
|
||||
</script>
|
||||
|
||||
<span
|
||||
<label
|
||||
class={`text-label ${className} ${extraClasses}`.trim()}
|
||||
class:disabled
|
||||
class:bold
|
||||
|
|
@ -33,9 +34,10 @@
|
|||
style:min-width={minWidth > 0 ? `${minWidth}px` : undefined}
|
||||
style={`${styleName} ${extraStyles}`.trim() || undefined}
|
||||
title={tooltip}
|
||||
for={checkboxId !== undefined ? `checkbox-input-${checkboxId}` : undefined}
|
||||
>
|
||||
<slot />
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<style lang="scss" global>
|
||||
.text-label {
|
||||
|
|
|
|||
|
|
@ -960,6 +960,8 @@ export class CheckboxInput extends WidgetProps {
|
|||
|
||||
@Transform(({ value }: { value: string }) => value || undefined)
|
||||
tooltip!: string | undefined;
|
||||
|
||||
forLabel!: bigint | undefined;
|
||||
}
|
||||
|
||||
export class ColorInput extends WidgetProps {
|
||||
|
|
@ -1360,6 +1362,8 @@ export class TextLabel extends WidgetProps {
|
|||
|
||||
@Transform(({ value }: { value: string }) => value || undefined)
|
||||
tooltip!: string | undefined;
|
||||
|
||||
checkboxId!: bigint | undefined;
|
||||
}
|
||||
|
||||
export type ReferencePoint = "None" | "TopLeft" | "TopCenter" | "TopRight" | "CenterLeft" | "Center" | "CenterRight" | "BottomLeft" | "BottomCenter" | "BottomRight";
|
||||
|
|
|
|||
Loading…
Reference in New Issue