mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-22 03:38:11 +08:00
Tidy up the UI with clearer Layers panel selection marks and removal of most "coming soon" UI elements
This commit is contained in:
@@ -1699,25 +1699,25 @@ impl DocumentMessageHandler {
|
||||
|
||||
let document_mode_layout = WidgetLayout::new(vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
DropdownInput::new(
|
||||
vec![vec![
|
||||
MenuListEntry::new(format!("{:?}", DocumentMode::DesignMode))
|
||||
.label(DocumentMode::DesignMode.to_string())
|
||||
.icon(DocumentMode::DesignMode.icon_name()),
|
||||
MenuListEntry::new(format!("{:?}", DocumentMode::SelectMode))
|
||||
.label(DocumentMode::SelectMode.to_string())
|
||||
.icon(DocumentMode::SelectMode.icon_name())
|
||||
.on_commit(|_| DialogMessage::RequestComingSoonDialog { issue: Some(330) }.into()),
|
||||
MenuListEntry::new(format!("{:?}", DocumentMode::GuideMode))
|
||||
.label(DocumentMode::GuideMode.to_string())
|
||||
.icon(DocumentMode::GuideMode.icon_name())
|
||||
.on_commit(|_| DialogMessage::RequestComingSoonDialog { issue: Some(331) }.into()),
|
||||
]])
|
||||
.selected_index(Some(self.document_mode as u32))
|
||||
.draw_icon(true)
|
||||
.interactive(false) // TODO: set to true when dialogs are not spawned
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Section).widget_holder(),
|
||||
// DropdownInput::new(
|
||||
// vec![vec![
|
||||
// MenuListEntry::new(format!("{:?}", DocumentMode::DesignMode))
|
||||
// .label(DocumentMode::DesignMode.to_string())
|
||||
// .icon(DocumentMode::DesignMode.icon_name()),
|
||||
// MenuListEntry::new(format!("{:?}", DocumentMode::SelectMode))
|
||||
// .label(DocumentMode::SelectMode.to_string())
|
||||
// .icon(DocumentMode::SelectMode.icon_name())
|
||||
// .on_commit(|_| DialogMessage::RequestComingSoonDialog { issue: Some(330) }.into()),
|
||||
// MenuListEntry::new(format!("{:?}", DocumentMode::GuideMode))
|
||||
// .label(DocumentMode::GuideMode.to_string())
|
||||
// .icon(DocumentMode::GuideMode.icon_name())
|
||||
// .on_commit(|_| DialogMessage::RequestComingSoonDialog { issue: Some(331) }.into()),
|
||||
// ]])
|
||||
// .selected_index(Some(self.document_mode as u32))
|
||||
// .draw_icon(true)
|
||||
// .interactive(false) // TODO: set to true when dialogs are not spawned
|
||||
// .widget_holder(),
|
||||
// Separator::new(SeparatorType::Section).widget_holder(),
|
||||
],
|
||||
}]);
|
||||
|
||||
@@ -1744,7 +1744,7 @@ impl DocumentMessageHandler {
|
||||
widgets: vec![TextLabel::new("Overlays").bold(true).widget_holder()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Coming soon").widget_holder()],
|
||||
widgets: vec![TextLabel::new("Granular settings in this menu are coming soon").widget_holder()],
|
||||
},
|
||||
])
|
||||
.widget_holder(),
|
||||
@@ -1828,16 +1828,16 @@ impl DocumentMessageHandler {
|
||||
_ => Some(1),
|
||||
})
|
||||
.widget_holder(),
|
||||
PopoverButton::new()
|
||||
.popover_layout(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("View Mode").bold(true).widget_holder()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Coming soon").widget_holder()],
|
||||
},
|
||||
])
|
||||
.widget_holder(),
|
||||
// PopoverButton::new()
|
||||
// .popover_layout(vec![
|
||||
// LayoutGroup::Row {
|
||||
// widgets: vec![TextLabel::new("View Mode").bold(true).widget_holder()],
|
||||
// },
|
||||
// LayoutGroup::Row {
|
||||
// widgets: vec![TextLabel::new("Coming soon").widget_holder()],
|
||||
// },
|
||||
// ])
|
||||
// .widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
];
|
||||
|
||||
@@ -2191,7 +2191,7 @@ impl<'a> ClickXRayIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn navigation_controls(ptz: &PTZ, navigation_handler: &NavigationMessageHandler, tooltip_name: &str) -> [WidgetHolder; 6] {
|
||||
pub fn navigation_controls(ptz: &PTZ, navigation_handler: &NavigationMessageHandler, tooltip_name: &str) -> [WidgetHolder; 5] {
|
||||
[
|
||||
IconButton::new("ZoomIn", 24)
|
||||
.tooltip("Zoom In")
|
||||
@@ -2209,34 +2209,34 @@ pub fn navigation_controls(ptz: &PTZ, navigation_handler: &NavigationMessageHand
|
||||
.on_update(|_| NavigationMessage::CanvasTiltResetAndZoomTo100Percent.into())
|
||||
.disabled(ptz.tilt().abs() < 1e-4 && (ptz.zoom() - 1.).abs() < 1e-4)
|
||||
.widget_holder(),
|
||||
PopoverButton::new()
|
||||
.popover_layout(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new(format!("{tooltip_name} Navigation")).bold(true).widget_holder()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new({
|
||||
let tilt = if tooltip_name == "Canvas" { "Tilt:\n• Alt + Middle Click Drag\n\n" } else { "" };
|
||||
format!(
|
||||
"
|
||||
Interactive controls in this\n\
|
||||
menu are coming soon.\n\
|
||||
\n\
|
||||
Pan:\n\
|
||||
• Middle Click Drag\n\
|
||||
\n\
|
||||
{tilt}Zoom:\n\
|
||||
• Shift + Middle Click Drag\n\
|
||||
• Ctrl + Scroll Wheel Roll
|
||||
"
|
||||
)
|
||||
.trim()
|
||||
})
|
||||
.multiline(true)
|
||||
.widget_holder()],
|
||||
},
|
||||
])
|
||||
.widget_holder(),
|
||||
// PopoverButton::new()
|
||||
// .popover_layout(vec![
|
||||
// LayoutGroup::Row {
|
||||
// widgets: vec![TextLabel::new(format!("{tooltip_name} Navigation")).bold(true).widget_holder()],
|
||||
// },
|
||||
// LayoutGroup::Row {
|
||||
// widgets: vec![TextLabel::new({
|
||||
// let tilt = if tooltip_name == "Canvas" { "Tilt:\n• Alt + Middle Click Drag\n\n" } else { "" };
|
||||
// format!(
|
||||
// "
|
||||
// Interactive controls in this\n\
|
||||
// menu are coming soon.\n\
|
||||
// \n\
|
||||
// Pan:\n\
|
||||
// • Middle Click Drag\n\
|
||||
// \n\
|
||||
// {tilt}Zoom:\n\
|
||||
// • Shift + Middle Click Drag\n\
|
||||
// • Ctrl + Scroll Wheel Roll
|
||||
// "
|
||||
// )
|
||||
// .trim()
|
||||
// })
|
||||
// .multiline(true)
|
||||
// .widget_holder()],
|
||||
// },
|
||||
// ])
|
||||
// .widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
NumberInput::new(Some(navigation_handler.snapped_zoom(ptz.zoom()) * 100.))
|
||||
.unit("%")
|
||||
|
||||
@@ -2250,13 +2250,17 @@ impl NodeGraphMessageHandler {
|
||||
.map(|layer| layer.to_node())
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
let mut selected_parents = HashSet::new();
|
||||
let mut ancestors_of_selected = HashSet::new();
|
||||
let mut descendants_of_selected = HashSet::new();
|
||||
for selected_layer in &selected_layers {
|
||||
for ancestor in LayerNodeIdentifier::new(*selected_layer, network_interface, &[]).ancestors(network_interface.document_metadata()) {
|
||||
if ancestor != LayerNodeIdentifier::ROOT_PARENT && !selected_layers.contains(&ancestor.to_node()) {
|
||||
selected_parents.insert(ancestor.to_node());
|
||||
if ancestor != LayerNodeIdentifier::ROOT_PARENT && ancestor.to_node() != *selected_layer {
|
||||
ancestors_of_selected.insert(ancestor.to_node());
|
||||
}
|
||||
}
|
||||
for descendant in LayerNodeIdentifier::new(*selected_layer, network_interface, &[]).descendants(network_interface.document_metadata()) {
|
||||
descendants_of_selected.insert(descendant.to_node());
|
||||
}
|
||||
}
|
||||
|
||||
for (&node_id, node_metadata) in &network_interface.network_metadata(&[]).unwrap().persistent_metadata.node_metadata {
|
||||
@@ -2294,26 +2298,25 @@ impl NodeGraphMessageHandler {
|
||||
}
|
||||
});
|
||||
|
||||
let is_selected_parent = selected_parents.contains(&node_id);
|
||||
|
||||
let data = LayerPanelEntry {
|
||||
id: node_id,
|
||||
alias: network_interface.frontend_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()),
|
||||
expanded: layer.has_children(network_interface.document_metadata()) && !collapsed.0.contains(&layer),
|
||||
depth: layer.ancestors(network_interface.document_metadata()).count() - 1,
|
||||
parent_id: layer
|
||||
.parent(network_interface.document_metadata())
|
||||
.and_then(|parent| if parent != LayerNodeIdentifier::ROOT_PARENT { Some(parent.to_node()) } else { None }),
|
||||
alias: network_interface.frontend_display_name(&node_id, &[]),
|
||||
tooltip: if cfg!(debug_assertions) { format!("Layer ID: {node_id}") } else { "".into() },
|
||||
visible: network_interface.is_visible(&node_id, &[]),
|
||||
parents_visible,
|
||||
unlocked: !network_interface.is_locked(&node_id, &[]),
|
||||
parents_unlocked,
|
||||
selected: selected_layers.contains(&node_id) || is_selected_parent,
|
||||
in_selected_network: selection_network_path.is_empty(),
|
||||
selected_parent: is_selected_parent,
|
||||
parent_id: layer
|
||||
.parent(network_interface.document_metadata())
|
||||
.and_then(|parent| if parent != LayerNodeIdentifier::ROOT_PARENT { Some(parent.to_node()) } else { None }),
|
||||
selected: selected_layers.contains(&node_id),
|
||||
ancestor_of_selected: ancestors_of_selected.contains(&node_id),
|
||||
descendant_of_selected: descendants_of_selected.contains(&node_id),
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateDocumentLayerDetails { data });
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ pub struct LayerPanelEntry {
|
||||
pub id: NodeId,
|
||||
pub alias: String,
|
||||
pub tooltip: String,
|
||||
#[serde(rename = "inSelectedNetwork")]
|
||||
pub in_selected_network: bool,
|
||||
#[serde(rename = "childrenAllowed")]
|
||||
pub children_allowed: bool,
|
||||
#[serde(rename = "childrenPresent")]
|
||||
@@ -51,10 +53,10 @@ pub struct LayerPanelEntry {
|
||||
#[serde(rename = "parentId")]
|
||||
pub parent_id: Option<NodeId>,
|
||||
pub selected: bool,
|
||||
#[serde(rename = "inSelectedNetwork")]
|
||||
pub in_selected_network: bool,
|
||||
#[serde(rename = "selectedParent")]
|
||||
pub selected_parent: bool,
|
||||
#[serde(rename = "ancestorOfSelected")]
|
||||
pub ancestor_of_selected: bool,
|
||||
#[serde(rename = "descendantOfSelected")]
|
||||
pub descendant_of_selected: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize, PartialEq, Eq, specta::Type)]
|
||||
|
||||
@@ -176,19 +176,19 @@ impl LayoutHolder for SelectTool {
|
||||
let disabled = self.tool_data.selected_layers_count < 2;
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
widgets.extend(self.alignment_widgets(disabled));
|
||||
widgets.push(
|
||||
PopoverButton::new()
|
||||
.popover_layout(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Align").bold(true).widget_holder()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Coming soon").widget_holder()],
|
||||
},
|
||||
])
|
||||
.disabled(disabled)
|
||||
.widget_holder(),
|
||||
);
|
||||
// widgets.push(
|
||||
// PopoverButton::new()
|
||||
// .popover_layout(vec![
|
||||
// LayoutGroup::Row {
|
||||
// widgets: vec![TextLabel::new("Align").bold(true).widget_holder()],
|
||||
// },
|
||||
// LayoutGroup::Row {
|
||||
// widgets: vec![TextLabel::new("Coming soon").widget_holder()],
|
||||
// },
|
||||
// ])
|
||||
// .disabled(disabled)
|
||||
// .widget_holder(),
|
||||
// );
|
||||
|
||||
// Flip
|
||||
let disabled = self.tool_data.selected_layers_count == 0;
|
||||
|
||||
@@ -250,14 +250,13 @@ impl LayoutHolder for ToolData {
|
||||
.iter()
|
||||
.map(|tool_group| tool_group.iter().map(|tool_availability| {
|
||||
match tool_availability {
|
||||
ToolAvailability::Available(tool) => ToolEntry::new( tool.tool_type(), tool.icon_name())
|
||||
.tooltip( tool.tooltip())
|
||||
.tooltip_shortcut(action_keys!(tool_type_to_activate_tool_message(tool.tool_type())))
|
||||
|
||||
,
|
||||
ToolAvailability::Available(tool) => ToolEntry::new(tool.tool_type(), tool.icon_name())
|
||||
.tooltip(tool.tooltip())
|
||||
.tooltip_shortcut(action_keys!(tool_type_to_activate_tool_message(tool.tool_type()))),
|
||||
ToolAvailability::ComingSoon(tool) => tool.clone(),
|
||||
}
|
||||
}).collect::<Vec<_>>())
|
||||
})
|
||||
.collect::<Vec<_>>())
|
||||
.flat_map(|group| {
|
||||
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 }| {
|
||||
@@ -397,16 +396,14 @@ fn list_tools_in_groups() -> Vec<Vec<ToolAvailability>> {
|
||||
],
|
||||
vec![
|
||||
// Raster tool group
|
||||
// ToolAvailability::Available(Box::<imaginate_tool::ImaginateTool>::default()), // TODO: Fix and reenable ASAP
|
||||
ToolAvailability::ComingSoon(
|
||||
ToolEntry::new(ToolType::Heal, "RasterImaginateTool").tooltip("Coming Soon: Imaginate Tool - Temporarily disabled, please use Imaginate node directly from graph"),
|
||||
),
|
||||
ToolAvailability::Available(Box::<brush_tool::BrushTool>::default()),
|
||||
ToolAvailability::ComingSoon(ToolEntry::new(ToolType::Heal, "RasterHealTool").tooltip("Coming Soon: Heal Tool (J)")),
|
||||
ToolAvailability::ComingSoon(ToolEntry::new(ToolType::Clone, "RasterCloneTool").tooltip("Coming Soon: Clone Tool (C)")),
|
||||
ToolAvailability::ComingSoon(ToolEntry::new(ToolType::Patch, "RasterPatchTool").tooltip("Coming Soon: Patch Tool")),
|
||||
ToolAvailability::ComingSoon(ToolEntry::new(ToolType::Detail, "RasterDetailTool").tooltip("Coming Soon: Detail Tool (D)")),
|
||||
ToolAvailability::ComingSoon(ToolEntry::new(ToolType::Relight, "RasterRelightTool").tooltip("Coming Soon: Relight Tool (O)")),
|
||||
// ToolAvailability::Available(Box::<imaginate_tool::ImaginateTool>::default()), // TODO: Fix and reenable
|
||||
ToolAvailability::ComingSoon(ToolEntry::new(ToolType::Heal, "RasterImaginateTool").tooltip("Coming Soon: Imaginate Tool")),
|
||||
],
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user