mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 02:48:12 +08:00
Polish node graph frames and rename them for clarity (#1104)
* Polish layer panel UI and layer type icons/text * Assorted UI text and comment cleanup * Insert Transform node before Imaginate node via tool * Rename "Node Graph Frame" to Layer type and Frame tool * Rename "Node Graph Frame" to "Frame" tool * Update Node Graph Frame -> Frame tool icon * Fix lint warnings
This commit is contained in:
@@ -1941,7 +1941,7 @@ impl DocumentMessageHandler {
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::IconButton(IconButton {
|
||||
icon: "NodeFolder".into(),
|
||||
icon: "Folder".into(),
|
||||
tooltip: "New Folder".into(),
|
||||
tooltip_shortcut: action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder),
|
||||
size: 24,
|
||||
|
||||
@@ -115,7 +115,7 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
});
|
||||
}
|
||||
|
||||
fn transform_change(&mut self, transform: DAffine2, transform_in: TransformIn, parent_transform: DAffine2, bounds: LayerBounds) {
|
||||
fn transform_change(&mut self, transform: DAffine2, transform_in: TransformIn, parent_transform: DAffine2) {
|
||||
self.modify_inputs("Transform", |inputs| {
|
||||
let layer_transform = transform_utils::get_current_transform(inputs);
|
||||
let to = match transform_in {
|
||||
@@ -123,7 +123,6 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
TransformIn::Scope { scope } => scope * parent_transform,
|
||||
TransformIn::Viewport => parent_transform,
|
||||
};
|
||||
let pivot = DAffine2::from_translation(bounds.layerspace_pivot(transform_utils::get_current_normalized_pivot(inputs)));
|
||||
let transform = to.inverse() * transform * to * layer_transform;
|
||||
transform_utils::update_transform(inputs, transform);
|
||||
});
|
||||
@@ -217,9 +216,8 @@ impl MessageHandler<GraphOperationMessage, (&mut Document, &mut NodeGraphMessage
|
||||
|
||||
GraphOperationMessage::TransformChange { layer, transform, transform_in } => {
|
||||
let parent_transform = document.multiply_transforms(&layer[..layer.len() - 1]).unwrap_or_default();
|
||||
let bounds = LayerBounds::new(document, &layer);
|
||||
if let Some(mut modify_inputs) = ModifyInputsContext::new(&layer, document, node_graph, responses) {
|
||||
modify_inputs.transform_change(transform, transform_in, parent_transform, bounds);
|
||||
modify_inputs.transform_change(transform, transform_in, parent_transform);
|
||||
} else {
|
||||
let transform = transform.to_cols_array();
|
||||
responses.add(match transform_in {
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
pub use self::document_node_types::*;
|
||||
use crate::messages::input_mapper::utility_types::macros::action_keys;
|
||||
use crate::messages::layout::utility_types::layout_widget::{Layout, LayoutGroup, Widget, WidgetCallback, WidgetHolder, WidgetLayout};
|
||||
use crate::messages::layout::utility_types::widgets::button_widgets::{BreadcrumbTrailButtons, TextButton};
|
||||
use crate::messages::layout::utility_types::widgets::button_widgets::TextButton;
|
||||
use crate::messages::prelude::*;
|
||||
|
||||
use document_legacy::document::Document;
|
||||
use document_legacy::layers::layer_info::LayerDataTypeDiscriminant;
|
||||
use document_legacy::layers::nodegraph_layer::NodeGraphFrameLayer;
|
||||
use document_legacy::LayerId;
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
@@ -148,34 +147,34 @@ impl NodeGraphMessageHandler {
|
||||
}
|
||||
|
||||
/// Collect the addresses of the currently viewed nested node e.g. Root -> MyFunFilter -> Exposure
|
||||
fn collect_nested_addresses(&mut self, document: &Document, responses: &mut VecDeque<Message>) {
|
||||
// Build path list
|
||||
let mut path = vec!["Root".to_string()];
|
||||
let mut network = self.get_root_network(document);
|
||||
for node_id in &self.nested_path {
|
||||
let node = network.and_then(|network| network.nodes.get(node_id));
|
||||
if let Some(DocumentNode { name, .. }) = node {
|
||||
path.push(name.clone());
|
||||
}
|
||||
network = node.and_then(|node| node.implementation.get_network());
|
||||
}
|
||||
let nesting = path.len();
|
||||
fn collect_nested_addresses(&mut self, _document: &Document, _responses: &mut VecDeque<Message>) {
|
||||
// // Build path list
|
||||
// let mut path = vec!["Root".to_string()];
|
||||
// let mut network = self.get_root_network(document);
|
||||
// for node_id in &self.nested_path {
|
||||
// let node = network.and_then(|network| network.nodes.get(node_id));
|
||||
// if let Some(DocumentNode { name, .. }) = node {
|
||||
// path.push(name.clone());
|
||||
// }
|
||||
// network = node.and_then(|node| node.implementation.get_network());
|
||||
// }
|
||||
// let nesting = path.len();
|
||||
|
||||
// Update UI
|
||||
self.widgets[0] = LayoutGroup::Row {
|
||||
widgets: vec![WidgetHolder::new(Widget::BreadcrumbTrailButtons(BreadcrumbTrailButtons {
|
||||
labels: path.clone(),
|
||||
on_update: WidgetCallback::new(move |input: &u64| {
|
||||
NodeGraphMessage::ExitNestedNetwork {
|
||||
depth_of_nesting: nesting - (*input as usize) - 1,
|
||||
}
|
||||
.into()
|
||||
}),
|
||||
..Default::default()
|
||||
}))],
|
||||
};
|
||||
// // Update UI
|
||||
// self.widgets[0] = LayoutGroup::Row {
|
||||
// widgets: vec![WidgetHolder::new(Widget::BreadcrumbTrailButtons(BreadcrumbTrailButtons {
|
||||
// labels: path.clone(),
|
||||
// on_update: WidgetCallback::new(move |input: &u64| {
|
||||
// NodeGraphMessage::ExitNestedNetwork {
|
||||
// depth_of_nesting: nesting - (*input as usize) - 1,
|
||||
// }
|
||||
// .into()
|
||||
// }),
|
||||
// ..Default::default()
|
||||
// }))],
|
||||
// };
|
||||
|
||||
self.send_node_bar_layout(responses);
|
||||
// self.send_node_bar_layout(responses);
|
||||
}
|
||||
|
||||
/// Updates the buttons for disable and preview
|
||||
@@ -405,7 +404,7 @@ impl NodeGraphMessageHandler {
|
||||
|
||||
impl MessageHandler<NodeGraphMessage, (&mut Document, &mut dyn Iterator<Item = &[LayerId]>)> for NodeGraphMessageHandler {
|
||||
#[remain::check]
|
||||
fn process_message(&mut self, message: NodeGraphMessage, responses: &mut VecDeque<Message>, (document, selected): (&mut Document, &mut dyn Iterator<Item = &[LayerId]>)) {
|
||||
fn process_message(&mut self, message: NodeGraphMessage, responses: &mut VecDeque<Message>, (document, _selected): (&mut Document, &mut dyn Iterator<Item = &[LayerId]>)) {
|
||||
#[remain::sorted]
|
||||
match message {
|
||||
NodeGraphMessage::CloseNodeGraph => {
|
||||
|
||||
@@ -141,7 +141,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
|
||||
properties: |_document_node, _node_id, _context| node_properties::string_properties("Downscale the image to a lower resolution"),
|
||||
},
|
||||
// DocumentNodeType {
|
||||
// name: "Input",
|
||||
// name: "Input Frame",
|
||||
// category: "Ignore",
|
||||
// identifier: NodeImplementation::proto("graphene_core::ops::IdNode"),
|
||||
// inputs: vec![DocumentInputType {
|
||||
@@ -153,7 +153,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
|
||||
// properties: node_properties::input_properties,
|
||||
// },
|
||||
DocumentNodeType {
|
||||
name: "Input",
|
||||
name: "Input Frame",
|
||||
category: "Ignore",
|
||||
identifier: NodeImplementation::DocumentNode(NodeNetwork {
|
||||
inputs: vec![0, 1],
|
||||
@@ -260,8 +260,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
|
||||
name: "Frame",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
}],
|
||||
|
||||
properties: |_document_node, _node_id, _context| node_properties::string_properties("The graph's output is rendered into the frame"),
|
||||
properties: |_document_node, _node_id, _context| node_properties::string_properties("The graph's output is drawn in the layer"),
|
||||
},
|
||||
DocumentNodeType {
|
||||
name: "Output",
|
||||
@@ -273,7 +272,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
|
||||
default: NodeInput::value(TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
}],
|
||||
outputs: vec![],
|
||||
properties: |_document_node, _node_id, _context| node_properties::string_properties("The graph's output is rendered into the frame"),
|
||||
properties: |_document_node, _node_id, _context| node_properties::string_properties("The graph's output is drawn in the layer"),
|
||||
},
|
||||
DocumentNodeType {
|
||||
name: "Image Frame",
|
||||
@@ -865,8 +864,8 @@ pub fn new_image_network(output_offset: i32, output_node_id: NodeId) -> NodeNetw
|
||||
inputs: vec![0],
|
||||
outputs: vec![NodeOutput::new(1, 0)],
|
||||
nodes: [
|
||||
resolve_document_node_type("Input")
|
||||
.expect("Input node does not exist")
|
||||
resolve_document_node_type("Input Frame")
|
||||
.expect("Input Frame node does not exist")
|
||||
.to_document_node_default_inputs([], DocumentNodeMetadata::position((8, 4))),
|
||||
resolve_document_node_type("Output")
|
||||
.expect("Output node does not exist")
|
||||
@@ -881,7 +880,7 @@ pub fn new_image_network(output_offset: i32, output_node_id: NodeId) -> NodeNetw
|
||||
}
|
||||
|
||||
pub fn new_vector_network(subpaths: Vec<bezier_rs::Subpath<uuid::ManipulatorGroupId>>) -> NodeNetwork {
|
||||
let input = resolve_document_node_type("Input").expect("Input node does not exist");
|
||||
let input = resolve_document_node_type("Input Frame").expect("Input Frame node does not exist");
|
||||
let path_generator = resolve_document_node_type("Path Generator").expect("Path Generator node does not exist");
|
||||
let transform = resolve_document_node_type("Transform").expect("Transform node does not exist");
|
||||
let fill = resolve_document_node_type("Fill").expect("Fill node does not exist");
|
||||
|
||||
@@ -421,10 +421,10 @@ fn color_widget(document_node: &DocumentNode, node_id: u64, index: usize, name:
|
||||
}
|
||||
/// Properties for the input node, with information describing how frames work and a refresh button
|
||||
pub fn input_properties(_document_node: &DocumentNode, _node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let information = WidgetHolder::text_widget("The graph's input is the artwork under the frame layer");
|
||||
let information = WidgetHolder::text_widget("The graph's input frame is the rasterized artwork under the layer");
|
||||
let layer_path = context.layer_path.to_vec();
|
||||
let refresh_button = TextButton::new("Refresh Input")
|
||||
.tooltip("Refresh the artwork under the frame")
|
||||
.tooltip("Refresh the artwork under the layer")
|
||||
.on_update(move |_| DocumentMessage::NodeGraphFrameGenerate { layer_path: layer_path.clone() }.into())
|
||||
.widget_holder();
|
||||
vec![LayoutGroup::Row { widgets: vec![information] }, LayoutGroup::Row { widgets: vec![refresh_button] }]
|
||||
@@ -936,8 +936,6 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
||||
LayoutGroup::Row { widgets }.with_tooltip("Seed determines the random outcome, enabling limitless unique variations")
|
||||
};
|
||||
|
||||
// Get the existing layer transform
|
||||
let transform = context.document.root.transform.inverse() * context.document.multiply_transforms(context.layer_path).unwrap();
|
||||
// Create the input to the graph using an empty image
|
||||
let image_frame = std::borrow::Cow::Owned(graphene_core::raster::ImageFrame {
|
||||
image: graphene_core::raster::Image::empty(),
|
||||
@@ -976,7 +974,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
||||
widgets.extend_from_slice(&[
|
||||
WidgetHolder::unrelated_separator(),
|
||||
IconButton::new("Rescale", 24)
|
||||
.tooltip("Set the Node Graph Frame layer dimensions to this resolution")
|
||||
.tooltip("Set the layer dimensions to this resolution")
|
||||
.on_update(move |_| {
|
||||
Operation::SetLayerScaleAroundPivot {
|
||||
path: layer_path.clone(),
|
||||
|
||||
@@ -77,7 +77,7 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
|
||||
tooltip: "Artboard".into(),
|
||||
..Default::default()
|
||||
})),
|
||||
WidgetHolder::related_separator(),
|
||||
WidgetHolder::unrelated_separator(),
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Artboard".into(),
|
||||
..TextLabel::default()
|
||||
@@ -256,7 +256,7 @@ pub fn register_artwork_layer_properties(
|
||||
widgets: vec![
|
||||
match &layer.data {
|
||||
LayerDataType::Folder(_) => WidgetHolder::new(Widget::IconLabel(IconLabel {
|
||||
icon: "NodeFolder".into(),
|
||||
icon: "Folder".into(),
|
||||
tooltip: "Folder".into(),
|
||||
..Default::default()
|
||||
})),
|
||||
@@ -271,15 +271,15 @@ pub fn register_artwork_layer_properties(
|
||||
..Default::default()
|
||||
})),
|
||||
LayerDataType::NodeGraphFrame(_) => WidgetHolder::new(Widget::IconLabel(IconLabel {
|
||||
icon: "NodeNodes".into(),
|
||||
tooltip: "Node Graph Frame".into(),
|
||||
icon: "Layer".into(),
|
||||
tooltip: "Layer".into(),
|
||||
..Default::default()
|
||||
})),
|
||||
},
|
||||
WidgetHolder::related_separator(),
|
||||
WidgetHolder::unrelated_separator(),
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: match &layer.data {
|
||||
LayerDataType::NodeGraphFrame(_) => "Node Graph Frame".into(),
|
||||
LayerDataType::NodeGraphFrame(_) => "Layer".into(),
|
||||
other => LayerDataTypeDiscriminant::from(other).to_string(),
|
||||
},
|
||||
..TextLabel::default()
|
||||
|
||||
@@ -35,12 +35,12 @@ pub use crate::messages::tool::tool_messages::artboard_tool::{ArtboardToolMessag
|
||||
pub use crate::messages::tool::tool_messages::ellipse_tool::{EllipseToolMessage, EllipseToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::eyedropper_tool::{EyedropperToolMessage, EyedropperToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::fill_tool::{FillToolMessage, FillToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::frame_tool::{NodeGraphFrameToolMessage, NodeGraphFrameToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::freehand_tool::{FreehandToolMessage, FreehandToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::gradient_tool::{GradientToolMessage, GradientToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::imaginate_tool::{ImaginateToolMessage, ImaginateToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::line_tool::{LineToolMessage, LineToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::navigate_tool::{NavigateToolMessage, NavigateToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::node_graph_frame_tool::{NodeGraphFrameToolMessage, NodeGraphFrameToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::path_tool::{PathToolMessage, PathToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::pen_tool::{PenToolMessage, PenToolMessageDiscriminant};
|
||||
pub use crate::messages::tool::tool_messages::rectangle_tool::{RectangleToolMessage, RectangleToolMessageDiscriminant};
|
||||
|
||||
@@ -11,8 +11,8 @@ use std::collections::VecDeque;
|
||||
/// Create a new vector layer from a vector of [`bezier_rs::Subpath`].
|
||||
pub fn new_vector_layer(subpaths: Vec<Subpath<ManipulatorGroupId>>, layer_path: Vec<LayerId>, responses: &mut VecDeque<Message>) {
|
||||
responses.push_back(DocumentMessage::DeselectAllLayers.into());
|
||||
let network = node_graph::new_vector_network(subpaths);
|
||||
|
||||
let network = node_graph::new_vector_network(subpaths);
|
||||
responses.push_back(
|
||||
Operation::AddNodeGraphFrame {
|
||||
path: layer_path.clone(),
|
||||
|
||||
@@ -60,10 +60,10 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for NodeGra
|
||||
|
||||
impl ToolMetadata for NodeGraphFrameTool {
|
||||
fn icon_name(&self) -> String {
|
||||
"RasterNodesTool".into()
|
||||
"RasterFrameTool".into()
|
||||
}
|
||||
fn tooltip(&self) -> String {
|
||||
"Node Graph Frame Tool".into()
|
||||
"Frame Tool".into()
|
||||
}
|
||||
fn tool_type(&self) -> crate::messages::tool::utility_types::ToolType {
|
||||
ToolType::NodeGraphFrame
|
||||
@@ -117,7 +117,7 @@ impl Fsm for NodeGraphToolFsmState {
|
||||
shape_data.path = Some(document.get_path_for_new_layer());
|
||||
responses.push_back(DocumentMessage::DeselectAllLayers.into());
|
||||
|
||||
let network = node_graph::new_image_network(20, 0);
|
||||
let network = node_graph::new_image_network(8, 0);
|
||||
|
||||
responses.push_back(
|
||||
Operation::AddNodeGraphFrame {
|
||||
@@ -119,18 +119,36 @@ impl Fsm for ImaginateToolFsmState {
|
||||
|
||||
use graph_craft::document::*;
|
||||
|
||||
// Utility function to offset the position of each consecutive node
|
||||
let mut pos = 8;
|
||||
let mut next_pos = || {
|
||||
pos += 8;
|
||||
graph_craft::document::DocumentNodeMetadata::position((pos, 4))
|
||||
};
|
||||
|
||||
// Get the node type for the Transform and Imaginate nodes
|
||||
let Some(transform_node_type) = crate::messages::portfolio::document::node_graph::resolve_document_node_type("Transform") else {
|
||||
warn!("Transform node should be in registry");
|
||||
return Drawing;
|
||||
};
|
||||
let imaginate_node_type = &*IMAGINATE_NODE;
|
||||
|
||||
let mut imaginate_inputs: Vec<NodeInput> = imaginate_node_type.inputs.iter().map(|input| input.default.clone()).collect();
|
||||
imaginate_inputs[0] = NodeInput::node(0, 0);
|
||||
// Give them a unique ID
|
||||
let [transform_node_id, imaginate_node_id] = [100, 101];
|
||||
|
||||
let imaginate_node_id = 100;
|
||||
// Create the network based on the Input -> Output passthrough default network
|
||||
let mut network = node_graph::new_image_network(16, imaginate_node_id);
|
||||
|
||||
// Insert the nodes into the default network
|
||||
network
|
||||
.nodes
|
||||
.insert(transform_node_id, transform_node_type.to_document_node_default_inputs([Some(NodeInput::node(0, 0))], next_pos()));
|
||||
network.nodes.insert(
|
||||
imaginate_node_id,
|
||||
imaginate_node_type.to_document_node(imaginate_inputs, graph_craft::document::DocumentNodeMetadata::position((16, 4))),
|
||||
imaginate_node_type.to_document_node_default_inputs([Some(graph_craft::document::NodeInput::node(transform_node_id, 0))], next_pos()),
|
||||
);
|
||||
|
||||
// Add the node graph frame layer to the document
|
||||
responses.push_back(
|
||||
Operation::AddNodeGraphFrame {
|
||||
path: shape_data.path.clone().unwrap(),
|
||||
@@ -140,6 +158,7 @@ impl Fsm for ImaginateToolFsmState {
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
responses.push_back(NodeGraphMessage::ShiftNode { node_id: imaginate_node_id }.into());
|
||||
|
||||
Drawing
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ pub mod artboard_tool;
|
||||
pub mod ellipse_tool;
|
||||
pub mod eyedropper_tool;
|
||||
pub mod fill_tool;
|
||||
pub mod frame_tool;
|
||||
pub mod freehand_tool;
|
||||
pub mod gradient_tool;
|
||||
pub mod imaginate_tool;
|
||||
pub mod line_tool;
|
||||
pub mod navigate_tool;
|
||||
pub mod node_graph_frame_tool;
|
||||
pub mod path_tool;
|
||||
pub mod pen_tool;
|
||||
pub mod rectangle_tool;
|
||||
|
||||
@@ -472,7 +472,7 @@ impl Fsm for SelectToolFsmState {
|
||||
if let Ok(intersect) = document.document_legacy.layer(intersect_layer_path) {
|
||||
match tool_data.nested_selection_behavior {
|
||||
NestedSelectionBehavior::Shallowest => edit_layer_shallowest_manipulation(document, intersect_layer_path, tool_data, responses),
|
||||
NestedSelectionBehavior::Deepest => edit_layer_deepest_manipulation(intersect, intersect_layer_path, responses),
|
||||
NestedSelectionBehavior::Deepest => edit_layer_deepest_manipulation(intersect, responses),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1201,7 +1201,7 @@ fn edit_layer_shallowest_manipulation(document: &DocumentMessageHandler, interse
|
||||
}
|
||||
}
|
||||
|
||||
fn edit_layer_deepest_manipulation(intersect: &Layer, intersect_layer_path: &Vec<u64>, responses: &mut VecDeque<Message>) {
|
||||
fn edit_layer_deepest_manipulation(intersect: &Layer, responses: &mut VecDeque<Message>) {
|
||||
match &intersect.data {
|
||||
LayerDataType::Text(_) => {
|
||||
responses.push_front(ToolMessage::ActivateTool { tool_type: ToolType::Text }.into());
|
||||
|
||||
@@ -408,7 +408,7 @@ fn list_tools_in_groups() -> Vec<Vec<ToolAvailability>> {
|
||||
],
|
||||
vec![
|
||||
// Raster tool group
|
||||
ToolAvailability::Available(Box::<node_graph_frame_tool::NodeGraphFrameTool>::default()),
|
||||
ToolAvailability::Available(Box::<frame_tool::NodeGraphFrameTool>::default()),
|
||||
ToolAvailability::Available(Box::<imaginate_tool::ImaginateTool>::default()),
|
||||
ToolAvailability::ComingSoon(ToolEntry {
|
||||
tool_type: ToolType::Brush,
|
||||
|
||||
@@ -7,7 +7,7 @@ pub struct WorkspaceMessageHandler {
|
||||
|
||||
impl MessageHandler<WorkspaceMessage, ()> for WorkspaceMessageHandler {
|
||||
#[remain::check]
|
||||
fn process_message(&mut self, message: WorkspaceMessage, responses: &mut VecDeque<Message>, _data: ()) {
|
||||
fn process_message(&mut self, message: WorkspaceMessage, _responses: &mut VecDeque<Message>, _data: ()) {
|
||||
use WorkspaceMessage::*;
|
||||
|
||||
#[remain::sorted]
|
||||
|
||||
Reference in New Issue
Block a user