mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 02:48:12 +08:00
Many subtle improvements to the UI design system (#1537)
This commit is contained in:
@@ -29,7 +29,7 @@ impl DialogLayoutHolder for AboutGraphiteDialog {
|
||||
.map(|(icon, label, url)| {
|
||||
TextButton::new(label)
|
||||
.icon(Some(icon.into()))
|
||||
.no_background(true)
|
||||
.flush(true)
|
||||
.on_update(|_| FrontendMessage::TriggerVisitLink { url: url.into() }.into())
|
||||
.widget_holder()
|
||||
})
|
||||
@@ -40,7 +40,7 @@ impl DialogLayoutHolder for AboutGraphiteDialog {
|
||||
widgets.push(
|
||||
TextButton::new("Licenses")
|
||||
.icon(Some("License".into()))
|
||||
.no_background(true)
|
||||
.flush(true)
|
||||
.on_update(move |_| {
|
||||
DialogMessage::RequestLicensesDialogWithLocalizedCommitDate {
|
||||
localized_commit_year: localized_commit_year.clone(),
|
||||
|
||||
@@ -28,7 +28,7 @@ impl LayoutHolder for ComingSoonDialog {
|
||||
let row2 = vec![TextLabel::new("But you can help build it! Visit its issue:").widget_holder()];
|
||||
let row3 = vec![TextButton::new(format!("GitHub Issue #{issue}"))
|
||||
.icon(Some("Website".into()))
|
||||
.no_background(true)
|
||||
.flush(true)
|
||||
.on_update(move |_| {
|
||||
FrontendMessage::TriggerVisitLink {
|
||||
url: format!("https://github.com/GraphiteEditor/Graphite/issues/{issue}"),
|
||||
|
||||
@@ -28,7 +28,7 @@ impl DialogLayoutHolder for LicensesDialog {
|
||||
.map(|(icon, label, url)| {
|
||||
TextButton::new(label)
|
||||
.icon(Some(icon.into()))
|
||||
.no_background(true)
|
||||
.flush(true)
|
||||
.on_update(|_| FrontendMessage::TriggerVisitLink { url: url.into() }.into())
|
||||
.widget_holder()
|
||||
})
|
||||
|
||||
@@ -173,11 +173,6 @@ pub enum FrontendMessage {
|
||||
#[serde(rename = "setColorChoice")]
|
||||
set_color_choice: Option<String>,
|
||||
},
|
||||
UpdateGraphViewOverlayButtonLayout {
|
||||
#[serde(rename = "layoutTarget")]
|
||||
layout_target: LayoutTarget,
|
||||
diff: Vec<WidgetDiff>,
|
||||
},
|
||||
UpdateImageData {
|
||||
#[serde(rename = "documentId")]
|
||||
document_id: DocumentId,
|
||||
|
||||
@@ -264,6 +264,8 @@ pub fn default_mapping() -> Mapping {
|
||||
entry!(KeyDown(KeyC); modifiers=[Alt], action_dispatch=ToolMessage::SelectRandomPrimaryColor),
|
||||
//
|
||||
// DocumentMessage
|
||||
entry!(KeyDown(Space); modifiers=[Control], action_dispatch=DocumentMessage::GraphViewOverlayToggle),
|
||||
entry!(KeyUp(Escape); action_dispatch=DocumentMessage::GraphViewOverlay { open: false }),
|
||||
entry!(KeyDown(Delete); action_dispatch=DocumentMessage::DeleteSelectedLayers),
|
||||
entry!(KeyDown(Backspace); action_dispatch=DocumentMessage::DeleteSelectedLayers),
|
||||
entry!(KeyDown(KeyP); modifiers=[Alt], action_dispatch=DocumentMessage::DebugPrintDocument),
|
||||
@@ -337,8 +339,6 @@ pub fn default_mapping() -> Mapping {
|
||||
entry!(KeyDown(Period); action_dispatch=NavigationMessage::FitViewportToSelection),
|
||||
//
|
||||
// PortfolioMessage
|
||||
entry!(KeyDown(Space); modifiers=[Control], action_dispatch=PortfolioMessage::GraphViewOverlayToggle),
|
||||
entry!(KeyUp(Escape); action_dispatch=PortfolioMessage::GraphViewOverlay { open: false }),
|
||||
entry!(KeyDown(Tab); modifiers=[Control], action_dispatch=PortfolioMessage::NextDocument),
|
||||
entry!(KeyDown(Tab); modifiers=[Control, Shift], action_dispatch=PortfolioMessage::PrevDocument),
|
||||
entry!(KeyDown(KeyW); modifiers=[Accel], action_dispatch=PortfolioMessage::CloseActiveDocumentWithConfirmation),
|
||||
|
||||
@@ -171,12 +171,6 @@ impl<F: Fn(&MessageDiscriminant) -> Vec<KeysGroup>> MessageHandler<LayoutMessage
|
||||
},
|
||||
_ => {} // If it's some other type we could just ignore it and leave the value as is
|
||||
},
|
||||
Widget::OptionalInput(optional_input) => {
|
||||
let update_value = value.as_bool().expect("OptionalInput update was not of type: bool");
|
||||
optional_input.checked = update_value;
|
||||
let callback_message = (optional_input.on_update.callback)(optional_input);
|
||||
responses.add(callback_message);
|
||||
}
|
||||
Widget::ParameterExposeButton(parameter_expose_button) => {
|
||||
let callback_message = (parameter_expose_button.on_update.callback)(parameter_expose_button);
|
||||
responses.add(callback_message);
|
||||
@@ -212,7 +206,7 @@ impl<F: Fn(&MessageDiscriminant) -> Vec<KeysGroup>> MessageHandler<LayoutMessage
|
||||
responses.add(callback_message);
|
||||
}
|
||||
Widget::TextLabel(_) => {}
|
||||
Widget::WorkingColorsButton(_) => {}
|
||||
Widget::WorkingColorsInput(_) => {}
|
||||
};
|
||||
responses.add(ResendActiveWidget { layout_target, dirty_id: widget_id });
|
||||
}
|
||||
@@ -273,7 +267,6 @@ impl LayoutMessageHandler {
|
||||
LayoutTarget::DialogColumn2 => FrontendMessage::UpdateDialogColumn2 { layout_target, diff },
|
||||
LayoutTarget::DocumentBar => FrontendMessage::UpdateDocumentBarLayout { layout_target, diff },
|
||||
LayoutTarget::DocumentMode => FrontendMessage::UpdateDocumentModeLayout { layout_target, diff },
|
||||
LayoutTarget::GraphViewOverlayButton => FrontendMessage::UpdateGraphViewOverlayButtonLayout { layout_target, diff },
|
||||
LayoutTarget::LayersPanelOptions => FrontendMessage::UpdateLayersPanelOptionsLayout { layout_target, diff },
|
||||
LayoutTarget::MenuBar => unreachable!("Menu bar is not diffed"),
|
||||
LayoutTarget::NodeGraphBar => FrontendMessage::UpdateNodeGraphBarLayout { layout_target, diff },
|
||||
|
||||
@@ -34,8 +34,6 @@ pub enum LayoutTarget {
|
||||
DocumentBar,
|
||||
/// Contains the dropdown for design / select / guide mode found on the top left of the canvas.
|
||||
DocumentMode,
|
||||
/// The button below the tool shelf and directly above the working colors which lets the user toggle the node graph overlaid on the canvas.
|
||||
GraphViewOverlayButton,
|
||||
/// Options for opacity seen at the top of the Layers panel.
|
||||
LayersPanelOptions,
|
||||
/// The dropdown menu at the very top of the application: File, Edit, etc.
|
||||
@@ -337,7 +335,6 @@ impl LayoutGroup {
|
||||
Widget::IconLabel(x) => &mut x.tooltip,
|
||||
Widget::ImageLabel(x) => &mut x.tooltip,
|
||||
Widget::NumberInput(x) => &mut x.tooltip,
|
||||
Widget::OptionalInput(x) => &mut x.tooltip,
|
||||
Widget::ParameterExposeButton(x) => &mut x.tooltip,
|
||||
Widget::PopoverButton(x) => &mut x.tooltip,
|
||||
Widget::TextAreaInput(x) => &mut x.tooltip,
|
||||
@@ -345,7 +342,7 @@ impl LayoutGroup {
|
||||
Widget::TextInput(x) => &mut x.tooltip,
|
||||
Widget::TextLabel(x) => &mut x.tooltip,
|
||||
Widget::BreadcrumbTrailButtons(x) => &mut x.tooltip,
|
||||
Widget::InvisibleStandinInput(_) | Widget::PivotInput(_) | Widget::RadioInput(_) | Widget::Separator(_) | Widget::WorkingColorsButton(_) => continue,
|
||||
Widget::InvisibleStandinInput(_) | Widget::PivotInput(_) | Widget::RadioInput(_) | Widget::Separator(_) | Widget::WorkingColorsInput(_) => continue,
|
||||
};
|
||||
if val.is_empty() {
|
||||
*val = tooltip.clone();
|
||||
@@ -491,7 +488,6 @@ pub enum Widget {
|
||||
ImageLabel(ImageLabel),
|
||||
InvisibleStandinInput(InvisibleStandinInput),
|
||||
NumberInput(NumberInput),
|
||||
OptionalInput(OptionalInput),
|
||||
ParameterExposeButton(ParameterExposeButton),
|
||||
PivotInput(PivotInput),
|
||||
PopoverButton(PopoverButton),
|
||||
@@ -501,7 +497,7 @@ pub enum Widget {
|
||||
TextButton(TextButton),
|
||||
TextInput(TextInput),
|
||||
TextLabel(TextLabel),
|
||||
WorkingColorsButton(WorkingColorsButton),
|
||||
WorkingColorsInput(WorkingColorsInput),
|
||||
}
|
||||
|
||||
/// A single change to part of the UI, containing the location of the change and the new value.
|
||||
@@ -560,7 +556,6 @@ impl DiffUpdate {
|
||||
Widget::FontInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
|
||||
Widget::IconButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
|
||||
Widget::NumberInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
|
||||
Widget::OptionalInput(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
|
||||
Widget::ParameterExposeButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
|
||||
Widget::PopoverButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
|
||||
Widget::TextButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
|
||||
@@ -574,7 +569,7 @@ impl DiffUpdate {
|
||||
| Widget::TextAreaInput(_)
|
||||
| Widget::TextInput(_)
|
||||
| Widget::TextLabel(_)
|
||||
| Widget::WorkingColorsButton(_) => None,
|
||||
| Widget::WorkingColorsInput(_) => None,
|
||||
};
|
||||
if let Some((tooltip, Some(tooltip_shortcut))) = &mut tooltip_shortcut {
|
||||
apply_shortcut_to_tooltip(tooltip_shortcut, tooltip);
|
||||
|
||||
@@ -35,6 +35,8 @@ pub struct IconButton {
|
||||
#[derive(Clone, Serialize, Deserialize, Derivative, WidgetBuilder, specta::Type)]
|
||||
#[derivative(Debug, PartialEq, Default)]
|
||||
pub struct PopoverButton {
|
||||
pub style: Option<String>,
|
||||
|
||||
pub icon: Option<String>,
|
||||
|
||||
pub disabled: bool,
|
||||
@@ -85,8 +87,7 @@ pub struct TextButton {
|
||||
|
||||
pub icon: Option<String>,
|
||||
|
||||
#[serde(rename = "noBackground")]
|
||||
pub no_background: bool,
|
||||
pub flush: bool,
|
||||
|
||||
pub emphasized: bool,
|
||||
|
||||
@@ -109,16 +110,6 @@ pub struct TextButton {
|
||||
pub on_update: WidgetCallback<TextButton>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Derivative, WidgetBuilder, specta::Type)]
|
||||
#[derivative(Debug, PartialEq, Default)]
|
||||
pub struct WorkingColorsButton {
|
||||
#[widget_builder(constructor)]
|
||||
pub primary: Color,
|
||||
|
||||
#[widget_builder(constructor)]
|
||||
pub secondary: Color,
|
||||
}
|
||||
|
||||
#[derive(Clone, Derivative, Serialize, Deserialize, WidgetBuilder, specta::Type)]
|
||||
#[derivative(Debug, PartialEq, Default)]
|
||||
pub struct ColorButton {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::messages::input_mapper::utility_types::misc::ActionKeys;
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
|
||||
use graphene_core::raster::curve::Curve;
|
||||
use graphene_core::{raster::curve::Curve, Color};
|
||||
use graphite_proc_macros::WidgetBuilder;
|
||||
|
||||
use derivative::*;
|
||||
@@ -253,28 +253,6 @@ pub enum NumberInputMode {
|
||||
Range,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Derivative, Serialize, Deserialize, WidgetBuilder, specta::Type)]
|
||||
#[derivative(Debug, PartialEq)]
|
||||
pub struct OptionalInput {
|
||||
#[widget_builder(constructor)]
|
||||
pub checked: bool,
|
||||
|
||||
pub disabled: bool,
|
||||
|
||||
#[widget_builder(constructor)]
|
||||
pub icon: String,
|
||||
|
||||
pub tooltip: String,
|
||||
|
||||
#[serde(skip)]
|
||||
pub tooltip_shortcut: Option<ActionKeys>,
|
||||
|
||||
// Callbacks
|
||||
#[serde(skip)]
|
||||
#[derivative(Debug = "ignore", PartialEq = "ignore")]
|
||||
pub on_update: WidgetCallback<OptionalInput>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Derivative, Serialize, Deserialize, WidgetBuilder, specta::Type)]
|
||||
#[derivative(Debug, PartialEq)]
|
||||
pub struct RadioInput {
|
||||
@@ -310,6 +288,16 @@ pub struct RadioEntryData {
|
||||
pub on_update: WidgetCallback<()>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Derivative, WidgetBuilder, specta::Type)]
|
||||
#[derivative(Debug, PartialEq, Default)]
|
||||
pub struct WorkingColorsInput {
|
||||
#[widget_builder(constructor)]
|
||||
pub primary: Color,
|
||||
|
||||
#[widget_builder(constructor)]
|
||||
pub secondary: Color,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Derivative, WidgetBuilder, specta::Type)]
|
||||
#[derivative(Debug, PartialEq, Default)]
|
||||
pub struct TextAreaInput {
|
||||
|
||||
@@ -46,7 +46,6 @@ pub enum SeparatorType {
|
||||
#[default]
|
||||
Unrelated,
|
||||
Section,
|
||||
List,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Derivative, Debug, PartialEq, Eq, Default, WidgetBuilder, specta::Type)]
|
||||
|
||||
@@ -59,6 +59,10 @@ pub enum DocumentMessage {
|
||||
FlipSelectedLayers {
|
||||
flip_axis: FlipAxis,
|
||||
},
|
||||
GraphViewOverlay {
|
||||
open: bool,
|
||||
},
|
||||
GraphViewOverlayToggle,
|
||||
GroupSelectedLayers,
|
||||
ImaginateGenerate,
|
||||
ImaginateRandom {
|
||||
|
||||
@@ -81,6 +81,8 @@ pub struct DocumentMessageHandler {
|
||||
#[serde(skip)]
|
||||
undo_in_progress: bool,
|
||||
#[serde(skip)]
|
||||
graph_view_overlay_open: bool,
|
||||
#[serde(skip)]
|
||||
pub snapping_state: SnappingState,
|
||||
#[serde(skip)]
|
||||
layer_range_selection_reference: Option<LayerNodeIdentifier>,
|
||||
@@ -119,6 +121,7 @@ impl Default for DocumentMessageHandler {
|
||||
saved_hash: None,
|
||||
auto_saved_hash: None,
|
||||
undo_in_progress: false,
|
||||
graph_view_overlay_open: false,
|
||||
snapping_state: SnappingState::default(),
|
||||
layer_range_selection_reference: None,
|
||||
metadata: Default::default(),
|
||||
@@ -227,7 +230,6 @@ pub struct DocumentInputs<'a> {
|
||||
pub ipp: &'a InputPreprocessorMessageHandler,
|
||||
pub persistent_data: &'a PersistentData,
|
||||
pub executor: &'a mut NodeGraphExecutor,
|
||||
pub graph_view_overlay_open: bool,
|
||||
}
|
||||
|
||||
impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHandler {
|
||||
@@ -238,7 +240,6 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
|
||||
ipp,
|
||||
persistent_data,
|
||||
executor,
|
||||
graph_view_overlay_open,
|
||||
} = document_inputs;
|
||||
use DocumentMessage::*;
|
||||
|
||||
@@ -282,7 +283,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
|
||||
document_name: self.name.as_str(),
|
||||
collapsed: &mut self.collapsed,
|
||||
input: ipp,
|
||||
graph_view_overlay_open,
|
||||
graph_view_overlay_open: self.graph_view_overlay_open,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -382,7 +383,11 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
|
||||
self.update_layers_panel_options_bar_widgets(responses);
|
||||
|
||||
let data_buffer: RawBuffer = self.serialize_root();
|
||||
responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer })
|
||||
responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer });
|
||||
|
||||
if self.graph_view_overlay_open {
|
||||
responses.add(NodeGraphMessage::SendGraph { should_rerender: false });
|
||||
}
|
||||
}
|
||||
DuplicateSelectedLayers => {
|
||||
// TODO: Reimplement selected layer duplication
|
||||
@@ -412,6 +417,17 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
|
||||
responses.add(BroadcastEvent::DocumentIsDirty);
|
||||
}
|
||||
}
|
||||
GraphViewOverlay { open } => {
|
||||
self.graph_view_overlay_open = open;
|
||||
|
||||
if open {
|
||||
responses.add(NodeGraphMessage::SendGraph { should_rerender: false });
|
||||
}
|
||||
responses.add(FrontendMessage::TriggerGraphViewOverlay { open });
|
||||
}
|
||||
GraphViewOverlayToggle => {
|
||||
responses.add(DocumentMessage::GraphViewOverlay { open: !self.graph_view_overlay_open });
|
||||
}
|
||||
GroupSelectedLayers => {
|
||||
// TODO: Add code that changes the insert index of the new folder based on the selected layer
|
||||
let parent = self.metadata().deepest_common_ancestor(self.metadata().selected_layers(), true).unwrap_or(LayerNodeIdentifier::ROOT);
|
||||
@@ -1089,9 +1105,10 @@ impl DocumentMessageHandler {
|
||||
pub fn update_document_widgets(&self, responses: &mut VecDeque<Message>) {
|
||||
let snapping_state = self.snapping_state.clone();
|
||||
let mut widgets = vec![
|
||||
OptionalInput::new(snapping_state.snapping_enabled, "Snapping")
|
||||
CheckboxInput::new(snapping_state.snapping_enabled)
|
||||
.icon("Snapping")
|
||||
.tooltip("Snapping")
|
||||
.on_update(move |optional_input: &OptionalInput| {
|
||||
.on_update(move |optional_input: &CheckboxInput| {
|
||||
let snapping_enabled = optional_input.checked;
|
||||
DocumentMessage::SetSnapping {
|
||||
snapping_enabled: Some(snapping_enabled),
|
||||
@@ -1105,6 +1122,8 @@ impl DocumentMessageHandler {
|
||||
.options_widget(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
TextLabel::new(SnappingOptions::BoundingBoxes.to_string()).table_align(true).min_width(96).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
CheckboxInput::new(snapping_state.bounding_box_snapping)
|
||||
.tooltip(SnappingOptions::BoundingBoxes.to_string())
|
||||
.on_update(move |input: &CheckboxInput| {
|
||||
@@ -1116,13 +1135,13 @@ impl DocumentMessageHandler {
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
TextLabel::new(SnappingOptions::BoundingBoxes.to_string()).table_align(false).min_width(60).widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
TextLabel::new(SnappingOptions::Points.to_string()).table_align(true).min_width(96).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
CheckboxInput::new(self.snapping_state.node_snapping)
|
||||
.tooltip(SnappingOptions::Points.to_string())
|
||||
.on_update(|input: &CheckboxInput| {
|
||||
@@ -1134,22 +1153,22 @@ impl DocumentMessageHandler {
|
||||
.into()
|
||||
})
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
TextLabel::new(SnappingOptions::Points.to_string()).table_align(false).min_width(60).widget_holder(),
|
||||
],
|
||||
},
|
||||
])
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
OptionalInput::new(true, "Grid")
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
CheckboxInput::new(true)
|
||||
.icon("Grid")
|
||||
.tooltip("Grid")
|
||||
.on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(318) }.into())
|
||||
.widget_holder(),
|
||||
PopoverButton::new("Grid", "Coming soon").widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
OptionalInput::new(self.overlays_visible, "Overlays")
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
CheckboxInput::new(self.overlays_visible)
|
||||
.icon("Overlays")
|
||||
.tooltip("Overlays")
|
||||
.on_update(|optional_input: &OptionalInput| DocumentMessage::SetOverlaysVisibility { visible: optional_input.checked }.into())
|
||||
.on_update(|optional_input: &CheckboxInput| DocumentMessage::SetOverlaysVisibility { visible: optional_input.checked }.into())
|
||||
.widget_holder(),
|
||||
PopoverButton::new("Overlays", "Coming soon").widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
@@ -1176,7 +1195,7 @@ impl DocumentMessageHandler {
|
||||
})
|
||||
.widget_holder(),
|
||||
PopoverButton::new("View Mode", "Coming soon").widget_holder(),
|
||||
Separator::new(SeparatorType::Section).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
IconButton::new("ZoomIn", 24)
|
||||
.tooltip("Zoom In")
|
||||
.tooltip_shortcut(action_keys!(NavigationMessageDiscriminant::IncreaseCanvasZoom))
|
||||
@@ -1192,6 +1211,11 @@ impl DocumentMessageHandler {
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ZoomCanvasTo100Percent))
|
||||
.on_update(|_| NavigationMessage::SetCanvasZoom { zoom_factor: 1. }.into())
|
||||
.widget_holder(),
|
||||
PopoverButton::new(
|
||||
"Canvas Navigation",
|
||||
"Interactive controls in this\nmenu are coming soon.\n\nPan:\n• Middle Click Drag\n\nTilt:\n• Alt + Middle Click Drag\n\nZoom:\n• Shift + Middle Click Drag\n• Ctrl + Scroll Wheel Roll",
|
||||
)
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
NumberInput::new(Some(self.navigation_handler.snapped_scale(self.navigation.zoom) * 100.))
|
||||
.unit("%")
|
||||
@@ -1208,6 +1232,13 @@ impl DocumentMessageHandler {
|
||||
.increment_callback_decrease(|_| NavigationMessage::DecreaseCanvasZoom { center_on_mouse: false }.into())
|
||||
.increment_callback_increase(|_| NavigationMessage::IncreaseCanvasZoom { center_on_mouse: false }.into())
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
TextButton::new("Node Graph")
|
||||
.icon(Some(if self.graph_view_overlay_open { "GraphViewOpen".into() } else { "GraphViewClosed".into() }))
|
||||
.tooltip(if self.graph_view_overlay_open { "Hide Node Graph" } else { "Show Node Graph" })
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::GraphViewOverlayToggle))
|
||||
.on_update(move |_| DocumentMessage::GraphViewOverlayToggle.into())
|
||||
.widget_holder(),
|
||||
];
|
||||
let rotation_value = self.navigation_handler.snapped_angle(self.navigation.tilt) / (std::f64::consts::PI / 180.);
|
||||
if rotation_value.abs() > 0.00001 {
|
||||
@@ -1225,14 +1256,6 @@ impl DocumentMessageHandler {
|
||||
.widget_holder(),
|
||||
]);
|
||||
}
|
||||
widgets.extend([
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
PopoverButton::new(
|
||||
"Canvas Navigation",
|
||||
"Interactive options in this popover\nmenu are coming soon.\n\nZoom:\n• Shift + Middle Click Drag\n• Ctrl + Scroll Wheel Roll\nRotate:\n• Alt + Left Click Drag",
|
||||
)
|
||||
.widget_holder(),
|
||||
]);
|
||||
let document_bar_layout = WidgetLayout::new(vec![LayoutGroup::Row { widgets }]);
|
||||
|
||||
let document_mode_layout = WidgetLayout::new(vec![LayoutGroup::Row {
|
||||
@@ -1339,7 +1362,7 @@ impl DocumentMessageHandler {
|
||||
}
|
||||
})
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Section).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
IconButton::new("Folder", 24)
|
||||
.tooltip("New Folder")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder))
|
||||
@@ -1398,7 +1421,7 @@ impl DocumentMessageHandler {
|
||||
responses.add(DocumentMessage::MoveSelectedLayersTo { parent, insert_index });
|
||||
}
|
||||
|
||||
pub fn actions_with_graph_open(&self, graph_open: bool) -> ActionList {
|
||||
pub fn actions_with_graph_open(&self) -> ActionList {
|
||||
let mut common = actions!(DocumentMessageDiscriminant;
|
||||
Undo,
|
||||
Redo,
|
||||
@@ -1411,9 +1434,15 @@ impl DocumentMessageHandler {
|
||||
ZoomCanvasToFitAll,
|
||||
ZoomCanvasTo100Percent,
|
||||
ZoomCanvasTo200Percent,
|
||||
GraphViewOverlayToggle,
|
||||
CreateEmptyFolder,
|
||||
);
|
||||
|
||||
if self.graph_view_overlay_open {
|
||||
let escape = actions!(DocumentMessageDiscriminant; GraphViewOverlay);
|
||||
common.extend(escape);
|
||||
}
|
||||
|
||||
if self.metadata().selected_layers().next().is_some() {
|
||||
let select = actions!(DocumentMessageDiscriminant;
|
||||
DeleteSelectedLayers,
|
||||
@@ -1429,7 +1458,7 @@ impl DocumentMessageHandler {
|
||||
common.extend(select);
|
||||
}
|
||||
common.extend(self.navigation_handler.actions());
|
||||
common.extend(self.node_graph_handler.actions_with_node_graph_open(graph_open));
|
||||
common.extend(self.node_graph_handler.actions_with_node_graph_open(self.graph_view_overlay_open));
|
||||
common
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,14 +130,22 @@ pub struct NodeGraphMessageHandler {
|
||||
|
||||
impl Default for NodeGraphMessageHandler {
|
||||
fn default() -> Self {
|
||||
// TODO: Replace this with an "Add Node" button, also next to an "Add Layer" button
|
||||
let add_nodes_label = TextLabel::new("Right Click Graph to Add Nodes").italic(true).widget_holder();
|
||||
let add_nodes_label_row = LayoutGroup::Row { widgets: vec![add_nodes_label] };
|
||||
let right_side_widgets = vec![
|
||||
// TODO: Replace this with an "Add Node" button, also next to an "Add Layer" button
|
||||
TextLabel::new("Right Click in Graph to Add Nodes").italic(true).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
TextButton::new("Node Graph")
|
||||
.icon(Some("GraphViewOpen".into()))
|
||||
.tooltip("Hide Node Graph")
|
||||
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::GraphViewOverlayToggle))
|
||||
.on_update(move |_| DocumentMessage::GraphViewOverlayToggle.into())
|
||||
.widget_holder(),
|
||||
];
|
||||
|
||||
Self {
|
||||
network: Vec::new(),
|
||||
has_selection: false,
|
||||
widgets: [add_nodes_label_row, LayoutGroup::default()],
|
||||
widgets: [LayoutGroup::Row { widgets: Vec::new() }, LayoutGroup::Row { widgets: right_side_widgets }],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,8 +169,6 @@ impl NodeGraphMessageHandler {
|
||||
|
||||
// If there is at least one other selected node then show the hide or show button
|
||||
if selected_nodes.next().is_some() {
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
// Check if any of the selected nodes are disabled
|
||||
let is_hidden = document_metadata.selected_nodes().any(|id| network.disabled.contains(id));
|
||||
|
||||
@@ -178,13 +184,13 @@ impl NodeGraphMessageHandler {
|
||||
.on_update(move |_| NodeGraphMessage::ToggleSelectedHidden.into())
|
||||
.widget_holder();
|
||||
widgets.push(hide_button);
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Related).widget_holder());
|
||||
}
|
||||
|
||||
// If only one node is selected then show the preview or stop previewing button
|
||||
let mut selected_nodes = document_metadata.selected_nodes();
|
||||
if let (Some(&node_id), None) = (selected_nodes.next(), selected_nodes.next()) {
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
// Is this node the current output
|
||||
let is_output = network.outputs_contain(node_id);
|
||||
|
||||
@@ -199,7 +205,7 @@ impl NodeGraphMessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
self.widgets[1] = LayoutGroup::Row { widgets };
|
||||
self.widgets[0] = LayoutGroup::Row { widgets };
|
||||
}
|
||||
self.send_node_bar_layout(responses);
|
||||
}
|
||||
|
||||
@@ -52,22 +52,19 @@ fn expose_widget(node_id: NodeId, index: usize, data_type: FrontendGraphDataType
|
||||
.widget_holder()
|
||||
}
|
||||
|
||||
// TODO: Remove this when we have proper entry row formatting that includes room for Assists.
|
||||
fn add_blank_assist(widgets: &mut Vec<WidgetHolder>) {
|
||||
widgets.extend_from_slice(&[
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: This last one is the separator after the 24px assist.
|
||||
// Custom CSS specific to the Properties panel converts this Section separator into the width of an assist (24px).
|
||||
Separator::new(SeparatorType::Section).widget_holder(),
|
||||
// This last one is the separator after the 24px assist.
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
]);
|
||||
}
|
||||
|
||||
fn start_widgets(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, data_type: FrontendGraphDataType, blank_assist: bool) -> Vec<WidgetHolder> {
|
||||
let input = document_node.inputs.get(index).expect("A widget failed to be built because its node's input index is invalid.");
|
||||
let mut widgets = vec![
|
||||
expose_widget(node_id, index, data_type, input.is_exposed()),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
TextLabel::new(name).widget_holder(),
|
||||
];
|
||||
let mut widgets = vec![expose_widget(node_id, index, data_type, input.is_exposed()), TextLabel::new(name).widget_holder()];
|
||||
if blank_assist {
|
||||
add_blank_assist(&mut widgets);
|
||||
}
|
||||
@@ -291,18 +288,17 @@ fn font_inputs(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
||||
.on_update(update_value(from_font_input, node_id, index))
|
||||
.widget_holder(),
|
||||
]);
|
||||
second_widgets = Some(vec![
|
||||
TextLabel::new("").widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
|
||||
let mut second_row = vec![TextLabel::new("").widget_holder()];
|
||||
add_blank_assist(&mut second_row);
|
||||
second_row.extend_from_slice(&[
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
FontInput::new(font.font_family.clone(), font.font_style.clone())
|
||||
.is_style_picker(true)
|
||||
.on_update(update_value(from_font_input, node_id, index))
|
||||
.widget_holder(),
|
||||
]);
|
||||
second_widgets = Some(second_row);
|
||||
}
|
||||
(first_widgets, second_widgets)
|
||||
}
|
||||
@@ -1559,16 +1555,10 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
||||
let transform_not_connected = false;
|
||||
|
||||
let progress = {
|
||||
let mut widgets = vec![TextLabel::new("Progress").widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder()];
|
||||
add_blank_assist(&mut widgets);
|
||||
let status = imaginate_status.to_text();
|
||||
let widgets = vec![
|
||||
TextLabel::new("Progress").widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
TextLabel::new(status.as_ref()).bold(true).widget_holder(),
|
||||
];
|
||||
widgets.push(TextLabel::new(status.as_ref()).bold(true).widget_holder());
|
||||
LayoutGroup::Row { widgets }.with_tooltip(match imaginate_status {
|
||||
ImaginateStatus::Failed(_) => status.as_ref(),
|
||||
_ => "When generating, the percentage represents how many sampling steps have so far been processed out of the target number",
|
||||
@@ -1577,20 +1567,14 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
||||
|
||||
let image_controls = {
|
||||
let mut widgets = vec![TextLabel::new("Image").widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder()];
|
||||
let assist_separators = [
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: These three separators add up to 24px,
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: which is the width of the Assist area.
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists.
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
];
|
||||
|
||||
match &imaginate_status {
|
||||
ImaginateStatus::Beginning | ImaginateStatus::Uploading => {
|
||||
widgets.extend_from_slice(&assist_separators);
|
||||
add_blank_assist(&mut widgets);
|
||||
widgets.push(TextButton::new("Beginning...").tooltip("Sending image generation request to the server").disabled(true).widget_holder());
|
||||
}
|
||||
ImaginateStatus::Generating(_) => {
|
||||
widgets.extend_from_slice(&assist_separators);
|
||||
add_blank_assist(&mut widgets);
|
||||
widgets.push(
|
||||
TextButton::new("Terminate")
|
||||
.tooltip("Cancel the in-progress image generation and keep the latest progress")
|
||||
@@ -1605,7 +1589,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
||||
);
|
||||
}
|
||||
ImaginateStatus::Terminating => {
|
||||
widgets.extend_from_slice(&assist_separators);
|
||||
add_blank_assist(&mut widgets);
|
||||
widgets.push(
|
||||
TextButton::new("Terminating...")
|
||||
.tooltip("Waiting on the final image generated after termination")
|
||||
@@ -1755,7 +1739,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
||||
resolution_index,
|
||||
))
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
NumberInput::new(Some(vec2.x))
|
||||
.label("W")
|
||||
.min(64.)
|
||||
|
||||
@@ -47,12 +47,10 @@ impl<'a> MessageHandler<PropertiesPanelMessage, (&PersistentData, PropertiesPane
|
||||
let options_bar = vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
IconLabel::new("File").tooltip("Document").widget_holder(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
TextInput::new(document_name)
|
||||
.on_update(|text_input| DocumentMessage::RenameDocument { new_name: text_input.value.clone() }.into())
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
PopoverButton::new("Additional Options", "Coming soon").widget_holder(),
|
||||
],
|
||||
}];
|
||||
|
||||
|
||||
@@ -55,10 +55,6 @@ pub enum PortfolioMessage {
|
||||
data: Vec<u8>,
|
||||
is_default: bool,
|
||||
},
|
||||
GraphViewOverlay {
|
||||
open: bool,
|
||||
},
|
||||
GraphViewOverlayToggle,
|
||||
ImaginateCheckServerStatus,
|
||||
ImaginatePollServerStatus,
|
||||
ImaginatePreferences,
|
||||
|
||||
@@ -3,7 +3,6 @@ use crate::application::generate_uuid;
|
||||
use crate::consts::{DEFAULT_DOCUMENT_NAME, GRAPHITE_DOCUMENT_VERSION};
|
||||
use crate::messages::dialog::simple_dialogs;
|
||||
use crate::messages::frontend::utility_types::FrontendDocumentDetails;
|
||||
use crate::messages::input_mapper::utility_types::macros::action_keys;
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
use crate::messages::portfolio::document::utility_types::clipboards::{Clipboard, CopyBufferEntry, INTERNAL_CLIPBOARD_COUNT};
|
||||
use crate::messages::portfolio::document::DocumentInputs;
|
||||
@@ -22,7 +21,6 @@ pub struct PortfolioMessageHandler {
|
||||
documents: HashMap<DocumentId, DocumentMessageHandler>,
|
||||
document_ids: Vec<DocumentId>,
|
||||
active_document_id: Option<DocumentId>,
|
||||
graph_view_overlay_open: bool,
|
||||
copy_buffer: [Vec<CopyBufferEntry>; INTERNAL_CLIPBOARD_COUNT as usize],
|
||||
pub persistent_data: PersistentData,
|
||||
pub executor: NodeGraphExecutor,
|
||||
@@ -55,7 +53,6 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
||||
ipp,
|
||||
persistent_data: &self.persistent_data,
|
||||
executor: &mut self.executor,
|
||||
graph_view_overlay_open: self.graph_view_overlay_open,
|
||||
};
|
||||
document.process_message(message, responses, document_inputs)
|
||||
}
|
||||
@@ -71,7 +68,6 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
||||
ipp,
|
||||
persistent_data: &self.persistent_data,
|
||||
executor: &mut self.executor,
|
||||
graph_view_overlay_open: self.graph_view_overlay_open,
|
||||
};
|
||||
document.process_message(message, responses, document_inputs)
|
||||
}
|
||||
@@ -257,29 +253,6 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
||||
responses.add(BroadcastEvent::DocumentIsDirty);
|
||||
}
|
||||
}
|
||||
PortfolioMessage::GraphViewOverlay { open } => {
|
||||
self.graph_view_overlay_open = open;
|
||||
|
||||
let layout = WidgetLayout::new(vec![LayoutGroup::Row {
|
||||
widgets: vec![IconButton::new(if open { "GraphViewOpen" } else { "GraphViewClosed" }, 32)
|
||||
.tooltip(if open { "Hide Node Graph" } else { "Show Node Graph" })
|
||||
.tooltip_shortcut(action_keys!(PortfolioMessageDiscriminant::GraphViewOverlayToggle))
|
||||
.on_update(move |_| PortfolioMessage::GraphViewOverlay { open: !open }.into())
|
||||
.widget_holder()],
|
||||
}]);
|
||||
responses.add(LayoutMessage::SendLayout {
|
||||
layout: Layout::WidgetLayout(layout),
|
||||
layout_target: LayoutTarget::GraphViewOverlayButton,
|
||||
});
|
||||
|
||||
if open {
|
||||
responses.add(NodeGraphMessage::SendGraph { should_rerender: false });
|
||||
}
|
||||
responses.add(FrontendMessage::TriggerGraphViewOverlay { open });
|
||||
}
|
||||
PortfolioMessage::GraphViewOverlayToggle => {
|
||||
responses.add(PortfolioMessage::GraphViewOverlay { open: !self.graph_view_overlay_open });
|
||||
}
|
||||
PortfolioMessage::ImaginateCheckServerStatus => {
|
||||
let server_status = self.persistent_data.imaginate.server_status().clone();
|
||||
self.persistent_data.imaginate.poll_server_check();
|
||||
@@ -473,9 +446,6 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
||||
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
||||
responses.add(NavigationMessage::TranslateCanvas { delta: (0., 0.).into() });
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
if self.graph_view_overlay_open {
|
||||
responses.add(NodeGraphMessage::SendGraph { should_rerender: false });
|
||||
}
|
||||
}
|
||||
PortfolioMessage::SetActiveDocument { document_id } => {
|
||||
self.active_document_id = Some(document_id);
|
||||
@@ -553,7 +523,6 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
||||
|
||||
fn actions(&self) -> ActionList {
|
||||
let mut common = actions!(PortfolioMessageDiscriminant;
|
||||
GraphViewOverlayToggle,
|
||||
CloseActiveDocumentWithConfirmation,
|
||||
CloseAllDocuments,
|
||||
CloseAllDocumentsWithConfirmation,
|
||||
@@ -565,11 +534,6 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
||||
ToggleRulers,
|
||||
);
|
||||
|
||||
if self.graph_view_overlay_open {
|
||||
let escape = actions!(PortfolioMessageDiscriminant; GraphViewOverlay);
|
||||
common.extend(escape);
|
||||
}
|
||||
|
||||
if let Some(document) = self.active_document() {
|
||||
if document.metadata().selected_layers().next().is_some() {
|
||||
let select = actions!(PortfolioMessageDiscriminant;
|
||||
@@ -578,7 +542,8 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
||||
);
|
||||
common.extend(select);
|
||||
}
|
||||
common.extend(document.actions_with_graph_open(self.graph_view_overlay_open));
|
||||
|
||||
common.extend(document.actions_with_graph_open());
|
||||
}
|
||||
|
||||
common
|
||||
@@ -652,7 +617,6 @@ impl PortfolioMessageHandler {
|
||||
responses.add(PortfolioMessage::SelectDocument { document_id });
|
||||
responses.add(PortfolioMessage::LoadDocumentResources { document_id });
|
||||
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
||||
responses.add(PortfolioMessage::GraphViewOverlay { open: self.graph_view_overlay_open });
|
||||
responses.add(ToolMessage::InitTools);
|
||||
responses.add(NodeGraphMessage::Init);
|
||||
responses.add(NavigationMessage::TranslateCanvas { delta: (0., 0.).into() });
|
||||
|
||||
@@ -141,7 +141,7 @@ impl LayoutHolder for BrushTool {
|
||||
.widget_holder(),
|
||||
];
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
let draw_mode_entries: Vec<_> = [DrawMode::Draw, DrawMode::Erase, DrawMode::Restore]
|
||||
.into_iter()
|
||||
@@ -149,7 +149,7 @@ impl LayoutHolder for BrushTool {
|
||||
.collect();
|
||||
widgets.push(RadioInput::new(draw_mode_entries).selected_index(Some(self.options.draw_mode as u32)).widget_holder());
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
widgets.append(&mut self.options.color.create_widgets(
|
||||
"Color",
|
||||
|
||||
@@ -96,7 +96,7 @@ impl LayoutHolder for EllipseTool {
|
||||
|color: &ColorButton| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColor(color.value)).into(),
|
||||
);
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
widgets.append(&mut self.options.stroke.create_widgets(
|
||||
"Stroke",
|
||||
|
||||
@@ -103,7 +103,7 @@ impl LayoutHolder for FreehandTool {
|
||||
|color: &ColorButton| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(color.value)).into(),
|
||||
);
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
widgets.append(&mut self.options.stroke.create_widgets(
|
||||
"Stroke",
|
||||
|
||||
@@ -118,7 +118,7 @@ impl LayoutHolder for PenTool {
|
||||
|color: &ColorButton| PenToolMessage::UpdateOptions(PenOptionsUpdate::FillColor(color.value)).into(),
|
||||
);
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
widgets.append(&mut self.options.stroke.create_widgets(
|
||||
"Stroke",
|
||||
|
||||
@@ -125,7 +125,7 @@ impl LayoutHolder for PolygonTool {
|
||||
create_sides_widget(self.options.vertices),
|
||||
];
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
widgets.append(&mut self.options.fill.create_widgets(
|
||||
"Fill",
|
||||
@@ -135,7 +135,7 @@ impl LayoutHolder for PolygonTool {
|
||||
|color: &ColorButton| PolygonToolMessage::UpdateOptions(PolygonOptionsUpdate::FillColor(color.value)).into(),
|
||||
));
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
widgets.append(&mut self.options.stroke.create_widgets(
|
||||
"Stroke",
|
||||
|
||||
@@ -84,7 +84,7 @@ impl LayoutHolder for RectangleTool {
|
||||
|color: &ColorButton| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::FillColor(color.value)).into(),
|
||||
);
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
widgets.append(&mut self.options.stroke.create_widgets(
|
||||
"Stroke",
|
||||
|
||||
@@ -175,23 +175,20 @@ impl LayoutHolder for SelectTool {
|
||||
|
||||
// Align
|
||||
let disabled = self.tool_data.selected_layers_count < 2;
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
widgets.extend(self.alignment_widgets(disabled));
|
||||
widgets.push(Separator::new(SeparatorType::Related).widget_holder());
|
||||
widgets.push(PopoverButton::new("Align", "Coming soon").disabled(disabled).widget_holder());
|
||||
|
||||
// Flip
|
||||
let disabled = self.tool_data.selected_layers_count == 0;
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
widgets.extend(self.flip_widgets(disabled));
|
||||
widgets.push(Separator::new(SeparatorType::Related).widget_holder());
|
||||
widgets.push(PopoverButton::new("Flip", "Coming soon").disabled(disabled).widget_holder());
|
||||
|
||||
// Boolean
|
||||
if self.tool_data.selected_layers_count >= 2 {
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
widgets.extend(self.boolean_widgets());
|
||||
widgets.push(Separator::new(SeparatorType::Related).widget_holder());
|
||||
widgets.push(PopoverButton::new("Boolean", "Coming soon").widget_holder());
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ impl LayoutHolder for SplineTool {
|
||||
|color: &ColorButton| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::FillColor(color.value)).into(),
|
||||
);
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
widgets.append(&mut self.options.stroke.create_widgets(
|
||||
"Stroke",
|
||||
|
||||
@@ -130,7 +130,7 @@ impl LayoutHolder for TextTool {
|
||||
fn layout(&self) -> Layout {
|
||||
let mut widgets = create_text_widgets(self);
|
||||
|
||||
widgets.push(Separator::new(SeparatorType::Section).widget_holder());
|
||||
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
|
||||
|
||||
widgets.append(&mut self.options.fill.create_widgets(
|
||||
"Fill",
|
||||
|
||||
@@ -138,7 +138,7 @@ impl DocumentToolData {
|
||||
pub fn update_working_colors(&self, responses: &mut VecDeque<Message>) {
|
||||
let layout = WidgetLayout::new(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![WorkingColorsButton::new(self.primary_color, self.secondary_color).widget_holder()],
|
||||
widgets: vec![WorkingColorsInput::new(self.primary_color, self.secondary_color).widget_holder()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
|
||||
Reference in New Issue
Block a user