Skip to content

Commit df87bc6

Browse files
authored
Merge branch 'master' into segment_edit_followup
2 parents d71bb46 + 112efe8 commit df87bc6

16 files changed

Lines changed: 587 additions & 178 deletions

File tree

editor/src/messages/layout/layout_message_handler.rs

Lines changed: 80 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@ impl LayoutMessageHandler {
123123
let callback_message = match action {
124124
WidgetValueAction::Commit => (breadcrumb_trail_buttons.on_commit.callback)(&()),
125125
WidgetValueAction::Update => {
126-
let update_value = value.as_u64().expect("BreadcrumbTrailButtons update was not of type: u64");
126+
let Some(update_value) = value.as_u64() else {
127+
error!("BreadcrumbTrailButtons update was not of type: u64");
128+
return;
129+
};
127130
(breadcrumb_trail_buttons.on_update.callback)(&update_value)
128131
}
129132
};
@@ -133,7 +136,10 @@ impl LayoutMessageHandler {
133136
let callback_message = match action {
134137
WidgetValueAction::Commit => (checkbox_input.on_commit.callback)(&()),
135138
WidgetValueAction::Update => {
136-
let update_value = value.as_bool().expect("CheckboxInput update was not of type: bool");
139+
let Some(update_value) = value.as_bool() else {
140+
error!("CheckboxInput update was not of type: bool");
141+
return;
142+
};
137143
checkbox_input.checked = update_value;
138144
(checkbox_input.on_update.callback)(checkbox_input)
139145
}
@@ -208,7 +214,10 @@ impl LayoutMessageHandler {
208214
let callback_message = match action {
209215
WidgetValueAction::Commit => (curve_input.on_commit.callback)(&()),
210216
WidgetValueAction::Update => {
211-
let curve = serde_json::from_value(value).expect("CurveInput event data could not be deserialized");
217+
let Some(curve) = serde_json::from_value(value).ok() else {
218+
error!("CurveInput event data could not be deserialized");
219+
return;
220+
};
212221
curve_input.value = curve;
213222
(curve_input.on_update.callback)(curve_input)
214223
}
@@ -219,13 +228,27 @@ impl LayoutMessageHandler {
219228
Widget::DropdownInput(dropdown_input) => {
220229
let callback_message = match action {
221230
WidgetValueAction::Commit => {
222-
let update_value = value.as_u64().unwrap_or_else(|| panic!("DropdownInput commit was not of type `u64`, found {value:?}"));
223-
(dropdown_input.entries.iter().flatten().nth(update_value as usize).unwrap().on_commit.callback)(&())
231+
let Some(update_value) = value.as_u64() else {
232+
error!("DropdownInput commit was not of type `u64`, found {value:?}");
233+
return;
234+
};
235+
let Some(entry) = dropdown_input.entries.iter().flatten().nth(update_value as usize) else {
236+
error!("DropdownInput commit was not able to find entry for index {update_value}");
237+
return;
238+
};
239+
(entry.on_commit.callback)(&())
224240
}
225241
WidgetValueAction::Update => {
226-
let update_value = value.as_u64().unwrap_or_else(|| panic!("DropdownInput update was not of type `u64`, found {value:?}"));
242+
let Some(update_value) = value.as_u64() else {
243+
error!("DropdownInput update was not of type `u64`, found {value:?}");
244+
return;
245+
};
227246
dropdown_input.selected_index = Some(update_value as u32);
228-
(dropdown_input.entries.iter().flatten().nth(update_value as usize).unwrap().on_update.callback)(&())
247+
let Some(entry) = dropdown_input.entries.iter().flatten().nth(update_value as usize) else {
248+
error!("DropdownInput update was not able to find entry for index {update_value}");
249+
return;
250+
};
251+
(entry.on_update.callback)(&())
229252
}
230253
};
231254

@@ -235,12 +258,27 @@ impl LayoutMessageHandler {
235258
let callback_message = match action {
236259
WidgetValueAction::Commit => (font_input.on_commit.callback)(&()),
237260
WidgetValueAction::Update => {
238-
let update_value = value.as_object().expect("FontInput update was not of type: object");
239-
let font_family_value = update_value.get("fontFamily").expect("FontInput update does not have a fontFamily");
240-
let font_style_value = update_value.get("fontStyle").expect("FontInput update does not have a fontStyle");
261+
let Some(update_value) = value.as_object() else {
262+
error!("FontInput update was not of type: object");
263+
return;
264+
};
265+
let Some(font_family_value) = update_value.get("fontFamily") else {
266+
error!("FontInput update does not have a fontFamily");
267+
return;
268+
};
269+
let Some(font_style_value) = update_value.get("fontStyle") else {
270+
error!("FontInput update does not have a fontStyle");
271+
return;
272+
};
241273

242-
let font_family = font_family_value.as_str().expect("FontInput update fontFamily was not of type: string");
243-
let font_style = font_style_value.as_str().expect("FontInput update fontStyle was not of type: string");
274+
let Some(font_family) = font_family_value.as_str() else {
275+
error!("FontInput update fontFamily was not of type: string");
276+
return;
277+
};
278+
let Some(font_style) = font_style_value.as_str() else {
279+
error!("FontInput update fontStyle was not of type: string");
280+
return;
281+
};
244282

245283
font_input.font_family = font_family.into();
246284
font_input.font_style = font_style.into();
@@ -285,7 +323,10 @@ impl LayoutMessageHandler {
285323
responses.add(callback_message);
286324
}
287325
WidgetValueAction::Update => {
288-
let value = value.as_str().expect("NodeCatalog update was not of type String").to_string();
326+
let Some(value) = value.as_str().map(|s| s.to_string()) else {
327+
error!("NodeCatalog update was not of type String");
328+
return;
329+
};
289330
let callback_message = (node_type_input.on_update.callback)(&value);
290331
responses.add(callback_message);
291332
}
@@ -296,8 +337,11 @@ impl LayoutMessageHandler {
296337
responses.add(callback_message);
297338
}
298339
WidgetValueAction::Update => match value {
299-
Value::Number(num) => {
300-
let update_value = num.as_f64().unwrap();
340+
Value::Number(ref num) => {
341+
let Some(update_value) = num.as_f64() else {
342+
error!("NumberInput update was not of type: f64, found {value:?}");
343+
return;
344+
};
301345
number_input.value = Some(update_value);
302346
let callback_message = (number_input.on_update.callback)(number_input);
303347
responses.add(callback_message);
@@ -323,7 +367,10 @@ impl LayoutMessageHandler {
323367
let callback_message = match action {
324368
WidgetValueAction::Commit => (reference_point_input.on_commit.callback)(&()),
325369
WidgetValueAction::Update => {
326-
let update_value = value.as_str().expect("ReferencePointInput update was not of type: u64");
370+
let Some(update_value) = value.as_str() else {
371+
error!("ReferencePointInput update was not of type: u64");
372+
return;
373+
};
327374
reference_point_input.value = update_value.into();
328375
(reference_point_input.on_update.callback)(reference_point_input)
329376
}
@@ -333,7 +380,10 @@ impl LayoutMessageHandler {
333380
}
334381
Widget::PopoverButton(_) => {}
335382
Widget::RadioInput(radio_input) => {
336-
let update_value = value.as_u64().expect("RadioInput update was not of type: u64");
383+
let Some(update_value) = value.as_u64() else {
384+
error!("RadioInput update was not of type: u64");
385+
return;
386+
};
337387
radio_input.selected_index = Some(update_value as u32);
338388
let callback_message = match action {
339389
WidgetValueAction::Commit => (radio_input.entries[update_value as usize].on_commit.callback)(&()),
@@ -347,7 +397,10 @@ impl LayoutMessageHandler {
347397
let callback_message = match action {
348398
WidgetValueAction::Commit => (text_area_input.on_commit.callback)(&()),
349399
WidgetValueAction::Update => {
350-
let update_value = value.as_str().expect("TextAreaInput update was not of type: string");
400+
let Some(update_value) = value.as_str() else {
401+
error!("TextAreaInput update was not of type: string");
402+
return;
403+
};
351404
text_area_input.value = update_value.into();
352405
(text_area_input.on_update.callback)(text_area_input)
353406
}
@@ -367,7 +420,10 @@ impl LayoutMessageHandler {
367420
let callback_message = match action {
368421
WidgetValueAction::Commit => (text_input.on_commit.callback)(&()),
369422
WidgetValueAction::Update => {
370-
let update_value = value.as_str().expect("TextInput update was not of type: string");
423+
let Some(update_value) = value.as_str() else {
424+
error!("TextInput update was not of type: string");
425+
return;
426+
};
371427
text_input.value = update_value.into();
372428
(text_input.on_update.callback)(text_input)
373429
}
@@ -411,10 +467,11 @@ impl LayoutMessageHandler {
411467
self.layouts[layout_target as usize] = new_layout;
412468

413469
// Update the UI
414-
responses.add(FrontendMessage::UpdateMenuBarLayout {
415-
layout_target,
416-
layout: self.layouts[layout_target as usize].clone().unwrap_menu_layout(action_input_mapping).layout,
417-
});
470+
let Some(layout) = self.layouts[layout_target as usize].clone().as_menu_layout(action_input_mapping).map(|x| x.layout) else {
471+
error!("Called unwrap_menu_layout on a widget layout");
472+
return;
473+
};
474+
responses.add(FrontendMessage::UpdateMenuBarLayout { layout_target, layout });
418475
}
419476
}
420477
}

editor/src/messages/layout/utility_types/layout_widget.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,14 @@ pub enum Layout {
109109
}
110110

111111
impl Layout {
112-
pub fn unwrap_menu_layout(self, action_input_mapping: &impl Fn(&MessageDiscriminant) -> Option<KeysGroup>) -> MenuLayout {
112+
pub fn as_menu_layout(self, action_input_mapping: &impl Fn(&MessageDiscriminant) -> Option<KeysGroup>) -> Option<MenuLayout> {
113113
if let Self::MenuLayout(mut menu) = self {
114114
menu.layout
115115
.iter_mut()
116116
.for_each(|menu_column| menu_column.children.fill_in_shortcut_actions_with_keys(action_input_mapping));
117-
menu
117+
Some(menu)
118118
} else {
119-
panic!("Called unwrap_menu_layout on a widget layout");
119+
None
120120
}
121121
}
122122

editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
12221222
NodeInput::value(TaggedValue::OptionalF64(TypesettingConfig::default().max_width), false),
12231223
NodeInput::value(TaggedValue::OptionalF64(TypesettingConfig::default().max_height), false),
12241224
NodeInput::value(TaggedValue::F64(TypesettingConfig::default().tilt), false),
1225+
NodeInput::value(TaggedValue::Bool(false), false),
12251226
],
12261227
..Default::default()
12271228
},
@@ -1281,14 +1282,15 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
12811282
),
12821283
InputMetadata::with_name_description_override(
12831284
"Tilt",
1284-
"Faux italic",
1285+
"Faux italic.",
12851286
WidgetOverride::Number(NumberInputSettings {
12861287
min: Some(-85.),
12871288
max: Some(85.),
12881289
unit: Some("°".to_string()),
12891290
..Default::default()
12901291
}),
12911292
),
1293+
("Per-Glyph Instances", "Splits each text glyph into its own instance, i.e. row in the table of vector data.").into(),
12921294
],
12931295
output_names: vec!["Vector".to_string()],
12941296
..Default::default()

editor/src/messages/portfolio/document_migration.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
635635
}
636636

637637
// Upgrade Text node to include line height and character spacing, which were previously hardcoded to 1, from https://github.com/GraphiteEditor/Graphite/pull/2016
638-
if reference == "Text" && inputs_count != 9 {
638+
if reference == "Text" && inputs_count != 10 {
639639
let mut template = resolve_document_node_type(reference)?.default_node_template();
640640
document.network_interface.replace_implementation(node_id, network_path, &mut template);
641641
let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut template)?;
@@ -689,6 +689,15 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
689689
},
690690
network_path,
691691
);
692+
document.network_interface.set_input(
693+
&InputConnector::node(*node_id, 9),
694+
if inputs_count >= 10 {
695+
old_inputs[9].clone()
696+
} else {
697+
NodeInput::value(TaggedValue::Bool(false), false)
698+
},
699+
network_path,
700+
);
692701
}
693702

694703
// Upgrade Sine, Cosine, and Tangent nodes to include a boolean input for whether the output should be in radians, which was previously the only option but is now not the default
@@ -960,6 +969,19 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
960969
}
961970
}
962971

972+
// Add the "Depth" parameter to the "Instance Index" node
973+
if reference == "Instance Index" && inputs_count == 0 {
974+
let mut node_template = resolve_document_node_type(reference)?.default_node_template();
975+
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
976+
977+
document.network_interface.add_import(TaggedValue::None, false, 0, "Primary", "", &[*node_id]);
978+
document.network_interface.add_import(TaggedValue::U32(0), false, 1, "Loop Level", "TODO", &[*node_id]);
979+
}
980+
981+
// ==================================
982+
// PUT ALL MIGRATIONS ABOVE THIS LINE
983+
// ==================================
984+
963985
// Ensure layers are positioned as stacks if they are upstream siblings of another layer
964986
document.network_interface.load_structure();
965987
let all_layers = LayerNodeIdentifier::ROOT_PARENT.descendants(document.network_interface.document_metadata()).collect::<Vec<_>>();

editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::consts::{ANGLE_MEASURE_RADIUS_FACTOR, ARC_MEASURE_RADIUS_FACTOR_RANGE, COLOR_OVERLAY_BLUE, COLOR_OVERLAY_GRAY_25, SLOWING_DIVISOR};
1+
use crate::consts::{ANGLE_MEASURE_RADIUS_FACTOR, ARC_MEASURE_RADIUS_FACTOR_RANGE, COLOR_OVERLAY_BLUE, COLOR_OVERLAY_GRAY, SLOWING_DIVISOR};
22
use crate::messages::input_mapper::utility_types::input_mouse::{DocumentPosition, ViewportPosition};
33
use crate::messages::portfolio::document::overlays::utility_types::{OverlayProvider, Pivot};
44
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
@@ -177,7 +177,7 @@ impl MessageHandler<TransformLayerMessage, TransformLayerMessageContext<'_>> for
177177

178178
if using_path_tool {
179179
for (outline, transform) in &self.ghost_outline {
180-
overlay_context.outline(outline.iter(), *transform, Some(COLOR_OVERLAY_GRAY_25));
180+
overlay_context.outline(outline.iter(), *transform, Some(COLOR_OVERLAY_GRAY));
181181
}
182182
}
183183

@@ -407,6 +407,10 @@ impl MessageHandler<TransformLayerMessage, TransformLayerMessageContext<'_>> for
407407
TransformLayerMessage::BeginRotate => responses.add_front(TransformLayerMessage::BeginGRS { operation: TransformType::Rotate }),
408408
TransformLayerMessage::BeginScale => responses.add_front(TransformLayerMessage::BeginGRS { operation: TransformType::Scale }),
409409
TransformLayerMessage::CancelTransformOperation => {
410+
if using_path_tool {
411+
self.ghost_outline.clear();
412+
}
413+
410414
if using_pen_tool {
411415
self.typing.clear();
412416

@@ -416,8 +420,6 @@ impl MessageHandler<TransformLayerMessage, TransformLayerMessageContext<'_>> for
416420

417421
responses.add(PenToolMessage::Abort);
418422
responses.add(ToolMessage::UpdateHints);
419-
} else if using_path_tool {
420-
self.ghost_outline.clear();
421423
} else {
422424
selected.original_transforms.clear();
423425
self.typing.clear();

0 commit comments

Comments
 (0)