mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-21 06:48:13 +08:00
Major overhaul of input and communication systems
* Add input manager * WIP lifetime hell * Hell yeah, dark lifetime magic * Replace events with actions in tools * Fix borrow in GlobalEventHandler * Fix typo in response-handler * Distribute dispatch structure * Add translation from events to actions * Port default key actions to input_mapper * Split actions macro * Add handling for Ambiguous Mouse events * Fix warnings and clippy lints * Add actions macro * WIP rework * Add AsMessage macro * Add implementation for derived enums * Add macro implementation for top level message * Add #[child] attribute to indicate derivation * Replace some mentions of Actions and Responses with Message * It compiles !!! * Add functionality to some message handlers * Add document rendering * ICE * Rework the previous code while keeping basic functionality * Reduce parent-top-level macro args to only two * Add workaround for ICE * Fix cyclic reference in document.rs * Make derive_transitive_child a bit more powerful This addresses the todo that was left, enabling arbitrary expressions to be passed as the last parameter of a #[parent] attribute * Adapt frontend message format * Make responses use VecDeque Our responses are a queue so we should use a queue type for them * Move traits to sensible location * Are we rectangle yet? * Simplify, improve & document `derive_discriminant` * Change `child` to `sub_discriminant` This only applies to `ToDiscriminant`. Code using `#[impl_message]` continues to work. * Add docs for `derive_transitive_child` * Finish docs and improve macros The improvements are that impl_message now uses trait resolution to obtain the parent's discriminant and that derive_as_message now allows for non-unit variants (which we don't use but it's nice to have, just in case) * Remove logging call * Move files around and cleanup structure * Fix proc macro doc tests * Improve actions_fn!() macro * Add ellipse tool * Pass populated actions list to the input mapper * Add KeyState bitvector * Merge mouse buttons into "keyboard" * Add macro for initialization of key mapper table * Add syntactic sugar for the macro * Implement mapping function * Translate the remaining tools * Fix shape tool * Add keybindings for line and pen tool * Fix modifiers * Cleanup * Add doc comments for the actions macro * Fix formatting * Rename MouseMove to PointerMove * Add keybinds for tools * Apply review suggestions * Rename KeyMappings -> KeyMappingEntries * Apply review changes Co-authored-by: T0mstone <realt0mstone@gmail.com> Co-authored-by: Paul Kupper <kupper.pa@gmail.com>
This commit is contained in:
co-authored by
T0mstone
Paul Kupper
parent
56c1110800
commit
a596ce0104
@@ -0,0 +1,18 @@
|
||||
//! Traits that can be derived using macros from `graphite-proc-macros`
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub trait Hint {
|
||||
fn hints(&self) -> HashMap<String, String>;
|
||||
}
|
||||
|
||||
pub trait ToDiscriminant {
|
||||
type Discriminant;
|
||||
|
||||
fn to_discriminant(&self) -> Self::Discriminant;
|
||||
}
|
||||
|
||||
pub trait TransitiveChild: Into<Self::Parent> + Into<Self::TopParent> {
|
||||
type TopParent;
|
||||
type Parent;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
use crate::Color;
|
||||
use document_core::DocumentError;
|
||||
use thiserror::Error;
|
||||
|
||||
/// The error type used by the Graphite editor.
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum EditorError {
|
||||
#[error("Failed to execute operation: {0}")]
|
||||
InvalidOperation(String),
|
||||
#[error("{0}")]
|
||||
Misc(String),
|
||||
#[error("Tried to construct an invalid color {0:?}")]
|
||||
Color(String),
|
||||
#[error("The requested tool does not exist")]
|
||||
UnknownTool,
|
||||
#[error("The operation caused a document error {0:?}")]
|
||||
Document(String),
|
||||
}
|
||||
|
||||
macro_rules! derive_from {
|
||||
($type:ty, $kind:ident) => {
|
||||
impl From<$type> for EditorError {
|
||||
fn from(error: $type) -> Self {
|
||||
EditorError::$kind(format!("{:?}", error))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
derive_from!(&str, Misc);
|
||||
derive_from!(String, Misc);
|
||||
derive_from!(Color, Color);
|
||||
derive_from!(DocumentError, Document);
|
||||
@@ -0,0 +1,138 @@
|
||||
/// Counts args in the macro invocation by adding `+ 1` for every arg.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// let x = count_args!(("example1"), (10), (25));
|
||||
/// assert_eq!(x, 3);
|
||||
/// ```
|
||||
/// expands to
|
||||
/// ```ignore
|
||||
/// let x = 0 + 1 + 1 + 1;
|
||||
/// assert_eq!(x, 3);
|
||||
/// ```
|
||||
macro_rules! count_args {
|
||||
(@one $($t:tt)*) => { 1 };
|
||||
($(($($x:tt)*)),*$(,)?) => {
|
||||
0 $(+ count_args!(@one $($x)*))*
|
||||
};
|
||||
}
|
||||
|
||||
/// Generates a [`std::collections::HashMap`] for `ToolState`'s `tools` variable.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// let tools = gen_tools_hash_map! {
|
||||
/// Select => select::Select,
|
||||
/// Crop => crop::Crop,
|
||||
/// };
|
||||
/// ```
|
||||
/// expands to
|
||||
/// ```ignore
|
||||
/// let tools = {
|
||||
/// let mut hash_map: std::collections::HashMap<crate::tool::ToolType, Box<dyn crate::tool::Tool>> = std::collections::HashMap::with_capacity(count_args!(/* Macro args */));
|
||||
///
|
||||
/// hash_map.insert(crate::tool::ToolType::Select, Box::new(select::Select::default()));
|
||||
/// hash_map.insert(crate::tool::ToolType::Crop, Box::new(crop::Crop::default()));
|
||||
///
|
||||
/// hash_map
|
||||
/// };
|
||||
/// ```
|
||||
macro_rules! gen_tools_hash_map {
|
||||
($($enum_variant:ident => $struct_path:ty),* $(,)?) => {{
|
||||
let mut hash_map: ::std::collections::HashMap<$crate::tool::ToolType, ::std::boxed::Box<dyn for<'a> $crate::message_prelude::MessageHandler<$crate::tool::tool_messages::ToolMessage,$crate::tool::ToolActionHandlerData<'a>>>> = ::std::collections::HashMap::with_capacity(count_args!($(($enum_variant)),*));
|
||||
$(hash_map.insert($crate::tool::ToolType::$enum_variant, ::std::boxed::Box::new(<$struct_path>::default()));)*
|
||||
|
||||
hash_map
|
||||
}};
|
||||
}
|
||||
|
||||
/// Creates a string representation of an enum value that exactly matches the given name of each enum variant
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// enum E {
|
||||
/// A(u8),
|
||||
/// B
|
||||
/// }
|
||||
///
|
||||
/// // this line is important
|
||||
/// use E::*;
|
||||
///
|
||||
/// let a = E::A(7);
|
||||
/// let s = match_variant_name!(match (a) { A, B });
|
||||
/// ```
|
||||
///
|
||||
/// expands to
|
||||
///
|
||||
/// ```ignore
|
||||
/// // ...
|
||||
///
|
||||
/// let s = match a {
|
||||
/// A { .. } => "A",
|
||||
/// B { .. } => "B"
|
||||
/// };
|
||||
/// ```
|
||||
macro_rules! match_variant_name {
|
||||
(match ($e:expr) { $($v:ident),* $(,)? }) => {
|
||||
match $e {
|
||||
$(
|
||||
$v { .. } => stringify!($v)
|
||||
),*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Syntax sugar for initializing an `ActionList`
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// actions!(DocumentMessage::Undo, DocumentMessage::Redo);
|
||||
/// ```
|
||||
///
|
||||
/// expands to:
|
||||
/// ```ignore
|
||||
/// vec![vec![DocumentMessage::Undo, DocumentMessage::Redo]];
|
||||
/// ```
|
||||
///
|
||||
/// and
|
||||
/// ```ignore
|
||||
/// actions!(DocumentMessage; Undo, Redo);
|
||||
/// ```
|
||||
///
|
||||
/// expands to:
|
||||
/// ```ignore
|
||||
/// vec![vec![DocumentMessage::Undo, DocumentMessage::Redo]];
|
||||
/// ```
|
||||
///
|
||||
macro_rules! actions {
|
||||
($($v:expr),* $(,)?) => {{
|
||||
vec![$(vec![$v.into()]),*]
|
||||
}};
|
||||
($name:ident; $($v:ident),* $(,)?) => {{
|
||||
vec![vec![$(($name::$v).into()),*]]
|
||||
}};
|
||||
}
|
||||
|
||||
/// Does the same thing as the `actions!` macro but wraps everything in:
|
||||
///
|
||||
/// ```ignore
|
||||
/// fn actions(&self) -> ActionList {
|
||||
/// actions!(…)
|
||||
/// }
|
||||
/// ```
|
||||
macro_rules! advertise_actions {
|
||||
($($v:expr),* $(,)?) => {
|
||||
fn actions(&self) -> $crate::communication::ActionList {
|
||||
actions!($($v),*)
|
||||
}
|
||||
};
|
||||
($name:ident; $($v:ident),* $(,)?) => {
|
||||
fn actions(&self) -> $crate::communication::ActionList {
|
||||
actions!($name; $($v),*)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub mod derivable_custom_traits;
|
||||
mod error;
|
||||
|
||||
pub use error::EditorError;
|
||||
pub use macros::*;
|
||||
Reference in New Issue
Block a user