mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-27 21:08:11 +08:00
Replace text-only tooltips with custom richly styled tooltips (#3436)
* Replace the title attribute with custom FloatingMenu tooltips * Separate tooltip labels and descriptions into two styled blocks * Move keyboard shortcut tooltips to a separate section at the bottom * Update shortcut key styling in tooltips and hints bar * Fix .to_string()
This commit is contained in:
@@ -97,13 +97,13 @@ impl DataPanelMessageHandler {
|
||||
|
||||
widgets.extend([
|
||||
if is_layer {
|
||||
IconLabel::new("Layer").tooltip("Name of the selected layer").widget_holder()
|
||||
IconLabel::new("Layer").tooltip_description("Name of the selected layer.").widget_holder()
|
||||
} else {
|
||||
IconLabel::new("Node").tooltip("Name of the selected node").widget_holder()
|
||||
IconLabel::new("Node").tooltip_description("Name of the selected node.").widget_holder()
|
||||
},
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
TextInput::new(network_interface.display_name(&node_id, &[]))
|
||||
.tooltip(if is_layer { "Name of the selected layer" } else { "Name of the selected node" })
|
||||
.tooltip_description(if is_layer { "Name of the selected layer." } else { "Name of the selected node." })
|
||||
.on_update(move |text_input| {
|
||||
NodeGraphMessage::SetDisplayName {
|
||||
node_id,
|
||||
|
||||
@@ -2211,21 +2211,21 @@ impl DocumentMessageHandler {
|
||||
|
||||
let mut widgets = vec![
|
||||
IconButton::new("PlaybackToStart", 24)
|
||||
.tooltip("Restart Animation")
|
||||
.tooltip_shortcut(action_keys!(AnimationMessageDiscriminant::RestartAnimation))
|
||||
.tooltip_label("Restart Animation")
|
||||
.shortcut_keys(action_keys!(AnimationMessageDiscriminant::RestartAnimation))
|
||||
.on_update(|_| AnimationMessage::RestartAnimation.into())
|
||||
.disabled(time == Duration::ZERO)
|
||||
.widget_holder(),
|
||||
IconButton::new(if animation_is_playing { "PlaybackPause" } else { "PlaybackPlay" }, 24)
|
||||
.tooltip(if animation_is_playing { "Pause Animation" } else { "Play Animation" })
|
||||
.tooltip_shortcut(action_keys!(AnimationMessageDiscriminant::ToggleLivePreview))
|
||||
.tooltip_label(if animation_is_playing { "Pause Animation" } else { "Play Animation" })
|
||||
.shortcut_keys(action_keys!(AnimationMessageDiscriminant::ToggleLivePreview))
|
||||
.on_update(|_| AnimationMessage::ToggleLivePreview.into())
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
CheckboxInput::new(self.overlays_visibility_settings.all)
|
||||
.icon("Overlays")
|
||||
.tooltip("Overlays")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ToggleOverlaysVisibility))
|
||||
.tooltip_label("Overlays")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::ToggleOverlaysVisibility))
|
||||
.on_update(|optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetOverlaysVisibility {
|
||||
visible: optional_input.checked,
|
||||
@@ -2473,8 +2473,8 @@ impl DocumentMessageHandler {
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
CheckboxInput::new(snapping_state.snapping_enabled)
|
||||
.icon("Snapping")
|
||||
.tooltip("Snapping")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ToggleSnapping))
|
||||
.tooltip_label("Snapping")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::ToggleSnapping))
|
||||
.on_update(move |optional_input: &CheckboxInput| {
|
||||
DocumentMessage::SetSnapping {
|
||||
closure: Some(|snapping_state| &mut snapping_state.snapping_enabled),
|
||||
@@ -2494,7 +2494,7 @@ impl DocumentMessageHandler {
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.chain(SNAP_FUNCTIONS_FOR_BOUNDING_BOXES.into_iter().map(|(name, closure, tooltip)| LayoutGroup::Row {
|
||||
.chain(SNAP_FUNCTIONS_FOR_BOUNDING_BOXES.into_iter().map(|(name, closure, description)| LayoutGroup::Row {
|
||||
widgets: {
|
||||
let checkbox_id = CheckboxId::new();
|
||||
vec![
|
||||
@@ -2506,17 +2506,18 @@ impl DocumentMessageHandler {
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.tooltip(tooltip)
|
||||
.tooltip_label(name)
|
||||
.tooltip_description(description)
|
||||
.for_label(checkbox_id)
|
||||
.widget_holder(),
|
||||
TextLabel::new(name).tooltip(tooltip).for_checkbox(checkbox_id).widget_holder(),
|
||||
TextLabel::new(name).tooltip_label(name).tooltip_description(description).for_checkbox(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 {
|
||||
.chain(SNAP_FUNCTIONS_FOR_PATHS.into_iter().map(|(name, closure, description)| LayoutGroup::Row {
|
||||
widgets: {
|
||||
let checkbox_id = CheckboxId::new();
|
||||
vec![
|
||||
@@ -2528,10 +2529,11 @@ impl DocumentMessageHandler {
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.tooltip(tooltip)
|
||||
.tooltip_label(name)
|
||||
.tooltip_description(description)
|
||||
.for_label(checkbox_id)
|
||||
.widget_holder(),
|
||||
TextLabel::new(name).tooltip(tooltip).for_checkbox(checkbox_id).widget_holder(),
|
||||
TextLabel::new(name).tooltip_label(name).tooltip_description(description).for_checkbox(checkbox_id).widget_holder(),
|
||||
]
|
||||
},
|
||||
}))
|
||||
@@ -2541,8 +2543,8 @@ impl DocumentMessageHandler {
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
CheckboxInput::new(self.snapping_state.grid_snapping)
|
||||
.icon("Grid")
|
||||
.tooltip("Grid")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ToggleGridVisibility))
|
||||
.tooltip_label("Grid")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::ToggleGridVisibility))
|
||||
.on_update(|optional_input: &CheckboxInput| DocumentMessage::GridVisibility { visible: optional_input.checked }.into())
|
||||
.widget_holder(),
|
||||
PopoverButton::new()
|
||||
@@ -2553,19 +2555,19 @@ impl DocumentMessageHandler {
|
||||
RadioInput::new(vec![
|
||||
RadioEntryData::new("Normal")
|
||||
.icon("RenderModeNormal")
|
||||
.tooltip("Render Mode: Normal")
|
||||
.tooltip_label("Render Mode: Normal")
|
||||
.on_update(|_| DocumentMessage::SetRenderMode { render_mode: RenderMode::Normal }.into()),
|
||||
RadioEntryData::new("Outline")
|
||||
.icon("RenderModeOutline")
|
||||
.tooltip("Render Mode: Outline")
|
||||
.tooltip_label("Render Mode: Outline")
|
||||
.on_update(|_| DocumentMessage::SetRenderMode { render_mode: RenderMode::Outline }.into()),
|
||||
// RadioEntryData::new("PixelPreview")
|
||||
// .icon("RenderModePixels")
|
||||
// .tooltip("Render Mode: Pixel Preview")
|
||||
// .tooltip_label("Render Mode: Pixel Preview")
|
||||
// .on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(320) }.into()),
|
||||
// RadioEntryData::new("SvgPreview")
|
||||
// .icon("RenderModeSvg")
|
||||
// .tooltip("Render Mode: SVG Preview")
|
||||
// .tooltip_label("Render Mode: SVG Preview")
|
||||
// .on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(1845) }.into()),
|
||||
])
|
||||
.selected_index(Some(self.render_mode as u32))
|
||||
@@ -2607,7 +2609,7 @@ impl DocumentMessageHandler {
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.tooltip("Canvas Tilt")
|
||||
.tooltip_label("Canvas Tilt")
|
||||
.on_update(|number_input: &NumberInput| {
|
||||
NavigationMessage::CanvasTiltSet {
|
||||
angle_radians: number_input.value.unwrap().to_radians(),
|
||||
@@ -2623,8 +2625,8 @@ impl DocumentMessageHandler {
|
||||
TextButton::new("Node Graph")
|
||||
.icon(Some((if self.graph_view_overlay_open { "GraphViewOpen" } else { "GraphViewClosed" }).into()))
|
||||
.hover_icon(Some((if self.graph_view_overlay_open { "GraphViewClosed" } else { "GraphViewOpen" }).into()))
|
||||
.tooltip(if self.graph_view_overlay_open { "Hide Node Graph" } else { "Show Node Graph" })
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::GraphViewOverlayToggle))
|
||||
.tooltip_label(if self.graph_view_overlay_open { "Hide Node Graph" } else { "Show Node Graph" })
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::GraphViewOverlayToggle))
|
||||
.on_update(move |_| DocumentMessage::GraphViewOverlayToggle.into())
|
||||
.widget_holder(),
|
||||
]);
|
||||
@@ -2723,7 +2725,7 @@ impl DocumentMessageHandler {
|
||||
.disabled(disabled)
|
||||
.draw_icon(false)
|
||||
.max_width(100)
|
||||
.tooltip("Blend Mode")
|
||||
.tooltip_label("Blend Mode")
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
NumberInput::new(opacity)
|
||||
@@ -2745,7 +2747,7 @@ impl DocumentMessageHandler {
|
||||
})
|
||||
.on_commit(|_| DocumentMessage::AddTransaction.into())
|
||||
.max_width(100)
|
||||
.tooltip("Opacity")
|
||||
.tooltip_label("Opacity")
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
NumberInput::new(fill)
|
||||
@@ -2767,7 +2769,7 @@ impl DocumentMessageHandler {
|
||||
})
|
||||
.on_commit(|_| DocumentMessage::AddTransaction.into())
|
||||
.max_width(100)
|
||||
.tooltip("Fill")
|
||||
.tooltip_label("Fill")
|
||||
.widget_holder(),
|
||||
];
|
||||
let layers_panel_control_bar_left = WidgetLayout::new(vec![LayoutGroup::Row { widgets }]);
|
||||
@@ -2775,15 +2777,15 @@ impl DocumentMessageHandler {
|
||||
let widgets = vec![
|
||||
IconButton::new(if selection_all_locked { "PadlockLocked" } else { "PadlockUnlocked" }, 24)
|
||||
.hover_icon(Some((if selection_all_locked { "PadlockUnlocked" } else { "PadlockLocked" }).into()))
|
||||
.tooltip(if selection_all_locked { "Unlock Selected" } else { "Lock Selected" })
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ToggleSelectedLocked))
|
||||
.tooltip_label(if selection_all_locked { "Unlock Selected" } else { "Lock Selected" })
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::ToggleSelectedLocked))
|
||||
.on_update(|_| NodeGraphMessage::ToggleSelectedLocked.into())
|
||||
.disabled(!has_selection)
|
||||
.widget_holder(),
|
||||
IconButton::new(if selection_all_visible { "EyeVisible" } else { "EyeHidden" }, 24)
|
||||
.hover_icon(Some((if selection_all_visible { "EyeHide" } else { "EyeShow" }).into()))
|
||||
.tooltip(if selection_all_visible { "Hide Selected" } else { "Show Selected" })
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ToggleSelectedVisibility))
|
||||
.tooltip_label(if selection_all_visible { "Hide Selected" } else { "Show Selected" })
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::ToggleSelectedVisibility))
|
||||
.on_update(|_| DocumentMessage::ToggleSelectedVisibility.into())
|
||||
.disabled(!has_selection)
|
||||
.widget_holder(),
|
||||
@@ -2816,7 +2818,7 @@ impl DocumentMessageHandler {
|
||||
PopoverButton::new()
|
||||
.icon(Some("Node".to_string()))
|
||||
.menu_direction(Some(MenuDirection::Top))
|
||||
.tooltip("Add an operation to the end of this layer's chain of nodes")
|
||||
.tooltip_description("Add an operation to the end of this layer's chain of nodes.")
|
||||
.disabled(!has_selection || has_multiple_selection)
|
||||
.popover_layout({
|
||||
// Showing only compatible types for the layer based on the output type of the node upstream from its horizontal input
|
||||
@@ -2847,8 +2849,8 @@ impl DocumentMessageHandler {
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
IconButton::new("Folder", 24)
|
||||
.tooltip("Group Selected")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::GroupSelectedLayers))
|
||||
.tooltip_label("Group Selected")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::GroupSelectedLayers))
|
||||
.on_update(|_| {
|
||||
let group_folder_type = GroupFolderType::Layer;
|
||||
DocumentMessage::GroupSelectedLayers { group_folder_type }.into()
|
||||
@@ -2856,13 +2858,13 @@ impl DocumentMessageHandler {
|
||||
.disabled(!has_selection)
|
||||
.widget_holder(),
|
||||
IconButton::new("NewLayer", 24)
|
||||
.tooltip("New Layer")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder))
|
||||
.tooltip_label("New Layer")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder))
|
||||
.on_update(|_| DocumentMessage::CreateEmptyFolder.into())
|
||||
.widget_holder(),
|
||||
IconButton::new("Trash", 24)
|
||||
.tooltip("Delete Selected")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::DeleteSelectedLayers))
|
||||
.tooltip_label("Delete Selected")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::DeleteSelectedLayers))
|
||||
.on_update(|_| DocumentMessage::DeleteSelectedLayers.into())
|
||||
.disabled(!has_selection)
|
||||
.widget_holder(),
|
||||
@@ -3145,18 +3147,18 @@ impl<'a> ClickXRayIter<'a> {
|
||||
pub fn navigation_controls(ptz: &PTZ, navigation_handler: &NavigationMessageHandler, node_graph: bool) -> Vec<WidgetHolder> {
|
||||
let mut list = vec![
|
||||
IconButton::new("ZoomIn", 24)
|
||||
.tooltip("Zoom In")
|
||||
.tooltip_shortcut(action_keys!(NavigationMessageDiscriminant::CanvasZoomIncrease))
|
||||
.tooltip_label("Zoom In")
|
||||
.shortcut_keys(action_keys!(NavigationMessageDiscriminant::CanvasZoomIncrease))
|
||||
.on_update(|_| NavigationMessage::CanvasZoomIncrease { center_on_mouse: false }.into())
|
||||
.widget_holder(),
|
||||
IconButton::new("ZoomOut", 24)
|
||||
.tooltip("Zoom Out")
|
||||
.tooltip_shortcut(action_keys!(NavigationMessageDiscriminant::CanvasZoomDecrease))
|
||||
.tooltip_label("Zoom Out")
|
||||
.shortcut_keys(action_keys!(NavigationMessageDiscriminant::CanvasZoomDecrease))
|
||||
.on_update(|_| NavigationMessage::CanvasZoomDecrease { center_on_mouse: false }.into())
|
||||
.widget_holder(),
|
||||
IconButton::new("ZoomReset", 24)
|
||||
.tooltip("Reset Tilt and Zoom to 100%")
|
||||
.tooltip_shortcut(action_keys!(NavigationMessageDiscriminant::CanvasTiltResetAndZoomTo100Percent))
|
||||
.tooltip_label("Reset Tilt and Zoom to 100%")
|
||||
.shortcut_keys(action_keys!(NavigationMessageDiscriminant::CanvasTiltResetAndZoomTo100Percent))
|
||||
.on_update(|_| NavigationMessage::CanvasTiltResetAndZoomTo100Percent.into())
|
||||
.disabled(ptz.tilt().abs() < 1e-4 && (ptz.zoom() - 1.).abs() < 1e-4)
|
||||
.widget_holder(),
|
||||
@@ -3164,8 +3166,9 @@ pub fn navigation_controls(ptz: &PTZ, navigation_handler: &NavigationMessageHand
|
||||
if ptz.flip && !node_graph {
|
||||
list.push(
|
||||
IconButton::new("Reverse", 24)
|
||||
.tooltip("Flip the canvas back to its standard orientation")
|
||||
.tooltip_shortcut(action_keys!(NavigationMessageDiscriminant::CanvasFlip))
|
||||
.tooltip_label("Unflip Canvas")
|
||||
.tooltip_description("Flip the canvas back to its standard orientation.")
|
||||
.shortcut_keys(action_keys!(NavigationMessageDiscriminant::CanvasFlip))
|
||||
.on_update(|_| NavigationMessage::CanvasFlip.into())
|
||||
.widget_holder(),
|
||||
);
|
||||
@@ -3176,7 +3179,7 @@ pub fn navigation_controls(ptz: &PTZ, navigation_handler: &NavigationMessageHand
|
||||
.unit("%")
|
||||
.min(0.000001)
|
||||
.max(1000000.)
|
||||
.tooltip(if node_graph { "Node Graph Zoom" } else { "Canvas Zoom" })
|
||||
.tooltip_label(if node_graph { "Node Graph Zoom" } else { "Canvas Zoom" })
|
||||
.on_update(|number_input: &NumberInput| {
|
||||
NavigationMessage::CanvasZoomSet {
|
||||
zoom_factor: number_input.value.unwrap() / 100.,
|
||||
|
||||
@@ -137,7 +137,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
description: Cow::Borrowed("A default node network you can use to create your own custom nodes."),
|
||||
description: Cow::Borrowed("An empty node network you can use to create your own custom nodes."),
|
||||
properties: None,
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
@@ -156,7 +156,10 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
description: Cow::Borrowed("TODO"),
|
||||
description: Cow::Borrowed(
|
||||
"Improves rendering performance if used in rare circumstances where automatic caching is not yet advanced enough to handle the situation.
|
||||
Stores the last evaluated data that flowed through this node, and immediately returns that data on subsequent renders if the context has not changed.",
|
||||
),
|
||||
properties: None,
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
@@ -1153,7 +1156,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
description: Cow::Borrowed("Generates different noise patterns."),
|
||||
description: Cow::Borrowed("Generates customizable procedural noise patterns."),
|
||||
properties: None,
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
@@ -1335,7 +1338,9 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
},
|
||||
},
|
||||
description: Cow::Borrowed(
|
||||
"Decomposes the X and Y components of a vec2.\n\nThe inverse of this node is \"Vec2 Value\", which can have either or both its X and Y parameters exposed as graph inputs.",
|
||||
"Decomposes the X and Y components of a vec2.\n\
|
||||
\n\
|
||||
The inverse of this node is \"Vec2 Value\", which can have either or both its X and Y parameters exposed as graph inputs.",
|
||||
),
|
||||
properties: None,
|
||||
},
|
||||
@@ -2008,10 +2013,10 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
}),
|
||||
input_metadata: vec![
|
||||
("Content", "The shape to be resampled and converted into a polyline.").into(),
|
||||
("Spacing", node_properties::SAMPLE_POLYLINE_TOOLTIP_SPACING).into(),
|
||||
("Spacing", node_properties::SAMPLE_POLYLINE_DESCRIPTION_SPACING).into(),
|
||||
InputMetadata::with_name_description_override(
|
||||
"Separation",
|
||||
node_properties::SAMPLE_POLYLINE_TOOLTIP_SEPARATION,
|
||||
node_properties::SAMPLE_POLYLINE_DESCRIPTION_SEPARATION,
|
||||
WidgetOverride::Number(NumberInputSettings {
|
||||
min: Some(0.),
|
||||
unit: Some(" px".to_string()),
|
||||
@@ -2020,7 +2025,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
),
|
||||
InputMetadata::with_name_description_override(
|
||||
"Quantity",
|
||||
node_properties::SAMPLE_POLYLINE_TOOLTIP_QUANTITY,
|
||||
node_properties::SAMPLE_POLYLINE_DESCRIPTION_QUANTITY,
|
||||
WidgetOverride::Number(NumberInputSettings {
|
||||
min: Some(2.),
|
||||
is_integer: true,
|
||||
@@ -2029,7 +2034,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
),
|
||||
InputMetadata::with_name_description_override(
|
||||
"Start Offset",
|
||||
node_properties::SAMPLE_POLYLINE_TOOLTIP_START_OFFSET,
|
||||
node_properties::SAMPLE_POLYLINE_DESCRIPTION_START_OFFSET,
|
||||
WidgetOverride::Number(NumberInputSettings {
|
||||
min: Some(0.),
|
||||
unit: Some(" px".to_string()),
|
||||
@@ -2038,14 +2043,14 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
),
|
||||
InputMetadata::with_name_description_override(
|
||||
"Stop Offset",
|
||||
node_properties::SAMPLE_POLYLINE_TOOLTIP_STOP_OFFSET,
|
||||
node_properties::SAMPLE_POLYLINE_DESCRIPTION_STOP_OFFSET,
|
||||
WidgetOverride::Number(NumberInputSettings {
|
||||
min: Some(0.),
|
||||
unit: Some(" px".to_string()),
|
||||
..Default::default()
|
||||
}),
|
||||
),
|
||||
("Adaptive Spacing", node_properties::SAMPLE_POLYLINE_TOOLTIP_ADAPTIVE_SPACING).into(),
|
||||
("Adaptive Spacing", node_properties::SAMPLE_POLYLINE_DESCRIPTION_ADAPTIVE_SPACING).into(),
|
||||
],
|
||||
output_names: vec!["Vector".to_string()],
|
||||
..Default::default()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::utility_types::{BoxSelection, ContextMenuInformation, DragStart, FrontendNode};
|
||||
use super::{document_node_definitions, node_properties};
|
||||
use crate::consts::GRID_SIZE;
|
||||
use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup;
|
||||
use crate::messages::input_mapper::utility_types::macros::action_keys;
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
use crate::messages::portfolio::document::document_message_handler::navigation_controls;
|
||||
@@ -2105,7 +2106,9 @@ impl NodeGraphMessageHandler {
|
||||
let mut widgets = vec![
|
||||
PopoverButton::new()
|
||||
.icon(Some("Node".to_string()))
|
||||
.tooltip("New Node (Right Click)")
|
||||
.tooltip_label("New Node")
|
||||
.tooltip_description("To add a node at the pointer location, perform the shortcut in an open area of the graph.")
|
||||
.tooltip_shortcut(Key::MouseRight.to_string())
|
||||
.popover_layout({
|
||||
// Showing only compatible types
|
||||
let compatible_type = match (selection_includes_layers, has_multiple_selection, selected_layer) {
|
||||
@@ -2150,8 +2153,8 @@ impl NodeGraphMessageHandler {
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
//
|
||||
IconButton::new("Folder", 24)
|
||||
.tooltip("Group Selected")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::GroupSelectedLayers))
|
||||
.tooltip_label("Group Selected")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::GroupSelectedLayers))
|
||||
.on_update(|_| {
|
||||
let group_folder_type = GroupFolderType::Layer;
|
||||
DocumentMessage::GroupSelectedLayers { group_folder_type }.into()
|
||||
@@ -2159,13 +2162,13 @@ impl NodeGraphMessageHandler {
|
||||
.disabled(!has_selection)
|
||||
.widget_holder(),
|
||||
IconButton::new("NewLayer", 24)
|
||||
.tooltip("New Layer")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder))
|
||||
.tooltip_label("New Layer")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder))
|
||||
.on_update(|_| DocumentMessage::CreateEmptyFolder.into())
|
||||
.widget_holder(),
|
||||
IconButton::new("Trash", 24)
|
||||
.tooltip("Delete Selected")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::DeleteSelectedLayers))
|
||||
.tooltip_label("Delete Selected")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::DeleteSelectedLayers))
|
||||
.on_update(|_| DocumentMessage::DeleteSelectedLayers.into())
|
||||
.disabled(!has_selection)
|
||||
.widget_holder(),
|
||||
@@ -2174,15 +2177,15 @@ impl NodeGraphMessageHandler {
|
||||
//
|
||||
IconButton::new(if selection_all_locked { "PadlockLocked" } else { "PadlockUnlocked" }, 24)
|
||||
.hover_icon(Some((if selection_all_locked { "PadlockUnlocked" } else { "PadlockLocked" }).into()))
|
||||
.tooltip(if selection_all_locked { "Unlock Selected" } else { "Lock Selected" })
|
||||
.tooltip_shortcut(action_keys!(NodeGraphMessageDiscriminant::ToggleSelectedLocked))
|
||||
.tooltip_label(if selection_all_locked { "Unlock Selected" } else { "Lock Selected" })
|
||||
.shortcut_keys(action_keys!(NodeGraphMessageDiscriminant::ToggleSelectedLocked))
|
||||
.on_update(|_| NodeGraphMessage::ToggleSelectedLocked.into())
|
||||
.disabled(!has_selection || !selection_includes_layers)
|
||||
.widget_holder(),
|
||||
IconButton::new(if selection_all_visible { "EyeVisible" } else { "EyeHidden" }, 24)
|
||||
.hover_icon(Some((if selection_all_visible { "EyeHide" } else { "EyeShow" }).into()))
|
||||
.tooltip(if selection_all_visible { "Hide Selected" } else { "Show Selected" })
|
||||
.tooltip_shortcut(action_keys!(NodeGraphMessageDiscriminant::ToggleSelectedVisibility))
|
||||
.tooltip_label(if selection_all_visible { "Hide Selected" } else { "Show Selected" })
|
||||
.shortcut_keys(action_keys!(NodeGraphMessageDiscriminant::ToggleSelectedVisibility))
|
||||
.on_update(|_| NodeGraphMessage::ToggleSelectedVisibility.into())
|
||||
.disabled(!has_selection)
|
||||
.widget_holder(),
|
||||
@@ -2208,7 +2211,7 @@ impl NodeGraphMessageHandler {
|
||||
if let Some(node_id) = previewing {
|
||||
let button = TextButton::new("End Preview")
|
||||
.icon(Some("FrameAll".to_string()))
|
||||
.tooltip("Restore preview to the graph output")
|
||||
.tooltip_description("Restore preview to the graph output.")
|
||||
.on_update(move |_| NodeGraphMessage::TogglePreview { node_id }.into())
|
||||
.widget_holder();
|
||||
widgets.extend([Separator::new(SeparatorType::Unrelated).widget_holder(), button]);
|
||||
@@ -2220,7 +2223,9 @@ impl NodeGraphMessageHandler {
|
||||
if selection_is_not_already_the_output && no_other_selections {
|
||||
let button = TextButton::new("Preview")
|
||||
.icon(Some("FrameAll".to_string()))
|
||||
.tooltip("Preview selected node/layer (Shortcut: Alt-click node/layer)")
|
||||
.tooltip_label("Preview")
|
||||
.tooltip_description("Temporarily set the graph output to the selected node or layer. Perform the shortcut on a node or layer for quick access.")
|
||||
.tooltip_shortcut(KeysGroup(vec![Key::Alt, Key::MouseLeft]).to_string())
|
||||
.on_update(move |_| NodeGraphMessage::TogglePreview { node_id }.into())
|
||||
.widget_holder();
|
||||
widgets.extend([Separator::new(SeparatorType::Unrelated).widget_holder(), button]);
|
||||
@@ -2262,7 +2267,7 @@ impl NodeGraphMessageHandler {
|
||||
.percentage()
|
||||
.display_decimal_places(0)
|
||||
.label("Fade Artwork")
|
||||
.tooltip("Opacity of the graph background that covers the artwork")
|
||||
.tooltip_description("Opacity of the graph background that covers the artwork.")
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
DocumentMessage::SetGraphFadeArtwork {
|
||||
percentage: number_input.value.unwrap_or(graph_fade_artwork_percentage),
|
||||
@@ -2278,8 +2283,8 @@ impl NodeGraphMessageHandler {
|
||||
TextButton::new("Node Graph")
|
||||
.icon(Some("GraphViewOpen".into()))
|
||||
.hover_icon(Some("GraphViewClosed".into()))
|
||||
.tooltip("Hide Node Graph")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::GraphViewOverlayToggle))
|
||||
.tooltip_label("Hide Node Graph")
|
||||
.shortcut_keys(action_keys!(DocumentMessageDiscriminant::GraphViewOverlayToggle))
|
||||
.on_update(move |_| DocumentMessage::GraphViewOverlayToggle.into())
|
||||
.widget_holder(),
|
||||
]);
|
||||
@@ -2329,10 +2334,10 @@ impl NodeGraphMessageHandler {
|
||||
properties.push(LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
IconLabel::new("Node").tooltip("Name of the selected node").widget_holder(),
|
||||
IconLabel::new("Node").tooltip_description("Name of the selected node.").widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
TextInput::new(context.network_interface.display_name(&node_id, context.selection_network_path))
|
||||
.tooltip("Name of the selected node")
|
||||
.tooltip_description("Name of the selected node.")
|
||||
.on_update(move |text_input| {
|
||||
NodeGraphMessage::SetDisplayName {
|
||||
node_id,
|
||||
@@ -2357,10 +2362,10 @@ impl NodeGraphMessageHandler {
|
||||
let mut properties = vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
IconLabel::new("File").tooltip("Name of the current document").widget_holder(),
|
||||
IconLabel::new("File").tooltip_description("Name of the current document.").widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
TextInput::new(context.document_name)
|
||||
.tooltip("Name of the current document")
|
||||
.tooltip_description("Name of the current document.")
|
||||
.on_update(|text_input| DocumentMessage::RenameDocument { new_name: text_input.value.clone() }.into())
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
@@ -2404,10 +2409,10 @@ impl NodeGraphMessageHandler {
|
||||
let mut layer_properties = vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
IconLabel::new("Layer").tooltip("Name of the selected layer").widget_holder(),
|
||||
IconLabel::new("Layer").tooltip_description("Name of the selected layer.").widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
TextInput::new(context.network_interface.display_name(&layer, context.selection_network_path))
|
||||
.tooltip("Name of the selected layer")
|
||||
.tooltip_description("Name of the selected layer.")
|
||||
.on_update(move |text_input| {
|
||||
NodeGraphMessage::SetDisplayName {
|
||||
node_id: layer,
|
||||
@@ -2420,7 +2425,7 @@ impl NodeGraphMessageHandler {
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
PopoverButton::new()
|
||||
.icon(Some("Node".to_string()))
|
||||
.tooltip("Add an operation to the end of this layer's chain of nodes")
|
||||
.tooltip_description("Add an operation to the end of this layer's chain of nodes.")
|
||||
.popover_layout({
|
||||
let compatible_type = context
|
||||
.network_interface
|
||||
@@ -2680,7 +2685,6 @@ impl NodeGraphMessageHandler {
|
||||
let data = LayerPanelEntry {
|
||||
id: node_id,
|
||||
alias: network_interface.display_name(&node_id, &[]),
|
||||
tooltip: if cfg!(debug_assertions) { format!("Layer ID: {node_id}") } else { "".into() },
|
||||
in_selected_network: selection_network_path.is_empty(),
|
||||
children_allowed,
|
||||
children_present: layer.has_children(network_interface.document_metadata()),
|
||||
|
||||
@@ -50,10 +50,10 @@ pub fn expose_widget(node_id: NodeId, index: usize, data_type: FrontendGraphData
|
||||
ParameterExposeButton::new()
|
||||
.exposed(exposed)
|
||||
.data_type(data_type)
|
||||
.tooltip(if exposed {
|
||||
"Stop exposing this parameter as a node input in the graph"
|
||||
.tooltip_description(if exposed {
|
||||
"Stop exposing this parameter as a node input in the graph."
|
||||
} else {
|
||||
"Expose this parameter as a node input in the graph"
|
||||
"Expose this parameter as a node input in the graph."
|
||||
})
|
||||
.on_update(move |_parameter| Message::Batched {
|
||||
messages: Box::new([NodeGraphMessage::ExposeInput {
|
||||
@@ -97,12 +97,11 @@ pub fn start_widgets(parameter_widgets_info: ParameterWidgetsInfo) -> Vec<Widget
|
||||
log::warn!("A widget failed to be built because its node's input index is invalid.");
|
||||
return vec![];
|
||||
};
|
||||
let description = if description != "TODO" { description } else { String::new() };
|
||||
let mut widgets = Vec::with_capacity(6);
|
||||
if exposable {
|
||||
widgets.push(expose_widget(node_id, index, input_type, input.is_exposed()));
|
||||
}
|
||||
widgets.push(TextLabel::new(name).tooltip(description).widget_holder());
|
||||
widgets.push(TextLabel::new(name).tooltip_description(description).widget_holder());
|
||||
if blank_assist {
|
||||
add_blank_assist(&mut widgets);
|
||||
}
|
||||
@@ -232,16 +231,16 @@ pub(crate) fn property_from_type(
|
||||
widgets.extend_from_slice(&[
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
TextLabel::new("-")
|
||||
.tooltip(format!(
|
||||
"This data can only be supplied through the node graph because no widget exists for its type:\n\
|
||||
{}",
|
||||
// TODO: Avoid needing to remove spaces here by fixing how `alias` is generated
|
||||
.tooltip_label(format!(
|
||||
"Data Type: {}",
|
||||
concrete_type
|
||||
.alias
|
||||
.as_deref()
|
||||
// TODO: Avoid needing to remove spaces here by fixing how `alias` is generated
|
||||
.map(|s| s.to_string().replace(" ", ""))
|
||||
.unwrap_or_else(|| graphene_std::format_type(concrete_type.name.as_ref()))
|
||||
.unwrap_or_else(|| graphene_std::format_type(concrete_type.name.as_ref())),
|
||||
))
|
||||
.tooltip_description("This data can only be supplied through the node graph because no widget exists for its type.")
|
||||
.widget_holder(),
|
||||
]);
|
||||
return Err(vec![widgets.into()]);
|
||||
@@ -961,7 +960,7 @@ pub fn blend_mode_widget(parameter_widgets_info: ParameterWidgetsInfo) -> Layout
|
||||
.widget_holder(),
|
||||
]);
|
||||
}
|
||||
LayoutGroup::Row { widgets }.with_tooltip("Formula used for blending")
|
||||
LayoutGroup::Row { widgets }.with_tooltip_description("Formula used for blending.")
|
||||
}
|
||||
|
||||
pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button: ColorInput) -> LayoutGroup {
|
||||
@@ -1400,12 +1399,12 @@ pub(crate) fn spiral_properties(node_id: NodeId, context: &mut NodePropertiesCon
|
||||
widgets
|
||||
}
|
||||
|
||||
pub(crate) const SAMPLE_POLYLINE_TOOLTIP_SPACING: &str = "Use a point sampling density controlled by a distance between, or specific number of, points.";
|
||||
pub(crate) const SAMPLE_POLYLINE_TOOLTIP_SEPARATION: &str = "Distance between each instance (exact if 'Adaptive Spacing' is disabled, approximate if enabled).";
|
||||
pub(crate) const SAMPLE_POLYLINE_TOOLTIP_QUANTITY: &str = "Number of points to place along the path.";
|
||||
pub(crate) const SAMPLE_POLYLINE_TOOLTIP_START_OFFSET: &str = "Exclude some distance from the start of the path before the first instance.";
|
||||
pub(crate) const SAMPLE_POLYLINE_TOOLTIP_STOP_OFFSET: &str = "Exclude some distance from the end of the path after the last instance.";
|
||||
pub(crate) const SAMPLE_POLYLINE_TOOLTIP_ADAPTIVE_SPACING: &str = "Round 'Separation' to a nearby value that divides into the path length evenly.";
|
||||
pub(crate) const SAMPLE_POLYLINE_DESCRIPTION_SPACING: &str = "Use a point sampling density controlled by a distance between, or specific number of, points.";
|
||||
pub(crate) const SAMPLE_POLYLINE_DESCRIPTION_SEPARATION: &str = "Distance between each instance (exact if 'Adaptive Spacing' is disabled, approximate if enabled).";
|
||||
pub(crate) const SAMPLE_POLYLINE_DESCRIPTION_QUANTITY: &str = "Number of points to place along the path.";
|
||||
pub(crate) const SAMPLE_POLYLINE_DESCRIPTION_START_OFFSET: &str = "Exclude some distance from the start of the path before the first instance.";
|
||||
pub(crate) const SAMPLE_POLYLINE_DESCRIPTION_STOP_OFFSET: &str = "Exclude some distance from the end of the path after the last instance.";
|
||||
pub(crate) const SAMPLE_POLYLINE_DESCRIPTION_ADAPTIVE_SPACING: &str = "Round 'Separation' to a nearby value that divides into the path length evenly.";
|
||||
|
||||
pub(crate) fn sample_polyline_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
use graphene_std::vector::sample_polyline::*;
|
||||
@@ -1434,15 +1433,15 @@ pub(crate) fn sample_polyline_properties(node_id: NodeId, context: &mut NodeProp
|
||||
);
|
||||
|
||||
vec![
|
||||
spacing.with_tooltip(SAMPLE_POLYLINE_TOOLTIP_SPACING),
|
||||
spacing.with_tooltip_description(SAMPLE_POLYLINE_DESCRIPTION_SPACING),
|
||||
match current_spacing {
|
||||
Some(TaggedValue::PointSpacingType(PointSpacingType::Separation)) => LayoutGroup::Row { widgets: separation }.with_tooltip(SAMPLE_POLYLINE_TOOLTIP_SEPARATION),
|
||||
Some(TaggedValue::PointSpacingType(PointSpacingType::Quantity)) => LayoutGroup::Row { widgets: quantity }.with_tooltip(SAMPLE_POLYLINE_TOOLTIP_QUANTITY),
|
||||
Some(TaggedValue::PointSpacingType(PointSpacingType::Separation)) => LayoutGroup::Row { widgets: separation }.with_tooltip_description(SAMPLE_POLYLINE_DESCRIPTION_SEPARATION),
|
||||
Some(TaggedValue::PointSpacingType(PointSpacingType::Quantity)) => LayoutGroup::Row { widgets: quantity }.with_tooltip_description(SAMPLE_POLYLINE_DESCRIPTION_QUANTITY),
|
||||
_ => LayoutGroup::Row { widgets: vec![] },
|
||||
},
|
||||
LayoutGroup::Row { widgets: start_offset }.with_tooltip(SAMPLE_POLYLINE_TOOLTIP_START_OFFSET),
|
||||
LayoutGroup::Row { widgets: stop_offset }.with_tooltip(SAMPLE_POLYLINE_TOOLTIP_STOP_OFFSET),
|
||||
LayoutGroup::Row { widgets: adaptive_spacing }.with_tooltip(SAMPLE_POLYLINE_TOOLTIP_ADAPTIVE_SPACING),
|
||||
LayoutGroup::Row { widgets: start_offset }.with_tooltip_description(SAMPLE_POLYLINE_DESCRIPTION_START_OFFSET),
|
||||
LayoutGroup::Row { widgets: stop_offset }.with_tooltip_description(SAMPLE_POLYLINE_DESCRIPTION_STOP_OFFSET),
|
||||
LayoutGroup::Row { widgets: adaptive_spacing }.with_tooltip_description(SAMPLE_POLYLINE_DESCRIPTION_ADAPTIVE_SPACING),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1776,7 +1775,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
||||
Fill::Solid(_) | Fill::None => add_blank_assist(&mut row),
|
||||
Fill::Gradient(gradient) => {
|
||||
let reverse_button = IconButton::new("Reverse", 24)
|
||||
.tooltip("Reverse the gradient color stops")
|
||||
.tooltip_description("Reverse the gradient color stops.")
|
||||
.on_update(update_value(
|
||||
{
|
||||
let gradient = gradient.clone();
|
||||
@@ -1826,7 +1825,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
||||
(gradient.start.x + gradient.start.y) < (gradient.end.x + gradient.end.y)
|
||||
};
|
||||
let reverse_radial_gradient_button = IconButton::new(if orientation { "ReverseRadialGradientToRight" } else { "ReverseRadialGradientToLeft" }, 24)
|
||||
.tooltip("Reverse which end the gradient radiates from")
|
||||
.tooltip_description("Reverse which end the gradient radiates from.")
|
||||
.on_update(update_value(
|
||||
{
|
||||
let gradient = gradient.clone();
|
||||
@@ -2027,9 +2026,9 @@ pub fn math_properties(node_id: NodeId, context: &mut NodePropertiesContext) ->
|
||||
let operand_a_hint = vec![TextLabel::new("(Operand A is the primary input)").widget_holder()];
|
||||
|
||||
vec![
|
||||
LayoutGroup::Row { widgets: expression }.with_tooltip(r#"A math expression that may incorporate "A" and/or "B", such as "sqrt(A + B) - B^2""#),
|
||||
LayoutGroup::Row { widgets: operand_b }.with_tooltip(r#"The value of "B" when calculating the expression"#),
|
||||
LayoutGroup::Row { widgets: operand_a_hint }.with_tooltip(r#""A" is fed by the value from the previous node in the primary data flow, or it is 0 if disconnected"#),
|
||||
LayoutGroup::Row { widgets: expression }.with_tooltip_description(r#"A math expression that may incorporate "A" and/or "B", such as "sqrt(A + B) - B^2"."#),
|
||||
LayoutGroup::Row { widgets: operand_b }.with_tooltip_description(r#"The value of "B" when calculating the expression."#),
|
||||
LayoutGroup::Row { widgets: operand_a_hint }.with_tooltip_description(r#""A" is fed by the value from the previous node in the primary data flow, or it is 0 if disconnected."#),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2149,13 +2148,12 @@ pub mod choice {
|
||||
.map(|(item, var_meta)| {
|
||||
let updater = updater_factory();
|
||||
let committer = committer_factory();
|
||||
let entry = RadioEntryData::new(var_meta.name).on_update(move |_| updater(item)).on_commit(committer);
|
||||
match (var_meta.icon, var_meta.docstring) {
|
||||
(None, None) => entry.label(var_meta.label),
|
||||
(None, Some(doc)) => entry.label(var_meta.label).tooltip(doc),
|
||||
(Some(icon), None) => entry.icon(icon).tooltip(var_meta.label),
|
||||
(Some(icon), Some(doc)) => entry.icon(icon).tooltip(format!("{}\n\n{}", var_meta.label, doc)),
|
||||
}
|
||||
let entry = RadioEntryData::new(var_meta.name)
|
||||
.on_update(move |_| updater(item))
|
||||
.on_commit(committer)
|
||||
.tooltip_label(var_meta.label)
|
||||
.tooltip_description(var_meta.description.unwrap_or_default());
|
||||
if let Some(icon) = var_meta.icon { entry.icon(icon) } else { entry.label(var_meta.label) }
|
||||
})
|
||||
.collect();
|
||||
RadioInput::new(items).selected_index(Some(current.as_u32())).widget_holder()
|
||||
@@ -2229,7 +2227,7 @@ pub mod choice {
|
||||
|
||||
let mut row = LayoutGroup::Row { widgets };
|
||||
if let Some(desc) = self.widget_factory.description() {
|
||||
row = row.with_tooltip(desc);
|
||||
row = row.with_tooltip_label(desc);
|
||||
}
|
||||
row
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ pub struct FrontendGraphInput {
|
||||
#[serde(rename = "validTypes")]
|
||||
pub valid_types: Vec<String>,
|
||||
#[serde(rename = "connectedTo")]
|
||||
/// Either "nothing", "import index {index}", or "{node name} output {output_index}".
|
||||
/// Either "nothing", "import #{index}", or "{node name} #{output_index}".
|
||||
pub connected_to: String,
|
||||
}
|
||||
|
||||
|
||||
@@ -276,14 +276,14 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
|
||||
color_widgets.extend([
|
||||
CheckboxInput::new(grid.dot_display)
|
||||
.icon("GridDotted")
|
||||
.tooltip("Display as dotted grid")
|
||||
.tooltip_label("Display as Dotted Grid")
|
||||
.on_update(update_display(grid, |grid| Some(&mut grid.dot_display)))
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
]);
|
||||
color_widgets.push(
|
||||
ColorInput::new(FillChoice::Solid(grid.grid_color.to_gamma_srgb()))
|
||||
.tooltip("Grid display color")
|
||||
.tooltip_label("Grid Display Color")
|
||||
.allow_none(false)
|
||||
.on_update(update_color(grid, |grid| Some(&mut grid.grid_color)))
|
||||
.widget_holder(),
|
||||
|
||||
@@ -386,55 +386,55 @@ pub const SNAP_FUNCTIONS_FOR_BOUNDING_BOXES: [(&str, GetSnapState, &str); 5] = [
|
||||
(
|
||||
"Align with Edges",
|
||||
(|snapping_state| &mut snapping_state.bounding_box.align_with_edges) as GetSnapState,
|
||||
"Snaps to horizontal/vertical alignment with the edges of any layer's bounding box",
|
||||
"Snaps to horizontal/vertical alignment with the edges of any layer's bounding box.",
|
||||
),
|
||||
(
|
||||
"Corner Points",
|
||||
(|snapping_state| &mut snapping_state.bounding_box.corner_point) as GetSnapState,
|
||||
"Snaps to the four corners of any layer's bounding box",
|
||||
"Snaps to the four corners of any layer's bounding box.",
|
||||
),
|
||||
(
|
||||
"Center Points",
|
||||
(|snapping_state| &mut snapping_state.bounding_box.center_point) as GetSnapState,
|
||||
"Snaps to the center point of any layer's bounding box",
|
||||
"Snaps to the center point of any layer's bounding box.",
|
||||
),
|
||||
(
|
||||
"Edge Midpoints",
|
||||
(|snapping_state| &mut snapping_state.bounding_box.edge_midpoint) as GetSnapState,
|
||||
"Snaps to any of the four points at the middle of the edges of any layer's bounding box",
|
||||
"Snaps to any of the four points at the middle of the edges of any layer's bounding box.",
|
||||
),
|
||||
(
|
||||
"Distribute Evenly",
|
||||
(|snapping_state| &mut snapping_state.bounding_box.distribute_evenly) as GetSnapState,
|
||||
"Snaps to a consistent distance offset established by the bounding boxes of nearby layers",
|
||||
"Snaps to a consistent distance offset established by the bounding boxes of nearby layers.",
|
||||
),
|
||||
];
|
||||
pub const SNAP_FUNCTIONS_FOR_PATHS: [(&str, GetSnapState, &str); 7] = [
|
||||
(
|
||||
"Align with Anchor Points",
|
||||
(|snapping_state: &mut SnappingState| &mut snapping_state.path.align_with_anchor_point) as GetSnapState,
|
||||
"Snaps to horizontal/vertical alignment with the anchor points of any vector path",
|
||||
"Snaps to horizontal/vertical alignment with the anchor points of any vector path.",
|
||||
),
|
||||
(
|
||||
"Anchor Points",
|
||||
(|snapping_state: &mut SnappingState| &mut snapping_state.path.anchor_point) as GetSnapState,
|
||||
"Snaps to the anchor point of any vector path",
|
||||
"Snaps to the anchor point of any vector path.",
|
||||
),
|
||||
(
|
||||
// TODO: Extend to the midpoints of curved segments and rename to "Segment Midpoint"
|
||||
"Line Midpoints",
|
||||
(|snapping_state: &mut SnappingState| &mut snapping_state.path.line_midpoint) as GetSnapState,
|
||||
"Snaps to the point at the middle of any straight line segment of a vector path",
|
||||
"Snaps to the point at the middle of any straight line segment of a vector path.",
|
||||
),
|
||||
(
|
||||
"Path Intersection Points",
|
||||
(|snapping_state: &mut SnappingState| &mut snapping_state.path.path_intersection_point) as GetSnapState,
|
||||
"Snaps to any points where vector paths intersect",
|
||||
"Snaps to any points where vector paths intersect.",
|
||||
),
|
||||
(
|
||||
"Along Paths",
|
||||
(|snapping_state: &mut SnappingState| &mut snapping_state.path.along_path) as GetSnapState,
|
||||
"Snaps along the length of any vector path",
|
||||
"Snaps along the length of any vector path.",
|
||||
),
|
||||
(
|
||||
// TODO: This works correctly for line segments, but not curved segments.
|
||||
@@ -442,7 +442,7 @@ pub const SNAP_FUNCTIONS_FOR_PATHS: [(&str, GetSnapState, &str); 7] = [
|
||||
"Normal to Paths",
|
||||
(|snapping_state: &mut SnappingState| &mut snapping_state.path.normal_to_path) as GetSnapState,
|
||||
// TODO: Fix the bug/limitation that requires 'Intersections of Paths' to be enabled
|
||||
"Snaps a line to a point perpendicular to a vector path\n(due to a bug, 'Intersections of Paths' must be enabled)",
|
||||
"Snaps a line to a point perpendicular to a vector path.\n(Due to a bug, 'Intersections of Paths' must be enabled.)",
|
||||
),
|
||||
(
|
||||
// TODO: This works correctly for line segments, but not curved segments.
|
||||
@@ -450,7 +450,7 @@ pub const SNAP_FUNCTIONS_FOR_PATHS: [(&str, GetSnapState, &str); 7] = [
|
||||
"Tangent to Paths",
|
||||
(|snapping_state: &mut SnappingState| &mut snapping_state.path.tangent_to_path) as GetSnapState,
|
||||
// TODO: Fix the bug/limitation that requires 'Intersections of Paths' to be enabled
|
||||
"Snaps a line to a point tangent to a vector path\n(due to a bug, 'Intersections of Paths' must be enabled)",
|
||||
"Snaps a line to a point tangent to a vector path.\n(Due to a bug, 'Intersections of Paths' must be enabled.)",
|
||||
),
|
||||
];
|
||||
|
||||
|
||||
@@ -631,15 +631,12 @@ impl NodeNetworkInterface {
|
||||
.upstream_output_connector(input_connector, network_path)
|
||||
.map(|output_connector| match output_connector {
|
||||
OutputConnector::Node { node_id, output_index } => {
|
||||
let mut name = self.display_name(&node_id, network_path);
|
||||
if cfg!(debug_assertions) {
|
||||
name.push_str(&format!(" (id: {node_id})"));
|
||||
}
|
||||
format!("{name} output {output_index}")
|
||||
let name = self.display_name(&node_id, network_path);
|
||||
format!("Connected to output #{output_index} of \"{name}\", ID: {node_id}.")
|
||||
}
|
||||
OutputConnector::Import(import_index) => format!("Import index {import_index}"),
|
||||
OutputConnector::Import(import_index) => format!("Connected to import #{import_index}."),
|
||||
})
|
||||
.unwrap_or("nothing".to_string());
|
||||
.unwrap_or("Connected to nothing.".to_string());
|
||||
|
||||
let (name, description) = match input_connector {
|
||||
InputConnector::Node { node_id, input_index } => self.displayed_input_name_and_description(node_id, *input_index, network_path),
|
||||
@@ -659,7 +656,7 @@ impl NodeNetworkInterface {
|
||||
} else if let Some(export_type_name) = input_type.compiled_nested_type().map(|nested| nested.to_string()) {
|
||||
export_type_name
|
||||
} else {
|
||||
format!("Export index {}", export_index)
|
||||
format!("Export #{}", export_index)
|
||||
};
|
||||
|
||||
(export_name, String::new())
|
||||
@@ -709,7 +706,7 @@ impl NodeNetworkInterface {
|
||||
} else if let Some(import_type_name) = output_type.compiled_nested_type().map(|nested| nested.to_string()) {
|
||||
import_type_name
|
||||
} else {
|
||||
format!("Import index {}", import_index)
|
||||
format!("Import #{}", import_index)
|
||||
};
|
||||
|
||||
(import_name, description)
|
||||
@@ -724,19 +721,16 @@ impl NodeNetworkInterface {
|
||||
.unwrap_or_default()
|
||||
.iter()
|
||||
.map(|input| match input {
|
||||
InputConnector::Node { node_id, input_index } => {
|
||||
let mut name = self.display_name(node_id, network_path);
|
||||
if cfg!(debug_assertions) {
|
||||
name.push_str(&format!(" (id: {node_id})"));
|
||||
}
|
||||
format!("{name} input {input_index}")
|
||||
&InputConnector::Node { node_id, input_index } => {
|
||||
let name = self.display_name(&node_id, network_path);
|
||||
format!("Connected to input #{input_index} of \"{name}\", ID: {node_id}.")
|
||||
}
|
||||
InputConnector::Export(export_index) => format!("Export index {export_index}"),
|
||||
InputConnector::Export(export_index) => format!("Connected to export #{export_index}."),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if connected_to.is_empty() {
|
||||
connected_to.push("nothing".to_string());
|
||||
connected_to.push("Connected to nothing.".to_string());
|
||||
}
|
||||
|
||||
Some(FrontendGraphOutput {
|
||||
@@ -1014,7 +1008,6 @@ impl NodeNetworkInterface {
|
||||
pub fn description(&self, node_id: &NodeId, network_path: &[NodeId]) -> String {
|
||||
self.get_node_definition(node_id, network_path)
|
||||
.map(|node_definition| node_definition.description.to_string())
|
||||
.filter(|description| description != "TODO")
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
@@ -6170,7 +6163,7 @@ pub struct InputPersistentMetadata {
|
||||
pub widget_override: Option<String>,
|
||||
/// An empty input name means to use the type as the name.
|
||||
pub input_name: String,
|
||||
/// Displayed as the tooltip.
|
||||
/// Displayed as the tooltip description.
|
||||
pub input_description: String,
|
||||
}
|
||||
|
||||
@@ -6233,8 +6226,8 @@ impl InputPersistentMetadata {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_description(mut self, tooltip: &str) -> Self {
|
||||
self.input_description = tooltip.to_string();
|
||||
pub fn with_description(mut self, description: &str) -> Self {
|
||||
self.input_description = description.to_string();
|
||||
self
|
||||
}
|
||||
}
|
||||
@@ -6314,9 +6307,9 @@ impl From<(&str, &str)> for InputMetadata {
|
||||
}
|
||||
|
||||
impl InputMetadata {
|
||||
pub fn with_name_description_override(input_name: &str, tooltip: &str, widget_override: WidgetOverride) -> Self {
|
||||
pub fn with_name_description_override(input_name: &str, description: &str, widget_override: WidgetOverride) -> Self {
|
||||
InputMetadata {
|
||||
persistent_metadata: InputPersistentMetadata::default().with_name(input_name).with_description(tooltip).with_override(widget_override),
|
||||
persistent_metadata: InputPersistentMetadata::default().with_name(input_name).with_description(description).with_override(widget_override),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ impl TypeSource {
|
||||
self.compiled_nested_type().map(|ty| format!("type:{ty}"))
|
||||
}
|
||||
|
||||
/// The type to display in the tooltip.
|
||||
/// The type to display in the tooltip label.
|
||||
pub fn resolved_type_tooltip_string(&self) -> String {
|
||||
match self {
|
||||
TypeSource::Compiled(compiled_type) => format!("Data Type: {:?}", compiled_type.nested_type().to_string()),
|
||||
|
||||
@@ -35,7 +35,6 @@ impl serde::Serialize for JsRawBuffer {
|
||||
pub struct LayerPanelEntry {
|
||||
pub id: NodeId,
|
||||
pub alias: String,
|
||||
pub tooltip: String,
|
||||
#[serde(rename = "inSelectedNetwork")]
|
||||
pub in_selected_network: bool,
|
||||
#[serde(rename = "childrenAllowed")]
|
||||
|
||||
@@ -42,8 +42,8 @@ impl std::fmt::Display for GraphWireStyle {
|
||||
impl GraphWireStyle {
|
||||
pub fn tooltip_description(&self) -> &'static str {
|
||||
match self {
|
||||
GraphWireStyle::GridAligned => "Wires follow the grid, running in straight lines between nodes",
|
||||
GraphWireStyle::Direct => "Wires bend to run at an angle directly between nodes",
|
||||
GraphWireStyle::GridAligned => "Wires follow the grid, running in straight lines between nodes.",
|
||||
GraphWireStyle::Direct => "Wires bend to run at an angle directly between nodes.",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user