Mountain/ApplicationState/DTO/TreeViewStateDTO.rs
1//! # TreeViewStateDTO
2//!
3//! # RESPONSIBILITY
4//! - Data transfer object for tree view state
5//! - In-memory state tracking (not serializable due to trait object)
6//! - Used by Mountain to track tree view provider instances
7//!
8//! # FIELDS
9//! - ViewIdentifier: Unique tree view identifier
10//! - Provider: Native Rust provider reference
11//! - SideCarIdentifier: Extension sidecar host ID
12//! - CanSelectMany: Multi-selection support flag
13//! - HasHandleDrag: Drag-and-drop source support
14//! - HasHandleDrop: Drop target support
15//! - Message: Optional UI message
16//! - Title: Tree view title
17//! - Description: Optional description text
18
19use std::sync::Arc;
20
21use CommonLibrary::TreeView::TreeViewProvider::TreeViewProvider;
22
23/// Maximum view identifier length
24const MAX_VIEW_IDENTIFIER_LENGTH:usize = 128;
25
26/// Maximum sidecar identifier length
27const MAX_SIDECAR_IDENTIFIER_LENGTH:usize = 128;
28
29/// Maximum message length
30const MAX_MESSAGE_LENGTH:usize = 1024;
31
32/// Maximum title length
33const MAX_TITLE_LENGTH:usize = 256;
34
35/// Maximum description length
36const MAX_DESCRIPTION_LENGTH:usize = 512;
37
38/// Maximum badge length (serialized JSON)
39const MAX_BADGE_LENGTH:usize = 2048;
40
41/// Holds the static options and provider for a tree view instance that has been
42/// registered by an extension or natively. This is stored in `ApplicationState`
43/// to track active tree views.
44///
45/// This struct holds references to either a native (Rust) provider or metadata
46/// for a proxied (extension) provider.
47///
48/// NOTE: This struct does not derive Serialize/Deserialize because `Arc<dyn
49/// ...>` is not serializable. It is intended for in-memory state management
50/// only.
51#[derive(Clone)]
52pub struct TreeViewStateDTO {
53 /// The unique identifier for this tree view.
54 pub ViewIdentifier:String,
55
56 /// A reference to the native provider, if one exists for this view.
57 /// This will be `None` for extension-provided (proxied) tree views.
58 pub Provider:Option<Arc<dyn TreeViewProvider + Send + Sync>>,
59
60 /// The identifier of the sidecar process that hosts the provider logic.
61 /// This will be `Some` for extension-provided (proxied) tree views.
62 pub SideCarIdentifier:Option<String>,
63
64 /// Whether the tree view supports selecting multiple items.
65 pub CanSelectMany:bool,
66
67 /// Whether the tree view supports drag and drop for its items.
68 pub HasHandleDrag:bool,
69
70 /// Whether the tree view supports dropping items onto it.
71 pub HasHandleDrop:bool,
72
73 /// An optional message to display in the tree view's UI.
74 pub Message:Option<String>,
75
76 /// The title of the tree view.
77 pub Title:Option<String>,
78
79 /// An optional description that appears with the title.
80 pub Description:Option<String>,
81
82 /// Badge to display on the tree view (typically a count or string)
83 pub Badge:Option<String>,
84}
85
86impl TreeViewStateDTO {
87 /// Creates a new TreeViewStateDTO with validation.
88 ///
89 /// # Arguments
90 /// * `ViewIdentifier` - Unique view identifier
91 /// * `Provider` - Optional native provider
92 /// * `SideCarIdentifier` - Optional sidecar identifier
93 /// * `CanSelectMany` - Multi-selection support
94 /// * `HasHandleDrag` - Drag support
95 /// * `HasHandleDrop` - Drop support
96 ///
97 /// # Returns
98 /// Result containing the DTO or validation error
99 pub fn New(
100 ViewIdentifier:String,
101
102 Provider:Option<Arc<dyn TreeViewProvider + Send + Sync>>,
103
104 SideCarIdentifier:Option<String>,
105
106 CanSelectMany:bool,
107
108 HasHandleDrag:bool,
109
110 HasHandleDrop:bool,
111 ) -> Result<Self, String> {
112 // Validate view identifier length
113 if ViewIdentifier.len() > MAX_VIEW_IDENTIFIER_LENGTH {
114 return Err(format!(
115 "View identifier exceeds maximum length of {} bytes",
116 MAX_VIEW_IDENTIFIER_LENGTH
117 ));
118 }
119
120 // Validate sidecar identifier length
121 if let Some(SideCarID) = &SideCarIdentifier {
122 if SideCarID.len() > MAX_SIDECAR_IDENTIFIER_LENGTH {
123 return Err(format!(
124 "SideCar identifier exceeds maximum length of {} bytes",
125 MAX_SIDECAR_IDENTIFIER_LENGTH
126 ));
127 }
128 }
129
130 Ok(Self {
131 ViewIdentifier,
132 Provider,
133 SideCarIdentifier,
134 CanSelectMany,
135 HasHandleDrag,
136 HasHandleDrop,
137 Message:None,
138 Title:None,
139 Description:None,
140 Badge:None,
141 })
142 }
143
144 /// Sets the UI message with validation.
145 ///
146 /// # Arguments
147 /// * `Message` - Message text
148 ///
149 /// # Returns
150 /// Result indicating success or error if message too long
151 pub fn SetMessage(&mut self, Message:String) -> Result<(), String> {
152 if Message.len() > MAX_MESSAGE_LENGTH {
153 return Err(format!("Message exceeds maximum length of {} bytes", MAX_MESSAGE_LENGTH));
154 }
155
156 self.Message = Some(Message);
157
158 Ok(())
159 }
160
161 /// Sets the title with validation.
162 ///
163 /// # Arguments
164 /// * `Title` - Title text
165 ///
166 /// # Returns
167 /// Result indicating success or error if title too long
168 pub fn SetTitle(&mut self, Title:String) -> Result<(), String> {
169 if Title.len() > MAX_TITLE_LENGTH {
170 return Err(format!("Title exceeds maximum length of {} bytes", MAX_TITLE_LENGTH));
171 }
172
173 self.Title = Some(Title);
174
175 Ok(())
176 }
177
178 /// Sets the description with validation.
179 ///
180 /// # Arguments
181 /// * `Description` - Description text
182 ///
183 /// # Returns
184 /// Result indicating success or error if description too long
185 pub fn SetDescription(&mut self, Description:String) -> Result<(), String> {
186 if Description.len() > MAX_DESCRIPTION_LENGTH {
187 return Err(format!(
188 "Description exceeds maximum length of {} bytes",
189 MAX_DESCRIPTION_LENGTH
190 ));
191 }
192
193 self.Description = Some(Description);
194
195 Ok(())
196 }
197
198 /// Sets the badge with validation.
199 ///
200 /// # Arguments
201 /// * `Badge` - Badge value (typically a count or string)
202 ///
203 /// # Returns
204 /// Result indicating success or error if badge too long
205 pub fn SetBadge(&mut self, Badge:String) -> Result<(), String> {
206 if Badge.len() > MAX_BADGE_LENGTH {
207 return Err(format!("Badge exceeds maximum length of {} bytes", MAX_BADGE_LENGTH));
208 }
209
210 self.Badge = Some(Badge);
211
212 Ok(())
213 }
214
215 /// Checks if this is a native (Rust) tree view.
216 pub fn IsNative(&self) -> bool { self.Provider.is_some() }
217
218 /// Checks if this is a proxy (extension) tree view.
219 pub fn IsProxy(&self) -> bool { self.SideCarIdentifier.is_some() }
220}