mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-21 21:28:11 +08:00
Add plumbing for event system (#52)
* Add plumbing for event system * Apply review suggestions * Add swap and reset color functions
This commit is contained in:
@@ -1,12 +1,21 @@
|
||||
use crate::tools::ToolType;
|
||||
use crate::Color;
|
||||
use bitflags::bitflags;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum Event {
|
||||
SelectTool(ToolType),
|
||||
ModifierKeyDown(ModKey),
|
||||
ModifierKeyUp(ModKey),
|
||||
MouseMovement(Trace),
|
||||
Click(MouseState),
|
||||
SelectPrimaryColor(Color),
|
||||
SelectSecondaryColor(Color),
|
||||
SwapColors,
|
||||
ResetColors,
|
||||
MouseDown(MouseState),
|
||||
MouseUp(MouseState),
|
||||
MouseMovement(CanvasPosition),
|
||||
ModifierKeyDown(ModKeys),
|
||||
ModifierKeyUp(ModKeys),
|
||||
KeyPress(Key),
|
||||
}
|
||||
|
||||
@@ -17,92 +26,81 @@ pub enum Response {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Trace(Vec<MouseState>);
|
||||
pub struct Trace(Vec<TracePoint>);
|
||||
|
||||
impl Deref for Trace {
|
||||
type Target = Vec<TracePoint>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Trace {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Trace {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
pub fn first_point(&self) -> Option<&MouseState> {
|
||||
self.0.first()
|
||||
}
|
||||
pub fn last_point(&self) -> Option<&MouseState> {
|
||||
self.0.last()
|
||||
}
|
||||
pub fn append_point(&mut self, x: u32, y: u32) {
|
||||
self.0.push(MouseState::from_pos(x, y))
|
||||
}
|
||||
pub fn clear(&mut self) {
|
||||
self.0.clear()
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
||||
// origin is top left
|
||||
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
|
||||
pub struct CanvasPosition {
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
|
||||
pub struct TracePoint {
|
||||
pub mouse_state: MouseState,
|
||||
pub mod_keys: ModKeys,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
|
||||
pub struct MouseState {
|
||||
x: u32,
|
||||
y: u32,
|
||||
mod_keys: ModKeysStorage,
|
||||
mouse_keys: MouseKeysStorage,
|
||||
pub position: CanvasPosition,
|
||||
pub mouse_keys: MouseKeys,
|
||||
}
|
||||
|
||||
impl MouseState {
|
||||
pub const fn new() -> MouseState {
|
||||
pub fn new() -> MouseState {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn from_pos(x: u32, y: u32) -> MouseState {
|
||||
MouseState {
|
||||
x: 0,
|
||||
y: 0,
|
||||
mod_keys: 0,
|
||||
mouse_keys: 0,
|
||||
position: CanvasPosition { x, y },
|
||||
mouse_keys: MouseKeys::default(),
|
||||
}
|
||||
}
|
||||
pub const fn from_pos(x: u32, y: u32) -> MouseState {
|
||||
MouseState { x, y, mod_keys: 0, mouse_keys: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum Key {
|
||||
None,
|
||||
UnknownKey,
|
||||
}
|
||||
|
||||
pub type ModKeysStorage = u8;
|
||||
pub type MouseKeysStorage = u8;
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
pub struct ModKeys(ModKeysStorage);
|
||||
|
||||
impl ModKeys {
|
||||
pub fn get_key(&self, key: ModKey) -> bool {
|
||||
key as ModKeysStorage & self.0 > 0
|
||||
}
|
||||
pub fn set_key(&mut self, key: ModKey) {
|
||||
self.0 |= key as ModKeysStorage
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct ModKeys: u8 {
|
||||
const CONTROL = 0b0000_0001;
|
||||
const SHIFT = 0b0000_0010;
|
||||
const ALT = 0b0000_0100;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
struct MouseKeys(u8);
|
||||
|
||||
impl MouseKeys {
|
||||
pub fn get_key(&self, key: MouseKey) -> bool {
|
||||
key as ModKeysStorage & self.0 > 0
|
||||
}
|
||||
pub fn set_key(&mut self, key: MouseKey) {
|
||||
self.0 |= key as MouseKeysStorage
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct MouseKeys: u8 {
|
||||
const LEFT = 0b0000_0001;
|
||||
const RIGHT = 0b0000_0010;
|
||||
const MIDDLE = 0b0000_0100;
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ModKey {
|
||||
Control = 1,
|
||||
Shift = 2,
|
||||
Alt = 4,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MouseKey {
|
||||
LeftMouse = 1,
|
||||
RightMouse = 2,
|
||||
MiddleMouse = 4,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod events;
|
||||
use crate::EditorError;
|
||||
use crate::tools::ToolState;
|
||||
use crate::{Color, EditorError};
|
||||
use events::{Event, Response};
|
||||
|
||||
pub type Callback = Box<dyn Fn(Response)>;
|
||||
@@ -8,10 +9,63 @@ pub struct Dispatcher {
|
||||
}
|
||||
|
||||
impl Dispatcher {
|
||||
pub fn handle_event(&self, event: Event) -> Result<(), EditorError> {
|
||||
pub fn handle_event(&self, tool_state: &mut ToolState, event: Event) -> Result<(), EditorError> {
|
||||
match event {
|
||||
Event::Click(_) => Ok(self.emit_response(Response::UpdateCanvas)),
|
||||
_ => todo!(),
|
||||
Event::SelectTool(tool_type) => {
|
||||
tool_state.active_tool = tool_type;
|
||||
Ok(())
|
||||
}
|
||||
Event::SelectPrimaryColor(color) => {
|
||||
tool_state.primary_color = color;
|
||||
Ok(())
|
||||
}
|
||||
Event::SelectSecondaryColor(color) => {
|
||||
tool_state.secondary_color = color;
|
||||
Ok(())
|
||||
}
|
||||
Event::SwapColors => {
|
||||
std::mem::swap(&mut tool_state.primary_color, &mut tool_state.secondary_color);
|
||||
Ok(())
|
||||
}
|
||||
Event::ResetColors => {
|
||||
tool_state.primary_color = Color::BLACK;
|
||||
tool_state.secondary_color = Color::WHITE;
|
||||
Ok(())
|
||||
}
|
||||
Event::MouseDown(mouse_state) => {
|
||||
tool_state.mouse_state = mouse_state;
|
||||
// the state has changed so we add a trace point
|
||||
tool_state.record_trace_point();
|
||||
|
||||
self.emit_response(Response::UpdateCanvas);
|
||||
Ok(())
|
||||
}
|
||||
Event::MouseUp(mouse_state) => {
|
||||
tool_state.mouse_state = mouse_state;
|
||||
// the state has changed so we add a trace point
|
||||
tool_state.record_trace_point();
|
||||
|
||||
self.emit_response(Response::UpdateCanvas);
|
||||
Ok(())
|
||||
}
|
||||
Event::MouseMovement(pos) => {
|
||||
tool_state.mouse_state.position = pos;
|
||||
tool_state.record_trace_point();
|
||||
Ok(())
|
||||
}
|
||||
Event::ModifierKeyDown(mod_keys) => {
|
||||
tool_state.mod_keys = mod_keys;
|
||||
// the state has changed so we add a trace point
|
||||
tool_state.record_trace_point();
|
||||
Ok(())
|
||||
}
|
||||
Event::ModifierKeyUp(mod_keys) => {
|
||||
tool_state.mod_keys = mod_keys;
|
||||
// the state has changed so we add a trace point
|
||||
tool_state.record_trace_point();
|
||||
Ok(())
|
||||
}
|
||||
Event::KeyPress(key) => todo!(),
|
||||
}
|
||||
}
|
||||
pub fn emit_response(&self, response: Response) {
|
||||
|
||||
@@ -22,7 +22,7 @@ use workspace::Workspace;
|
||||
|
||||
// TODO: serialize with serde to save the current editor state
|
||||
pub struct Editor {
|
||||
pub tools: ToolState,
|
||||
tools: ToolState,
|
||||
workspace: Workspace,
|
||||
dispatcher: Dispatcher,
|
||||
}
|
||||
@@ -36,6 +36,6 @@ impl Editor {
|
||||
}
|
||||
}
|
||||
pub fn handle_event(&mut self, event: events::Event) -> Result<(), EditorError> {
|
||||
self.dispatcher.handle_event(event)
|
||||
self.dispatcher.handle_event(&mut self.tools, event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use crate::events::{ModKeys, MouseState, TracePoint};
|
||||
use crate::{events::Trace, Color};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct ToolState {
|
||||
pub mouse_is_clicked: bool,
|
||||
pub mouse_state: MouseState,
|
||||
pub mod_keys: ModKeys,
|
||||
pub trace: Trace,
|
||||
pub primary_color: Color,
|
||||
pub secondary_color: Color,
|
||||
@@ -10,10 +12,11 @@ pub struct ToolState {
|
||||
tool_settings: HashMap<ToolType, ToolSettings>,
|
||||
}
|
||||
|
||||
impl ToolState {
|
||||
pub fn new() -> Self {
|
||||
impl Default for ToolState {
|
||||
fn default() -> Self {
|
||||
ToolState {
|
||||
mouse_is_clicked: false,
|
||||
mouse_state: MouseState::default(),
|
||||
mod_keys: ModKeys::default(),
|
||||
trace: Trace::new(),
|
||||
primary_color: Color::BLACK,
|
||||
secondary_color: Color::WHITE,
|
||||
@@ -23,14 +26,29 @@ impl ToolState {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToolState {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn record_trace_point(&mut self) {
|
||||
self.trace.push(TracePoint {
|
||||
mouse_state: self.mouse_state,
|
||||
mod_keys: self.mod_keys,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn default_tool_settings() -> HashMap<ToolType, ToolSettings> {
|
||||
let tool_init = |tool: &ToolType| (*tool, tool.default_settings());
|
||||
// TODO: when 1.51 is more common, change this to use array::IntoIter
|
||||
[
|
||||
tool_init(&ToolType::Select),
|
||||
tool_init(&ToolType::Ellipse),
|
||||
tool_init(&ToolType::Shape), // TODO: Add more tool defaults
|
||||
]
|
||||
.iter()
|
||||
.cloned()
|
||||
.copied()
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -54,6 +72,7 @@ impl ToolType {
|
||||
fn default_settings(&self) -> ToolSettings {
|
||||
match self {
|
||||
ToolType::Select => ToolSettings::Select { append_mode: SelectAppendMode::New },
|
||||
ToolType::Ellipse => ToolSettings::Ellipse,
|
||||
ToolType::Shape => ToolSettings::Shape {
|
||||
shape: Shape::Polygon { vertices: 3 },
|
||||
},
|
||||
@@ -62,13 +81,14 @@ impl ToolType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum ToolSettings {
|
||||
Select { append_mode: SelectAppendMode },
|
||||
Ellipse,
|
||||
Shape { shape: Shape },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum SelectAppendMode {
|
||||
New,
|
||||
Add,
|
||||
@@ -76,7 +96,7 @@ pub enum SelectAppendMode {
|
||||
Intersect,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum Shape {
|
||||
Star { vertices: u32 },
|
||||
Polygon { vertices: u32 },
|
||||
|
||||
Reference in New Issue
Block a user