Repository: GraphiteEditor/Graphite
File: editor/src/messages/portfolio/document/node_graph/node_properties.rs (Rust)

Code before:
								let mut gradient = gradient.clone();
								std::mem::swap(&mut gradient.start, &mut gradient.end);
								TaggedValue::Fill(Fill::Gradient(gradient))
							}
						},
						node_id,
						FillInput::<Color>::INDEX,
					))
					.widget_instance();
				row.push(Separator::new(SeparatorStyle::Unrelated).widget_instance());
				row.push(reverse_radial_gradient_button);
			}
		}

		let gradient_for_closure = gradient.clone();

		let entries = [GradientType::Linear, GradientType::Radial]
			.iter()
			.map(|&grad_type| {
				let gradient = gradient_for_closure.clone();
				RadioEntryData::new(format!("{:?}", grad_type))
					.label(format!("{:?}", grad_type))
					.on_update(move |_| {
						let mut new_gradient = gradient.clone();
						new_gradient.gradient_type = grad_type;
						Message::Batched {
							messages: Box::new([
								NodeGraphMessage::SetInputValue {
									node_id,
									input_index: FillInput::<Color>::INDEX,
									value: TaggedValue::Fill(Fill::Gradient(new_gradient)),
								}
								.into(),
								GradientToolMessage::UpdateOptions {
									options: GradientOptionsUpdate::Type(grad_type),
								}
								.into(),
							]),
						}
					})
					.on_commit(commit_value)
			})
			.collect();

		row.extend_from_slice(&[
			Separator::new(SeparatorStyle::Unrelated).widget_instance(),
			RadioInput::new(entries).selected_index(Some(gradient.gradient_type as u32)).widget_instance(),
		]);

		widgets.push(LayoutGroup::Row { widgets: row });
	}

Review comment (performance):
This makes an un-idiomatic change where the call to the `on_update` function (which receives back a `Message`) is now inlined for the message creation, for the sake of creating two batched messages. You can and should still call `on_update` and use its return value as one of the two messages that are given to the array for the batched message return value.

Code after:
								let mut gradient = gradient.clone();
								std::mem::swap(&mut gradient.start, &mut gradient.end);
								TaggedValue::Fill(Fill::Gradient(gradient))
							}
						},
						node_id,
						FillInput::<Color>::INDEX,
					))
					.widget_instance();
				row.push(Separator::new(SeparatorStyle::Unrelated).widget_instance());
				row.push(reverse_radial_gradient_button);
			}
		}

		let gradient_for_closure = gradient.clone();

		let entries = [GradientType::Linear, GradientType::Radial]
			.iter()
			.map(|&grad_type| {
				let gradient = gradient_for_closure.clone();
				let set_input_value = update_value(
					move |_: &()| {
						let mut new_gradient = gradient.clone();
						new_gradient.gradient_type = grad_type;
						TaggedValue::Fill(Fill::Gradient(new_gradient))
					},
					node_id,
					FillInput::<Color>::INDEX,
				);
				RadioEntryData::new(format!("{:?}", grad_type))
					.label(format!("{:?}", grad_type))
					.on_update(move |_| Message::Batched {
						messages: Box::new([
							set_input_value(&()),
							GradientToolMessage::UpdateOptions {
								options: GradientOptionsUpdate::Type(grad_type),
							}
							.into(),
						]),
					})
					.on_commit(commit_value)
			})
			.collect();

		row.extend_from_slice(&[
			Separator::new(SeparatorStyle::Unrelated).widget_instance(),
			RadioInput::new(entries).selected_index(Some(gradient.gradient_type as u32)).widget_instance(),
		]);

		widgets.push(LayoutGroup::Row { widgets: row });
	}