mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-02 04:48:12 +08:00
Implement backend part of the layer selection (#172)
* Implement backend part of the layer selection
This commit is contained in:
@@ -104,11 +104,12 @@ pub fn export_document() -> Result<(), JsValue> {
|
|||||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::ExportDocument)).map_err(convert_error)
|
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::ExportDocument)).map_err(convert_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Select a layer from the layer list
|
/// Update the list of selected layers. The layer paths have to be stored in one array and are separated by LayerId::MAX
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn select_layer(path: Vec<LayerId>) -> Result<(), JsValue> {
|
pub fn select_layers(paths: Vec<LayerId>) -> Result<(), JsValue> {
|
||||||
|
let paths = paths.split(|id| *id == LayerId::MAX).map(|path| path.to_vec()).collect();
|
||||||
EDITOR_STATE
|
EDITOR_STATE
|
||||||
.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::SelectLayer(path)))
|
.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::SelectLayers(paths)))
|
||||||
.map_err(convert_error)
|
.map_err(convert_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
layers::{self, Folder, Layer, LayerData, LayerDataTypes, Line, PolyLine, Rect, Shape},
|
layers::{self, Folder, Layer, LayerData, LayerDataTypes, Line, PolyLine, Rect, Shape},
|
||||||
response::LayerPanelEntry,
|
|
||||||
DocumentError, DocumentResponse, LayerId, Operation,
|
DocumentError, DocumentResponse, LayerId, Operation,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -168,19 +167,6 @@ impl Document {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of `LayerPanelEntry`s intended for display purposes. These don't contain
|
|
||||||
/// any actual data, but rather metadata such as visibility and names of the layers.
|
|
||||||
pub fn layer_panel(&self, path: &[LayerId]) -> Result<Vec<LayerPanelEntry>, DocumentError> {
|
|
||||||
let folder = self.document_folder(path)?;
|
|
||||||
let entries = folder
|
|
||||||
.layers()
|
|
||||||
.iter()
|
|
||||||
.zip(folder.layer_ids.iter())
|
|
||||||
.map(|(layer, id)| LayerPanelEntry::from_layer(layer, [path, &[*id]].concat()))
|
|
||||||
.collect();
|
|
||||||
Ok(entries)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutate the document by applying the `operation` to it. If the operation necessitates a
|
/// Mutate the document by applying the `operation` to it. If the operation necessitates a
|
||||||
/// reaction from the frontend, responses may be returned.
|
/// reaction from the frontend, responses may be returned.
|
||||||
pub fn handle_operation(&mut self, operation: Operation) -> Result<Option<Vec<DocumentResponse>>, DocumentError> {
|
pub fn handle_operation(&mut self, operation: Operation) -> Result<Option<Vec<DocumentResponse>>, DocumentError> {
|
||||||
@@ -255,14 +241,12 @@ impl Document {
|
|||||||
self.delete(&path)?;
|
self.delete(&path)?;
|
||||||
|
|
||||||
let (path, _) = split_path(path.as_slice()).unwrap_or_else(|_| (&[], 0));
|
let (path, _) = split_path(path.as_slice()).unwrap_or_else(|_| (&[], 0));
|
||||||
let children = self.layer_panel(path)?;
|
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path: path.to_vec() }])
|
||||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::ExpandFolder { path: path.to_vec(), children }])
|
|
||||||
}
|
}
|
||||||
Operation::AddFolder { path } => {
|
Operation::AddFolder { path } => {
|
||||||
self.set_layer(&path, Layer::new(LayerDataTypes::Folder(Folder::default())))?;
|
self.set_layer(&path, Layer::new(LayerDataTypes::Folder(Folder::default())))?;
|
||||||
|
|
||||||
let children = self.layer_panel(path.as_slice())?;
|
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path: path.clone() }])
|
||||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::ExpandFolder { path: path.clone(), children }])
|
|
||||||
}
|
}
|
||||||
Operation::MountWorkingFolder { path } => {
|
Operation::MountWorkingFolder { path } => {
|
||||||
self.work_mount_path = path.clone();
|
self.work_mount_path = path.clone();
|
||||||
@@ -298,17 +282,15 @@ impl Document {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let children = self.layer_panel(path.as_slice())?;
|
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path }])
|
||||||
// TODO: Return `responses` and add deduplication in the future
|
|
||||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::ExpandFolder { path, children }])
|
|
||||||
}
|
}
|
||||||
Operation::ToggleVisibility { path } => {
|
Operation::ToggleVisibility { path } => {
|
||||||
let _ = self.layer_mut(&path).map(|layer| {
|
let _ = self.layer_mut(&path).map(|layer| {
|
||||||
layer.visible = !layer.visible;
|
layer.visible = !layer.visible;
|
||||||
layer.cache_dirty = true;
|
layer.cache_dirty = true;
|
||||||
});
|
});
|
||||||
let children = self.layer_panel(&path.as_slice()[..path.len() - 1])?;
|
let path = path.as_slice()[..path.len() - 1].to_vec();
|
||||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::ExpandFolder { path: vec![], children }])
|
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path }])
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !matches!(
|
if !matches!(
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ pub struct Folder {
|
|||||||
next_assignment_id: LayerId,
|
next_assignment_id: LayerId,
|
||||||
pub layer_ids: Vec<LayerId>,
|
pub layer_ids: Vec<LayerId>,
|
||||||
layers: Vec<Layer>,
|
layers: Vec<Layer>,
|
||||||
pub collapsed: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayerData for Folder {
|
impl LayerData for Folder {
|
||||||
@@ -88,7 +87,6 @@ impl Default for Folder {
|
|||||||
layer_ids: vec![],
|
layer_ids: vec![],
|
||||||
layers: vec![],
|
layers: vec![],
|
||||||
next_assignment_id: 0,
|
next_assignment_id: 0,
|
||||||
collapsed: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,91 +1,19 @@
|
|||||||
use crate::{
|
use crate::LayerId;
|
||||||
layers::{Layer, LayerDataTypes},
|
|
||||||
LayerId,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
|
||||||
pub struct LayerPanelEntry {
|
|
||||||
pub name: String,
|
|
||||||
pub visible: bool,
|
|
||||||
pub layer_type: LayerType,
|
|
||||||
pub collapsed: bool,
|
|
||||||
pub path: Vec<LayerId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
|
||||||
pub enum LayerType {
|
|
||||||
Folder,
|
|
||||||
Shape,
|
|
||||||
Circle,
|
|
||||||
Rect,
|
|
||||||
Line,
|
|
||||||
PolyLine,
|
|
||||||
Ellipse,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for LayerType {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
let name = match self {
|
|
||||||
LayerType::Folder => "Folder",
|
|
||||||
LayerType::Shape => "Shape",
|
|
||||||
LayerType::Rect => "Rectangle",
|
|
||||||
LayerType::Line => "Line",
|
|
||||||
LayerType::Circle => "Circle",
|
|
||||||
LayerType::PolyLine => "Polyline",
|
|
||||||
LayerType::Ellipse => "Ellipse",
|
|
||||||
};
|
|
||||||
|
|
||||||
formatter.write_str(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&LayerDataTypes> for LayerType {
|
|
||||||
fn from(data: &LayerDataTypes) -> Self {
|
|
||||||
use LayerDataTypes::*;
|
|
||||||
match data {
|
|
||||||
Folder(_) => LayerType::Folder,
|
|
||||||
Shape(_) => LayerType::Shape,
|
|
||||||
Circle(_) => LayerType::Circle,
|
|
||||||
Rect(_) => LayerType::Rect,
|
|
||||||
Line(_) => LayerType::Line,
|
|
||||||
PolyLine(_) => LayerType::PolyLine,
|
|
||||||
Ellipse(_) => LayerType::Ellipse,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LayerPanelEntry {
|
|
||||||
pub fn from_layer(layer: &Layer, path: Vec<LayerId>) -> Self {
|
|
||||||
let layer_type: LayerType = (&layer.data).into();
|
|
||||||
let name = layer.name.clone().unwrap_or_else(|| format!("Unnamed {}", layer_type));
|
|
||||||
let collapsed = if let LayerDataTypes::Folder(f) = &layer.data { f.collapsed } else { true };
|
|
||||||
Self {
|
|
||||||
name,
|
|
||||||
visible: layer.visible,
|
|
||||||
layer_type,
|
|
||||||
collapsed,
|
|
||||||
path,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
// TODO - Make Copy when possible
|
|
||||||
pub enum DocumentResponse {
|
pub enum DocumentResponse {
|
||||||
DocumentChanged,
|
DocumentChanged,
|
||||||
CollapseFolder { path: Vec<LayerId> },
|
FolderChanged { path: Vec<LayerId> },
|
||||||
ExpandFolder { path: Vec<LayerId>, children: Vec<LayerPanelEntry> },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for DocumentResponse {
|
impl fmt::Display for DocumentResponse {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let name = match self {
|
let name = match self {
|
||||||
DocumentResponse::DocumentChanged { .. } => "DocumentChanged",
|
DocumentResponse::DocumentChanged { .. } => "DocumentChanged",
|
||||||
DocumentResponse::CollapseFolder { .. } => "CollapseFolder",
|
DocumentResponse::FolderChanged { .. } => "FolderChanged",
|
||||||
DocumentResponse::ExpandFolder { .. } => "ExpandFolder",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
formatter.write_str(name)
|
formatter.write_str(name)
|
||||||
|
|||||||
@@ -1,7 +1,69 @@
|
|||||||
use document_core::document::Document as InteralDocument;
|
use crate::{frontend::layer_panel::*, EditorError};
|
||||||
|
use document_core::{document::Document as InteralDocument, layers::Layer, LayerId};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Document {
|
pub struct Document {
|
||||||
pub document: InteralDocument,
|
pub document: InteralDocument,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub layer_data: HashMap<Vec<LayerId>, LayerData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Document {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
document: InteralDocument::default(),
|
||||||
|
name: String::from("Unnamed Document"),
|
||||||
|
layer_data: vec![(vec![], LayerData { selected: false, expanded: true })].into_iter().collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layer_data<'a>(layer_data: &'a mut HashMap<Vec<LayerId>, LayerData>, path: &[LayerId]) -> &'a mut LayerData {
|
||||||
|
if !layer_data.contains_key(path) {
|
||||||
|
layer_data.insert(path.to_vec(), LayerData::default());
|
||||||
|
}
|
||||||
|
layer_data.get_mut(path).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn layer_panel_entry(layer_data: &mut LayerData, layer: &Layer, path: Vec<LayerId>) -> LayerPanelEntry {
|
||||||
|
let layer_type: LayerType = (&layer.data).into();
|
||||||
|
let name = layer.name.clone().unwrap_or_else(|| format!("Unnamed {}", layer_type));
|
||||||
|
LayerPanelEntry {
|
||||||
|
name,
|
||||||
|
visible: layer.visible,
|
||||||
|
layer_type,
|
||||||
|
layer_data: *layer_data,
|
||||||
|
path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Document {
|
||||||
|
pub fn layer_data(&mut self, path: &[LayerId]) -> &mut LayerData {
|
||||||
|
layer_data(&mut self.layer_data, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a list of `LayerPanelEntry`s intended for display purposes. These don't contain
|
||||||
|
/// any actual data, but rather metadata such as visibility and names of the layers.
|
||||||
|
pub fn layer_panel(&mut self, path: &[LayerId]) -> Result<Vec<LayerPanelEntry>, EditorError> {
|
||||||
|
let folder = self.document.document_folder(path)?;
|
||||||
|
let self_layer_data = &mut self.layer_data;
|
||||||
|
let entries = folder
|
||||||
|
.layers()
|
||||||
|
.iter()
|
||||||
|
.zip(folder.layer_ids.iter())
|
||||||
|
.map(|(layer, id)| {
|
||||||
|
let path = [path, &[*id]].concat();
|
||||||
|
layer_panel_entry(layer_data(self_layer_data, &path), layer, path)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Ok(entries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Copy, Default)]
|
||||||
|
pub struct LayerData {
|
||||||
|
pub selected: bool,
|
||||||
|
pub expanded: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::collections::VecDeque;
|
|||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub enum DocumentMessage {
|
pub enum DocumentMessage {
|
||||||
DispatchOperation(DocumentOperation),
|
DispatchOperation(DocumentOperation),
|
||||||
SelectLayer(Vec<LayerId>),
|
SelectLayers(Vec<Vec<LayerId>>),
|
||||||
DeleteLayer(Vec<LayerId>),
|
DeleteLayer(Vec<LayerId>),
|
||||||
AddFolder(Vec<LayerId>),
|
AddFolder(Vec<LayerId>),
|
||||||
RenameLayer(Vec<LayerId>, String),
|
RenameLayer(Vec<LayerId>, String),
|
||||||
@@ -49,6 +49,13 @@ impl DocumentMessageHandler {
|
|||||||
document_responses.retain(|response| !matches!(response, DocumentResponse::DocumentChanged));
|
document_responses.retain(|response| !matches!(response, DocumentResponse::DocumentChanged));
|
||||||
document_responses.len() != len
|
document_responses.len() != len
|
||||||
}
|
}
|
||||||
|
fn handle_folder_changed(&mut self, path: Vec<LayerId>) -> Option<Message> {
|
||||||
|
let document = self.active_document_mut();
|
||||||
|
document.layer_data(&path).expanded.then(|| {
|
||||||
|
let children = document.layer_panel(path.as_slice()).expect("The provided Path was not valid");
|
||||||
|
FrontendMessage::ExpandFolder { path, children }.into()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for DocumentMessageHandler {
|
impl Default for DocumentMessageHandler {
|
||||||
@@ -84,6 +91,17 @@ impl MessageHandler<DocumentMessage, ()> for DocumentMessageHandler {
|
|||||||
ToggleLayerVisibility(path) => {
|
ToggleLayerVisibility(path) => {
|
||||||
responses.push_back(DocumentOperation::ToggleVisibility { path }.into());
|
responses.push_back(DocumentOperation::ToggleVisibility { path }.into());
|
||||||
}
|
}
|
||||||
|
ToggleLayerExpansion(path) => {
|
||||||
|
self.active_document_mut().layer_data(&path).expanded ^= true;
|
||||||
|
responses.extend(self.handle_folder_changed(path));
|
||||||
|
}
|
||||||
|
SelectLayers(paths) => {
|
||||||
|
for path in paths {
|
||||||
|
self.active_document_mut().layer_data(&path).selected ^= true;
|
||||||
|
responses.extend(self.handle_folder_changed(path));
|
||||||
|
// TODO: Add deduplication
|
||||||
|
}
|
||||||
|
}
|
||||||
Undo => {
|
Undo => {
|
||||||
// this is a temporary fix and will be addressed by #123
|
// this is a temporary fix and will be addressed by #123
|
||||||
if let Some(id) = self.active_document().document.root.list_layers().last() {
|
if let Some(id) = self.active_document().document.root.list_layers().last() {
|
||||||
@@ -93,7 +111,15 @@ impl MessageHandler<DocumentMessage, ()> for DocumentMessageHandler {
|
|||||||
DispatchOperation(op) => {
|
DispatchOperation(op) => {
|
||||||
if let Ok(Some(mut document_responses)) = self.active_document_mut().document.handle_operation(op) {
|
if let Ok(Some(mut document_responses)) = self.active_document_mut().document.handle_operation(op) {
|
||||||
let canvas_dirty = self.filter_document_responses(&mut document_responses);
|
let canvas_dirty = self.filter_document_responses(&mut document_responses);
|
||||||
responses.extend(document_responses.into_iter().map(Into::into));
|
responses.extend(
|
||||||
|
document_responses
|
||||||
|
.into_iter()
|
||||||
|
.map(|response| match response {
|
||||||
|
DocumentResponse::FolderChanged { path } => self.handle_folder_changed(path),
|
||||||
|
DocumentResponse::DocumentChanged => unreachable!(),
|
||||||
|
})
|
||||||
|
.flatten(),
|
||||||
|
);
|
||||||
if canvas_dirty {
|
if canvas_dirty {
|
||||||
responses.push_back(RenderDocument.into())
|
responses.push_back(RenderDocument.into())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ mod document_file;
|
|||||||
mod document_message_handler;
|
mod document_message_handler;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use document_file::Document;
|
pub use document_file::{Document, LayerData};
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use document_message_handler::{DocumentMessage, DocumentMessageDiscriminant, DocumentMessageHandler};
|
pub use document_message_handler::{DocumentMessage, DocumentMessageDiscriminant, DocumentMessageHandler};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
use crate::frontend::layer_panel::LayerPanelEntry;
|
||||||
use crate::message_prelude::*;
|
use crate::message_prelude::*;
|
||||||
use document_core::{response::LayerPanelEntry, DocumentResponse, LayerId};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub type Callback = Box<dyn Fn(FrontendMessage)>;
|
pub type Callback = Box<dyn Fn(FrontendMessage)>;
|
||||||
@@ -16,22 +16,6 @@ pub enum FrontendMessage {
|
|||||||
DisableTextInput,
|
DisableTextInput,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DocumentResponse> for Message {
|
|
||||||
fn from(response: DocumentResponse) -> Self {
|
|
||||||
let frontend: FrontendMessage = response.into();
|
|
||||||
frontend.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl From<DocumentResponse> for FrontendMessage {
|
|
||||||
fn from(response: DocumentResponse) -> Self {
|
|
||||||
match response {
|
|
||||||
DocumentResponse::ExpandFolder { path, children } => Self::ExpandFolder { path, children },
|
|
||||||
DocumentResponse::CollapseFolder { path } => Self::CollapseFolder { path },
|
|
||||||
_ => unimplemented!("The frontend does not handle {:?}", response),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FrontendMessageHandler {
|
pub struct FrontendMessageHandler {
|
||||||
callback: crate::Callback,
|
callback: crate::Callback,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
use crate::document::LayerData;
|
||||||
|
use document_core::{layers::LayerDataTypes, LayerId};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||||
|
pub struct LayerPanelEntry {
|
||||||
|
pub name: String,
|
||||||
|
pub visible: bool,
|
||||||
|
pub layer_type: LayerType,
|
||||||
|
pub layer_data: LayerData,
|
||||||
|
pub path: Vec<LayerId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||||
|
pub enum LayerType {
|
||||||
|
Folder,
|
||||||
|
Shape,
|
||||||
|
Circle,
|
||||||
|
Rect,
|
||||||
|
Line,
|
||||||
|
PolyLine,
|
||||||
|
Ellipse,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for LayerType {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let name = match self {
|
||||||
|
LayerType::Folder => "Folder",
|
||||||
|
LayerType::Shape => "Shape",
|
||||||
|
LayerType::Rect => "Rectangle",
|
||||||
|
LayerType::Line => "Line",
|
||||||
|
LayerType::Circle => "Circle",
|
||||||
|
LayerType::PolyLine => "Polyline",
|
||||||
|
LayerType::Ellipse => "Ellipse",
|
||||||
|
};
|
||||||
|
|
||||||
|
formatter.write_str(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&LayerDataTypes> for LayerType {
|
||||||
|
fn from(data: &LayerDataTypes) -> Self {
|
||||||
|
use LayerDataTypes::*;
|
||||||
|
match data {
|
||||||
|
Folder(_) => LayerType::Folder,
|
||||||
|
Shape(_) => LayerType::Shape,
|
||||||
|
Circle(_) => LayerType::Circle,
|
||||||
|
Rect(_) => LayerType::Rect,
|
||||||
|
Line(_) => LayerType::Line,
|
||||||
|
PolyLine(_) => LayerType::PolyLine,
|
||||||
|
Ellipse(_) => LayerType::Ellipse,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod frontend_message_handler;
|
pub mod frontend_message_handler;
|
||||||
|
pub mod layer_panel;
|
||||||
|
|
||||||
pub use frontend_message_handler::{Callback, FrontendMessage, FrontendMessageDiscriminant, FrontendMessageHandler};
|
pub use frontend_message_handler::{Callback, FrontendMessage, FrontendMessageDiscriminant, FrontendMessageHandler};
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ pub mod message_prelude {
|
|||||||
pub use super::tool::tools::rectangle::{RectangleMessage, RectangleMessageDiscriminant};
|
pub use super::tool::tools::rectangle::{RectangleMessage, RectangleMessageDiscriminant};
|
||||||
pub use super::tool::tools::select::{SelectMessage, SelectMessageDiscriminant};
|
pub use super::tool::tools::select::{SelectMessage, SelectMessageDiscriminant};
|
||||||
pub use super::tool::tools::shape::{ShapeMessage, ShapeMessageDiscriminant};
|
pub use super::tool::tools::shape::{ShapeMessage, ShapeMessageDiscriminant};
|
||||||
|
pub use crate::LayerId;
|
||||||
pub use graphite_proc_macros::*;
|
pub use graphite_proc_macros::*;
|
||||||
pub use std::collections::VecDeque;
|
pub use std::collections::VecDeque;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user