@@ -7,10 +7,16 @@ use glam::DVec2;
7
7
use serde:: { Deserialize , Serialize } ;
8
8
use std:: fmt:: Write ;
9
9
10
+ /// A layer that encapsulates other layers, including potentially more folders.
11
+ /// The contained layers are rendered in the same order they are
12
+ /// stored in the [layers](FolderLayer::layers) field.
10
13
#[ derive( Debug , Clone , PartialEq , Deserialize , Serialize , Default ) ]
11
14
pub struct FolderLayer {
15
+ /// The ID that will be assigned to the next layer that is added to the folder
12
16
next_assignment_id : LayerId ,
17
+ /// The IDs of the [Layer]s contained within the Folder
13
18
pub layer_ids : Vec < LayerId > ,
19
+ /// The [Layer]s contained in the folder
14
20
layers : Vec < Layer > ,
15
21
}
16
22
@@ -38,12 +44,29 @@ impl LayerData for FolderLayer {
38
44
}
39
45
40
46
impl FolderLayer {
41
- /// When a insertion id is provided, try to insert the layer with the given id.
42
- /// If that id is already used, return None.
43
- /// When no insertion id is provided, search for the next free id and insert it with that.
44
- /// Negative values for insert_index represent distance from the end
47
+ /// When a insertion ID is provided, try to insert the layer with the given ID.
48
+ /// If that ID is already used, return `None`.
49
+ /// When no insertion ID is provided, search for the next free ID and insert it with that.
50
+ /// Negative values for `insert_index` represent distance from the end
51
+ ///
52
+ /// # Example
53
+ /// ```
54
+ /// # use graphite_graphene::layers::shape_layer::ShapeLayer;
55
+ /// # use graphite_graphene::layers::folder_layer::FolderLayer;
56
+ /// # use graphite_graphene::layers::style::PathStyle;
57
+ /// # use graphite_graphene::layers::layer_info::LayerDataType;
58
+ /// let mut folder = FolderLayer::default();
59
+ ///
60
+ /// // Create two layers to be added to the folder
61
+ /// let mut shape_layer = ShapeLayer::rectangle(PathStyle::default());
62
+ /// let mut folder_layer = FolderLayer::default();
63
+ ///
64
+ /// folder.add_layer(shape_layer.into(), None, -1);
65
+ /// folder.add_layer(folder_layer.into(), Some(123), 0);
66
+ /// ```
45
67
pub fn add_layer ( & mut self , layer : Layer , id : Option < LayerId > , insert_index : isize ) -> Option < LayerId > {
46
68
let mut insert_index = insert_index as i128 ;
69
+
47
70
if insert_index < 0 {
48
71
insert_index = self . layers . len ( ) as i128 + insert_index as i128 + 1 ;
49
72
}
@@ -71,22 +94,42 @@ impl FolderLayer {
71
94
}
72
95
}
73
96
97
+ /// Remove a layer with a given ID from the folder.
98
+ /// This operation will fail if `id` is not present in the folder.
99
+ ///
100
+ /// # Example
101
+ /// ```
102
+ /// # use graphite_graphene::layers::folder_layer::FolderLayer;
103
+ /// let mut folder = FolderLayer::default();
104
+ ///
105
+ /// // Try to remove a layer that does not exist
106
+ /// assert!(folder.remove_layer(123).is_err());
107
+ ///
108
+ /// // Add another folder to the folder
109
+ /// folder.add_layer(FolderLayer::default().into(), Some(123), -1);
110
+ ///
111
+ /// // Try to remove that folder again
112
+ /// assert!(folder.remove_layer(123).is_ok());
113
+ /// assert_eq!(folder.layers().len(), 0)
114
+ /// ```
74
115
pub fn remove_layer ( & mut self , id : LayerId ) -> Result < ( ) , DocumentError > {
75
116
let pos = self . position_of_layer ( id) ?;
76
117
self . layers . remove ( pos) ;
77
118
self . layer_ids . remove ( pos) ;
78
119
Ok ( ( ) )
79
120
}
80
121
81
- /// Returns a list of layers in the folder
122
+ /// Returns a list of [LayerId]s in the folder.
82
123
pub fn list_layers ( & self ) -> & [ LayerId ] {
83
124
self . layer_ids . as_slice ( )
84
125
}
85
126
127
+ /// Get references to all the [Layer]s in the folder.
86
128
pub fn layers ( & self ) -> & [ Layer ] {
87
129
self . layers . as_slice ( )
88
130
}
89
131
132
+ /// Get mutable references to all the [Layer]s in the folder.
90
133
pub fn layers_mut ( & mut self ) -> & mut [ Layer ] {
91
134
self . layers . as_mut_slice ( )
92
135
}
@@ -101,14 +144,70 @@ impl FolderLayer {
101
144
Some ( & mut self . layers [ pos] )
102
145
}
103
146
147
+ /// Returns `true` if the folder contains a layer with the given [LayerId].
148
+ ///
149
+ /// # Example
150
+ /// ```
151
+ /// # use graphite_graphene::layers::folder_layer::FolderLayer;
152
+ /// let mut folder = FolderLayer::default();
153
+ ///
154
+ /// // Search for an id that does not exist
155
+ /// assert!(!folder.folder_contains(123));
156
+ ///
157
+ /// // Add layer with the id "123" to the folder
158
+ /// folder.add_layer(FolderLayer::default().into(), Some(123), -1);
159
+ ///
160
+ /// // Search for the id "123"
161
+ /// assert!(folder.folder_contains(123));
162
+ /// ```
104
163
pub fn folder_contains ( & self , id : LayerId ) -> bool {
105
164
self . layer_ids . contains ( & id)
106
165
}
107
166
167
+ /// Tries to find the index of a layer with the given [LayerId] within the folder.
168
+ /// This operation will fail if no layer with a matching ID is present in the folder.
169
+ ///
170
+ /// # Example
171
+ /// ```
172
+ /// # use graphite_graphene::layers::folder_layer::FolderLayer;
173
+ /// let mut folder = FolderLayer::default();
174
+ ///
175
+ /// // Search for an id that does not exist
176
+ /// assert!(folder.position_of_layer(123).is_err());
177
+ ///
178
+ /// // Add layer with the id "123" to the folder
179
+ /// folder.add_layer(FolderLayer::default().into(), Some(123), -1);
180
+ /// folder.add_layer(FolderLayer::default().into(), Some(42), -1);
181
+ ///
182
+ /// assert_eq!(folder.position_of_layer(123), Ok(0));
183
+ /// assert_eq!(folder.position_of_layer(42), Ok(1));
184
+ /// ```
108
185
pub fn position_of_layer ( & self , layer_id : LayerId ) -> Result < usize , DocumentError > {
109
186
self . layer_ids . iter ( ) . position ( |x| * x == layer_id) . ok_or_else ( || DocumentError :: LayerNotFound ( [ layer_id] . into ( ) ) )
110
187
}
111
188
189
+ /// Tries to get a reference to a folder with the given [LayerId].
190
+ /// This operation will return `None` if either no layer with `id` exists
191
+ /// in the folder, or the layer with matching ID is not a folder.
192
+ ///
193
+ /// # Example
194
+ /// ```
195
+ /// # use graphite_graphene::layers::folder_layer::FolderLayer;
196
+ /// # use graphite_graphene::layers::shape_layer::ShapeLayer;
197
+ /// # use graphite_graphene::layers::style::PathStyle;
198
+ /// let mut folder = FolderLayer::default();
199
+ ///
200
+ /// // Search for an id that does not exist
201
+ /// assert!(folder.folder(132).is_none());
202
+ ///
203
+ /// // add a folder and search for it
204
+ /// folder.add_layer(FolderLayer::default().into(), Some(123), -1);
205
+ /// assert!(folder.folder(123).is_some());
206
+ ///
207
+ /// // add a non-folder layer and search for it
208
+ /// folder.add_layer(ShapeLayer::rectangle(PathStyle::default()).into(), Some(42), -1);
209
+ /// assert!(folder.folder(42).is_none());
210
+ /// ```
112
211
pub fn folder ( & self , id : LayerId ) -> Option < & FolderLayer > {
113
212
match self . layer ( id) {
114
213
Some ( Layer {
@@ -118,6 +217,10 @@ impl FolderLayer {
118
217
}
119
218
}
120
219
220
+ /// Tries to get a mutable reference to folder with the given `id`.
221
+ /// This operation will return `None` if either no layer with `id` exists
222
+ /// in the folder or the layer with matching ID is not a folder.
223
+ /// See the [FolderLayer::folder] method for a usage example.
121
224
pub fn folder_mut ( & mut self , id : LayerId ) -> Option < & mut FolderLayer > {
122
225
match self . layer_mut ( id) {
123
226
Some ( Layer {
0 commit comments