mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-23 18:58:11 +08:00
Move node graph from panel to overlay on viewport
This commit is contained in:
@@ -255,7 +255,6 @@ impl Dispatcher {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::application::Editor;
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
|
||||
use crate::messages::prelude::*;
|
||||
use crate::test_utils::EditorTestUtils;
|
||||
|
||||
@@ -72,6 +72,9 @@ pub enum FrontendMessage {
|
||||
#[serde(rename = "isDefault")]
|
||||
is_default: bool,
|
||||
},
|
||||
TriggerGraphViewOverlay {
|
||||
open: bool,
|
||||
},
|
||||
TriggerImport,
|
||||
TriggerIndexedDbRemoveDocument {
|
||||
#[serde(rename = "documentId")]
|
||||
@@ -177,6 +180,11 @@ 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: u64,
|
||||
|
||||
@@ -330,13 +330,17 @@ pub fn default_mapping() -> Mapping {
|
||||
entry!(KeyDown(Period); action_dispatch=NavigationMessage::FitViewportToSelection),
|
||||
//
|
||||
// PortfolioMessage
|
||||
entry!(KeyDown(KeyO); modifiers=[Accel], action_dispatch=PortfolioMessage::OpenDocument),
|
||||
entry!(KeyDown(KeyI); modifiers=[Accel], action_dispatch=PortfolioMessage::Import),
|
||||
entry!(KeyUp(Space); action_dispatch=PortfolioMessage::GraphViewOverlayToggle),
|
||||
entry!(KeyDownNoRepeat(Space); action_dispatch=PortfolioMessage::GraphViewOverlayToggleDisabled { disabled: 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),
|
||||
entry!(KeyDown(KeyO); modifiers=[Accel], action_dispatch=PortfolioMessage::OpenDocument),
|
||||
entry!(KeyDown(KeyI); modifiers=[Accel], action_dispatch=PortfolioMessage::Import),
|
||||
entry!(KeyDown(KeyX); modifiers=[Accel], action_dispatch=PortfolioMessage::Cut { clipboard: Clipboard::Device }),
|
||||
entry!(KeyDown(KeyC); modifiers=[Accel], action_dispatch=PortfolioMessage::Copy { clipboard: Clipboard::Device }),
|
||||
//
|
||||
// FrontendMessage
|
||||
entry!(KeyDown(KeyV); modifiers=[Accel], action_dispatch=FrontendMessage::TriggerPaste),
|
||||
//
|
||||
// DialogMessage
|
||||
@@ -351,7 +355,7 @@ pub fn default_mapping() -> Mapping {
|
||||
entry!(KeyDown(Digit1); modifiers=[Alt], action_dispatch=DebugMessage::MessageNames),
|
||||
entry!(KeyDown(Digit2); modifiers=[Alt], action_dispatch=DebugMessage::MessageContents),
|
||||
];
|
||||
let (mut key_up, mut key_down, mut double_click, mut wheel_scroll, mut pointer_move) = mappings;
|
||||
let (mut key_up, mut key_down, mut key_up_no_repeat, mut key_down_no_repeat, mut double_click, mut wheel_scroll, mut pointer_move) = mappings;
|
||||
|
||||
// TODO: Hardcode these 10 lines into 10 lines of declarations, or make this use a macro to do all 10 in one line
|
||||
const NUMBER_KEYS: [Key; 10] = [Digit0, Digit1, Digit2, Digit3, Digit4, Digit5, Digit6, Digit7, Digit8, Digit9];
|
||||
@@ -367,7 +371,7 @@ pub fn default_mapping() -> Mapping {
|
||||
}
|
||||
|
||||
let sort = |list: &mut KeyMappingEntries| list.0.sort_by(|u, v| v.modifiers.ones().cmp(&u.modifiers.ones()));
|
||||
for list in [&mut key_up, &mut key_down] {
|
||||
for list in [&mut key_up, &mut key_down, &mut key_up_no_repeat, &mut key_down_no_repeat] {
|
||||
for sublist in list {
|
||||
sort(sublist);
|
||||
}
|
||||
@@ -379,6 +383,8 @@ pub fn default_mapping() -> Mapping {
|
||||
Mapping {
|
||||
key_up,
|
||||
key_down,
|
||||
key_up_no_repeat,
|
||||
key_down_no_repeat,
|
||||
double_click,
|
||||
wheel_scroll,
|
||||
pointer_move,
|
||||
|
||||
@@ -14,6 +14,12 @@ pub enum InputMapperMessage {
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
KeyUp(Key),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
KeyDownNoRepeat(Key),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
KeyUpNoRepeat(Key),
|
||||
|
||||
// Messages
|
||||
DoubleClick,
|
||||
|
||||
@@ -50,6 +50,16 @@ macro_rules! entry {
|
||||
input: InputMapperMessage::KeyUp(Key::$refresh),
|
||||
modifiers: modifiers!(),
|
||||
},
|
||||
MappingEntry {
|
||||
action: $action_dispatch.into(),
|
||||
input: InputMapperMessage::KeyDownNoRepeat(Key::$refresh),
|
||||
modifiers: modifiers!(),
|
||||
},
|
||||
MappingEntry {
|
||||
action: $action_dispatch.into(),
|
||||
input: InputMapperMessage::KeyUpNoRepeat(Key::$refresh),
|
||||
modifiers: modifiers!(),
|
||||
},
|
||||
)*
|
||||
)*
|
||||
]]
|
||||
@@ -65,6 +75,8 @@ macro_rules! mapping {
|
||||
[$($entry:expr),* $(,)?] => {{
|
||||
let mut key_up = KeyMappingEntries::key_array();
|
||||
let mut key_down = KeyMappingEntries::key_array();
|
||||
let mut key_up_no_repeat = KeyMappingEntries::key_array();
|
||||
let mut key_down_no_repeat = KeyMappingEntries::key_array();
|
||||
let mut double_click = KeyMappingEntries::new();
|
||||
let mut wheel_scroll = KeyMappingEntries::new();
|
||||
let mut pointer_move = KeyMappingEntries::new();
|
||||
@@ -77,6 +89,8 @@ macro_rules! mapping {
|
||||
let corresponding_list = match entry.input {
|
||||
InputMapperMessage::KeyDown(key) => &mut key_down[key as usize],
|
||||
InputMapperMessage::KeyUp(key) => &mut key_up[key as usize],
|
||||
InputMapperMessage::KeyDownNoRepeat(key) => &mut key_down_no_repeat[key as usize],
|
||||
InputMapperMessage::KeyUpNoRepeat(key) => &mut key_up_no_repeat[key as usize],
|
||||
InputMapperMessage::DoubleClick => &mut double_click,
|
||||
InputMapperMessage::WheelScroll => &mut wheel_scroll,
|
||||
InputMapperMessage::PointerMove => &mut pointer_move,
|
||||
@@ -87,7 +101,7 @@ macro_rules! mapping {
|
||||
}
|
||||
)*
|
||||
|
||||
(key_up, key_down, double_click, wheel_scroll, pointer_move)
|
||||
(key_up, key_down, key_up_no_repeat, key_down_no_repeat, double_click, wheel_scroll, pointer_move)
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ use serde::{Deserialize, Serialize};
|
||||
pub struct Mapping {
|
||||
pub key_up: [KeyMappingEntries; NUMBER_OF_KEYS],
|
||||
pub key_down: [KeyMappingEntries; NUMBER_OF_KEYS],
|
||||
pub key_up_no_repeat: [KeyMappingEntries; NUMBER_OF_KEYS],
|
||||
pub key_down_no_repeat: [KeyMappingEntries; NUMBER_OF_KEYS],
|
||||
pub double_click: KeyMappingEntries,
|
||||
pub wheel_scroll: KeyMappingEntries,
|
||||
pub pointer_move: KeyMappingEntries,
|
||||
@@ -40,6 +42,8 @@ impl Mapping {
|
||||
match message {
|
||||
InputMapperMessage::KeyDown(key) => &self.key_down[*key as usize],
|
||||
InputMapperMessage::KeyUp(key) => &self.key_up[*key as usize],
|
||||
InputMapperMessage::KeyDownNoRepeat(key) => &self.key_down_no_repeat[*key as usize],
|
||||
InputMapperMessage::KeyUpNoRepeat(key) => &self.key_up_no_repeat[*key as usize],
|
||||
InputMapperMessage::DoubleClick => &self.double_click,
|
||||
InputMapperMessage::WheelScroll => &self.wheel_scroll,
|
||||
InputMapperMessage::PointerMove => &self.pointer_move,
|
||||
@@ -50,6 +54,8 @@ impl Mapping {
|
||||
match message {
|
||||
InputMapperMessage::KeyDown(key) => &mut self.key_down[*key as usize],
|
||||
InputMapperMessage::KeyUp(key) => &mut self.key_up[*key as usize],
|
||||
InputMapperMessage::KeyDownNoRepeat(key) => &mut self.key_down_no_repeat[*key as usize],
|
||||
InputMapperMessage::KeyUpNoRepeat(key) => &mut self.key_up_no_repeat[*key as usize],
|
||||
InputMapperMessage::DoubleClick => &mut self.double_click,
|
||||
InputMapperMessage::WheelScroll => &mut self.wheel_scroll,
|
||||
InputMapperMessage::PointerMove => &mut self.pointer_move,
|
||||
|
||||
@@ -12,8 +12,8 @@ use serde::{Deserialize, Serialize};
|
||||
pub enum InputPreprocessorMessage {
|
||||
BoundsOfViewports { bounds_of_viewports: Vec<ViewportBounds> },
|
||||
DoubleClick { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
|
||||
KeyDown { key: Key, modifier_keys: ModifierKeys },
|
||||
KeyUp { key: Key, modifier_keys: ModifierKeys },
|
||||
KeyDown { key: Key, key_repeat: bool, modifier_keys: ModifierKeys },
|
||||
KeyUp { key: Key, key_repeat: bool, modifier_keys: ModifierKeys },
|
||||
PointerDown { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
|
||||
PointerMove { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
|
||||
PointerUp { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
|
||||
|
||||
@@ -39,14 +39,20 @@ impl MessageHandler<InputPreprocessorMessage, KeyboardPlatformLayout> for InputP
|
||||
|
||||
responses.add(InputMapperMessage::DoubleClick);
|
||||
}
|
||||
InputPreprocessorMessage::KeyDown { key, modifier_keys } => {
|
||||
InputPreprocessorMessage::KeyDown { key, key_repeat, modifier_keys } => {
|
||||
self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses);
|
||||
self.keyboard.set(key as usize);
|
||||
if !key_repeat {
|
||||
responses.add(InputMapperMessage::KeyDownNoRepeat(key));
|
||||
}
|
||||
responses.add(InputMapperMessage::KeyDown(key));
|
||||
}
|
||||
InputPreprocessorMessage::KeyUp { key, modifier_keys } => {
|
||||
InputPreprocessorMessage::KeyUp { key, key_repeat, modifier_keys } => {
|
||||
self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses);
|
||||
self.keyboard.unset(key as usize);
|
||||
if !key_repeat {
|
||||
responses.add(InputMapperMessage::KeyUpNoRepeat(key));
|
||||
}
|
||||
responses.add(InputMapperMessage::KeyUp(key));
|
||||
}
|
||||
InputPreprocessorMessage::PointerDown { editor_mouse_state, modifier_keys } => {
|
||||
@@ -218,8 +224,9 @@ mod test {
|
||||
input_preprocessor.keyboard.set(Key::Control as usize);
|
||||
|
||||
let key = Key::KeyA;
|
||||
let key_repeat = false;
|
||||
let modifier_keys = ModifierKeys::empty();
|
||||
let message = InputPreprocessorMessage::KeyDown { key, modifier_keys };
|
||||
let message = InputPreprocessorMessage::KeyDown { key, key_repeat, modifier_keys };
|
||||
|
||||
let mut responses = VecDeque::new();
|
||||
|
||||
@@ -234,8 +241,9 @@ mod test {
|
||||
let mut input_preprocessor = InputPreprocessorMessageHandler::default();
|
||||
|
||||
let key = Key::KeyS;
|
||||
let key_repeat = false;
|
||||
let modifier_keys = ModifierKeys::CONTROL | ModifierKeys::SHIFT;
|
||||
let message = InputPreprocessorMessage::KeyUp { key, modifier_keys };
|
||||
let message = InputPreprocessorMessage::KeyUp { key, key_repeat, modifier_keys };
|
||||
|
||||
let mut responses = VecDeque::new();
|
||||
|
||||
|
||||
@@ -291,6 +291,7 @@ impl LayoutMessageHandler {
|
||||
LayoutTarget::DialogDetails => FrontendMessage::UpdateDialogDetails { 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::LayerTreeOptions => FrontendMessage::UpdateLayerTreeOptionsLayout { layout_target, diff },
|
||||
LayoutTarget::MenuBar => unreachable!("Menu bar is not diffed"),
|
||||
LayoutTarget::NodeGraphBar => FrontendMessage::UpdateNodeGraphBarLayout { layout_target, diff },
|
||||
|
||||
@@ -21,11 +21,13 @@ 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.
|
||||
LayerTreeOptions,
|
||||
/// The dropdown menu at the very top of the application: File, Edit, etc.
|
||||
MenuBar,
|
||||
/// Bar at the top of the node graph containing the location and the 'preview' and 'hide' buttons.
|
||||
/// Bar at the top of the node graph containing the location and the "Preview" and "Hide" buttons.
|
||||
NodeGraphBar,
|
||||
/// The bar at the top of the Properties panel containing the layer name and icon.
|
||||
PropertiesOptions,
|
||||
|
||||
@@ -233,6 +233,9 @@ impl MessageHandler<NavigationMessage, (&Document, Option<[DVec2; 2]>, &InputPre
|
||||
TranslateCanvasBegin => {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Grabbing });
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data: HintData(Vec::new()) });
|
||||
// Because the pan key shares the Spacebar with toggling the graph view overlay, now that we've begun panning,
|
||||
// we need to prevent the graph view overlay from toggling when the Spacebar is released.
|
||||
responses.add(PortfolioMessage::GraphViewOverlayToggleDisabled { disabled: true });
|
||||
|
||||
self.panning = true;
|
||||
self.mouse_position = ipp.mouse.position;
|
||||
|
||||
@@ -54,6 +54,13 @@ pub enum PortfolioMessage {
|
||||
data: Vec<u8>,
|
||||
is_default: bool,
|
||||
},
|
||||
GraphViewOverlay {
|
||||
open: bool,
|
||||
},
|
||||
GraphViewOverlayToggle,
|
||||
GraphViewOverlayToggleDisabled {
|
||||
disabled: bool,
|
||||
},
|
||||
ImaginateCheckServerStatus,
|
||||
ImaginatePollServerStatus,
|
||||
ImaginatePreferences,
|
||||
|
||||
@@ -3,6 +3,7 @@ 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::prelude::*;
|
||||
@@ -24,10 +25,12 @@ pub struct PortfolioMessageHandler {
|
||||
menu_bar_message_handler: MenuBarMessageHandler,
|
||||
documents: HashMap<u64, DocumentMessageHandler>,
|
||||
document_ids: Vec<u64>,
|
||||
pub executor: NodeGraphExecutor,
|
||||
active_document_id: Option<u64>,
|
||||
graph_view_overlay_open: bool,
|
||||
graph_view_overlay_toggle_disabled: bool,
|
||||
copy_buffer: [Vec<CopyBufferEntry>; INTERNAL_CLIPBOARD_COUNT as usize],
|
||||
pub persistent_data: PersistentData,
|
||||
pub executor: NodeGraphExecutor,
|
||||
}
|
||||
|
||||
impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &PreferencesMessageHandler)> for PortfolioMessageHandler {
|
||||
@@ -220,6 +223,31 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
||||
self.persistent_data.font_cache.insert(font, preview_url, data, is_default);
|
||||
self.executor.update_font_cache(self.persistent_data.font_cache.clone());
|
||||
}
|
||||
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,
|
||||
});
|
||||
|
||||
responses.add(FrontendMessage::TriggerGraphViewOverlay { open });
|
||||
}
|
||||
PortfolioMessage::GraphViewOverlayToggle => {
|
||||
if !self.graph_view_overlay_toggle_disabled {
|
||||
responses.add(PortfolioMessage::GraphViewOverlay { open: !self.graph_view_overlay_open });
|
||||
}
|
||||
}
|
||||
PortfolioMessage::GraphViewOverlayToggleDisabled { disabled } => {
|
||||
self.graph_view_overlay_toggle_disabled = disabled;
|
||||
}
|
||||
PortfolioMessage::ImaginateCheckServerStatus => {
|
||||
let server_status = self.persistent_data.imaginate.server_status().clone();
|
||||
self.persistent_data.imaginate.poll_server_check();
|
||||
@@ -519,6 +547,8 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
||||
|
||||
fn actions(&self) -> ActionList {
|
||||
let mut common = actions!(PortfolioMessageDiscriminant;
|
||||
GraphViewOverlayToggle,
|
||||
GraphViewOverlayToggleDisabled,
|
||||
CloseActiveDocumentWithConfirmation,
|
||||
CloseAllDocuments,
|
||||
Import,
|
||||
@@ -618,6 +648,7 @@ 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(PropertiesPanelMessage::Init);
|
||||
responses.add(NavigationMessage::TranslateCanvas { delta: (0., 0.).into() });
|
||||
|
||||
@@ -194,13 +194,13 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, u64, &InputPreprocess
|
||||
document_data.primary_color = Color::BLACK;
|
||||
document_data.secondary_color = Color::WHITE;
|
||||
|
||||
document_data.update_working_colors(responses);
|
||||
document_data.update_working_colors(responses); // TODO: Make this an event
|
||||
}
|
||||
ToolMessage::SelectPrimaryColor { color } => {
|
||||
let document_data = &mut self.tool_state.document_tool_data;
|
||||
document_data.primary_color = color;
|
||||
|
||||
self.tool_state.document_tool_data.update_working_colors(responses);
|
||||
self.tool_state.document_tool_data.update_working_colors(responses); // TODO: Make this an event
|
||||
}
|
||||
ToolMessage::SelectRandomPrimaryColor => {
|
||||
// Select a random primary color (rgba) based on an UUID
|
||||
@@ -213,20 +213,20 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, u64, &InputPreprocess
|
||||
let random_color = Color::from_rgba8_srgb(r, g, b, 255);
|
||||
document_data.primary_color = random_color;
|
||||
|
||||
document_data.update_working_colors(responses);
|
||||
document_data.update_working_colors(responses); // TODO: Make this an event
|
||||
}
|
||||
ToolMessage::SelectSecondaryColor { color } => {
|
||||
let document_data = &mut self.tool_state.document_tool_data;
|
||||
document_data.secondary_color = color;
|
||||
|
||||
document_data.update_working_colors(responses);
|
||||
document_data.update_working_colors(responses); // TODO: Make this an event
|
||||
}
|
||||
ToolMessage::SwapColors => {
|
||||
let document_data = &mut self.tool_state.document_tool_data;
|
||||
|
||||
std::mem::swap(&mut document_data.primary_color, &mut document_data.secondary_color);
|
||||
|
||||
document_data.update_working_colors(responses);
|
||||
document_data.update_working_colors(responses); // TODO: Make this an event
|
||||
}
|
||||
|
||||
// Sub-messages
|
||||
|
||||
Reference in New Issue
Block a user