feat(plugin): add layer creation and modification host API

- Add LayerConfig struct and add_layer / modify_layer methods to HostApi trait
- Implement IPC request/response serialization for AddLayer and ModifyLayer
- Implement HostSession methods with CAD property defaults and selective modification
- Refresh layer panel UI and invalidate scene layer dependencies upon layer changes
- Add unit tests for add_layer with defaults and partial modify_layer
This commit is contained in:
yztink committed 2026-09-19 16:40:41 -07:00
1 parent 28e530470f
commit 929f185ba5
6 files changed
+298

No files matched your search

+31
View File
@@ -552,6 +552,37 @@ pub trait HostApi {
let _ = tab_id;
None
}
/// Add a layer to the active document with full initial properties.
/// If an optional property in `config` is `None`, standard CAD defaults are applied.
/// Returns `None` if the layer already exists or `config.name` is invalid.
fn add_layer(&mut self, config: LayerConfig) -> Option<Handle> {
let _ = config;
None
}
/// Modify specified properties of an existing layer in the active document.
/// Properties that are `None` in `config` are left untouched as-is.
/// Returns `false` if the layer does not exist or `config.name` is invalid.
fn modify_layer(&mut self, config: LayerConfig) -> bool {
let _ = config;
false
}
}
/// Configuration properties for creating or modifying a layer.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct LayerConfig {
pub name: String,
pub color: Option<acadrust::types::Color>,
pub linetype: Option<String>,
pub lineweight: Option<acadrust::types::LineWeight>,
pub off: Option<bool>,
pub frozen: Option<bool>,
pub locked: Option<bool>,
pub plottable: Option<bool>,
pub transparency: Option<acadrust::types::Transparency>,
pub description: Option<String>,
}
/// Simplified, read-only entity kind exposed by [`DocumentReader`].
+28
View File
@@ -416,6 +416,34 @@ impl HostApi for PluginHostApi {
}
}
}
fn add_layer(&mut self, config: crate::host::LayerConfig) -> Option<Handle> {
match self.client.request(PluginRequest::AddLayer(config)) {
Ok(PluginResponse::OptHandle(h)) => h,
Ok(other) => {
eprintln!("[plugin] unexpected AddLayer response: {other:?}");
None
}
Err(e) => {
eprintln!("[plugin] AddLayer request failed: {e}");
None
}
}
}
fn modify_layer(&mut self, config: crate::host::LayerConfig) -> bool {
match self.client.request(PluginRequest::ModifyLayer(config)) {
Ok(PluginResponse::Bool(b)) => b,
Ok(other) => {
eprintln!("[plugin] unexpected ModifyLayer response: {other:?}");
false
}
Err(e) => {
eprintln!("[plugin] ModifyLayer request failed: {e}");
false
}
}
}
}
/// Sentinel reader used when the shared-memory view could not be initialized.
@@ -138,6 +138,10 @@ pub enum PluginRequest {
GetTabId,
/// V5: ask the host for the filesystem path of the document in `tab_id`.
DocumentPath { tab_id: u64 },
/// Add a layer to the active document with full initial properties.
AddLayer(crate::host::LayerConfig),
/// Modify specified properties of an existing layer in the active document.
ModifyLayer(crate::host::LayerConfig),
}
/// Responses the host sends back for `PluginRequest`.
@@ -164,6 +168,8 @@ pub enum PluginResponse {
TabId(u64),
/// V5: filesystem path of the document in the requested tab, if any.
DocumentPath(Option<std::ffi::OsString>),
/// Optional entity handle (e.g. from AddLayer).
OptHandle(Option<Handle>),
}
/// Messages sent from the host to the plugin runner.
+2
View File
@@ -77,5 +77,7 @@ pub fn handle_plugin_request(
DocumentPath { tab_id } => PluginResponse::DocumentPath(
host.document_path(tab_id).map(|path| path.into_os_string()),
),
AddLayer(config) => PluginResponse::OptHandle(host.add_layer(config)),
ModifyLayer(config) => PluginResponse::Bool(host.modify_layer(config)),
}
}
@@ -730,6 +730,34 @@ impl HostApi for V4PluginHostApi {
}
}
}
fn add_layer(&mut self, config: crate::host::LayerConfig) -> Option<Handle> {
match self.request(PluginRequest::AddLayer(config)) {
Ok(PluginResponse::OptHandle(h)) => h,
Ok(other) => {
eprintln!("[plugin] unexpected AddLayer response: {other:?}");
None
}
Err(e) => {
eprintln!("[plugin] AddLayer request failed: {e}");
None
}
}
}
fn modify_layer(&mut self, config: crate::host::LayerConfig) -> bool {
match self.request(PluginRequest::ModifyLayer(config)) {
Ok(PluginResponse::Bool(b)) => b,
Ok(other) => {
eprintln!("[plugin] unexpected ModifyLayer response: {other:?}");
false
}
Err(e) => {
eprintln!("[plugin] ModifyLayer request failed: {e}");
false
}
}
}
}
#[cfg(test)]