mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 02:48:12 +08:00
Color Input (#565)
* initial working prototype * clean up component * Fix alignment * Code review tweaks Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
@@ -2,7 +2,7 @@ use super::layer_panel::LayerDataTypeDiscriminant;
|
||||
use crate::document::properties_panel_message::TransformOp;
|
||||
use crate::layout::layout_message::LayoutTarget;
|
||||
use crate::layout::widgets::{
|
||||
IconLabel, LayoutRow, NumberInput, PopoverButton, Separator, SeparatorDirection, SeparatorType, TextInput, TextLabel, Widget, WidgetCallback, WidgetHolder, WidgetLayout,
|
||||
ColorInput, IconLabel, LayoutRow, NumberInput, PopoverButton, Separator, SeparatorDirection, SeparatorType, TextInput, TextLabel, Widget, WidgetCallback, WidgetHolder, WidgetLayout,
|
||||
};
|
||||
use crate::message_prelude::*;
|
||||
|
||||
@@ -424,9 +424,9 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutRow> {
|
||||
separator_type: SeparatorType::Related,
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::TextInput(TextInput {
|
||||
WidgetHolder::new(Widget::ColorInput(ColorInput {
|
||||
value: color.rgba_hex(),
|
||||
on_update: WidgetCallback::new(|text_input: &TextInput| {
|
||||
on_update: WidgetCallback::new(|text_input: &ColorInput| {
|
||||
if let Some(color) = Color::from_rgba_str(&text_input.value).or(Color::from_rgb_str(&text_input.value)) {
|
||||
let new_fill = Fill::Solid(color);
|
||||
PropertiesPanelMessage::ModifyFill { fill: new_fill }.into()
|
||||
@@ -455,9 +455,9 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutRow> {
|
||||
separator_type: SeparatorType::Related,
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::TextInput(TextInput {
|
||||
WidgetHolder::new(Widget::ColorInput(ColorInput {
|
||||
value: gradient_1.positions[0].1.rgba_hex(),
|
||||
on_update: WidgetCallback::new(move |text_input: &TextInput| {
|
||||
on_update: WidgetCallback::new(move |text_input: &ColorInput| {
|
||||
if let Some(color) = Color::from_rgba_str(&text_input.value).or(Color::from_rgb_str(&text_input.value)) {
|
||||
let mut new_gradient = (*gradient_1).clone();
|
||||
new_gradient.positions[0].1 = color;
|
||||
@@ -483,9 +483,9 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutRow> {
|
||||
separator_type: SeparatorType::Related,
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::TextInput(TextInput {
|
||||
WidgetHolder::new(Widget::ColorInput(ColorInput {
|
||||
value: gradient_2.positions[1].1.rgba_hex(),
|
||||
on_update: WidgetCallback::new(move |text_input: &TextInput| {
|
||||
on_update: WidgetCallback::new(move |text_input: &ColorInput| {
|
||||
if let Some(color) = Color::from_rgba_str(&text_input.value).or(Color::from_rgb_str(&text_input.value)) {
|
||||
let mut new_gradient = (*gradient_2).clone();
|
||||
new_gradient.positions[1].1 = color;
|
||||
@@ -524,9 +524,9 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
|
||||
separator_type: SeparatorType::Related,
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::TextInput(TextInput {
|
||||
WidgetHolder::new(Widget::ColorInput(ColorInput {
|
||||
value: stroke.color().rgba_hex(),
|
||||
on_update: WidgetCallback::new(move |text_input: &TextInput| {
|
||||
on_update: WidgetCallback::new(move |text_input: &ColorInput| {
|
||||
PropertiesPanelMessage::ModifyStroke {
|
||||
color: text_input.value.clone(),
|
||||
weight: weight as f64,
|
||||
|
||||
@@ -80,17 +80,23 @@ impl MessageHandler<LayoutMessage, ()> for LayoutMessageHandler {
|
||||
responses.push_back(callback_message);
|
||||
}
|
||||
Widget::RadioInput(radio_input) => {
|
||||
let update_value = value.as_u64().expect("OptionalInput update was not of type: u64");
|
||||
let update_value = value.as_u64().expect("RadioInput update was not of type: u64");
|
||||
radio_input.selected_index = update_value as u32;
|
||||
let callback_message = (radio_input.entries[update_value as usize].on_update.callback)(&());
|
||||
responses.push_back(callback_message);
|
||||
}
|
||||
Widget::TextInput(text_input) => {
|
||||
let update_value = value.as_str().expect("OptionalInput update was not of type: string");
|
||||
let update_value = value.as_str().expect("TextInput update was not of type: string");
|
||||
text_input.value = update_value.into();
|
||||
let callback_message = (text_input.on_update.callback)(text_input);
|
||||
responses.push_back(callback_message);
|
||||
}
|
||||
Widget::ColorInput(color_input) => {
|
||||
let update_value = value.as_str().expect("ColorInput update was not of type: string");
|
||||
color_input.value = update_value.into();
|
||||
let callback_message = (color_input.on_update.callback)(color_input);
|
||||
responses.push_back(callback_message);
|
||||
}
|
||||
Widget::TextLabel(_) => {}
|
||||
};
|
||||
self.send_layout(layout_target, responses);
|
||||
|
||||
@@ -150,6 +150,7 @@ impl<T> Default for WidgetCallback<T> {
|
||||
#[remain::sorted]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Widget {
|
||||
ColorInput(ColorInput),
|
||||
IconButton(IconButton),
|
||||
IconLabel(IconLabel),
|
||||
NumberInput(NumberInput),
|
||||
@@ -199,6 +200,15 @@ pub struct TextInput {
|
||||
pub on_update: WidgetCallback<TextInput>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Derivative)]
|
||||
#[derivative(Debug, PartialEq, Default)]
|
||||
pub struct ColorInput {
|
||||
pub value: String,
|
||||
#[serde(skip)]
|
||||
#[derivative(Debug = "ignore", PartialEq = "ignore")]
|
||||
pub on_update: WidgetCallback<ColorInput>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
|
||||
pub enum NumberInputIncrementBehavior {
|
||||
Add,
|
||||
|
||||
Reference in New Issue
Block a user