Skip to main content

rs_teststand/property/
property_object_file.rs

1//! A file that stores property objects.
2
3use rs_teststand_sys::{Dispatch, Value};
4
5use crate::Error;
6use crate::dispids::property_object_file;
7use crate::types::TypeUsageList;
8
9/// A file holding property objects (`PropertyObjectFile`).
10///
11/// The file view of something that also has a richer identity, a sequence file
12/// reached through `as_property_object_file`, or a workspace's options file.
13/// This is where a file's registered types live.
14#[derive(Debug)]
15pub struct PropertyObjectFile {
16    dispatch: Box<dyn Dispatch>,
17}
18
19impl PropertyObjectFile {
20    /// Wraps a dispatch handle returned by the engine.
21    pub(crate) fn new(dispatch: Box<dyn Dispatch>) -> Self {
22        Self { dispatch }
23    }
24
25    /// Writes the file to disk if it has changed
26    /// (`PropertyObjectFile.SaveFileIfModified`).
27    ///
28    /// Does nothing when the file is unmodified. The path written is whatever
29    /// [`path`](Self::path) reports.
30    ///
31    /// **Pass `prompt = false` from a host with no operator.** With `true` the
32    /// engine puts a dialog on screen offering to save, and a headless caller
33    /// would block on a question nobody can answer. The returned `false` means
34    /// only that someone declined at that dialog, so under `prompt = false` a
35    /// `false` should not happen.
36    ///
37    /// # Errors
38    /// [`Error`] if the COM call fails or returns an unexpected type.
39    pub fn save_file_if_modified(&self, prompt: bool) -> Result<bool, Error> {
40        Ok(self
41            .dispatch
42            .call(
43                property_object_file::SAVE_FILE_IF_MODIFIED,
44                &[Value::Bool(prompt)],
45            )?
46            .as_bool()?)
47    }
48
49    /// The types registered in this file (`TypeUsageList`).
50    ///
51    /// # Errors
52    /// [`Error`] if the COM call fails or returns an unexpected type.
53    pub fn type_usage_list(&self) -> Result<TypeUsageList, Error> {
54        Ok(TypeUsageList::new(
55            self.dispatch
56                .get(property_object_file::TYPE_USAGE_LIST)?
57                .into_object()?,
58        ))
59    }
60
61    /// Marks the file as modified (`IncChangeCount`).
62    ///
63    /// Saving does nothing when the file does not believe it has changed, so a
64    /// change made through the API needs this before the save will write.
65    ///
66    /// # Errors
67    /// [`Error`] if the COM call fails.
68    pub fn inc_change_count(&self) -> Result<(), Error> {
69        self.dispatch
70            .call(property_object_file::INC_CHANGE_COUNT, &[])?;
71        Ok(())
72    }
73
74    /// The root of the file's property tree (`Data`).
75    ///
76    /// Everything a file stores hangs off here, which is how a file with no
77    /// richer identity, the templates file, for one, is read at all.
78    ///
79    /// # Errors
80    /// [`Error`] if the COM call fails or returns an unexpected type.
81    pub fn data(&self) -> Result<crate::property::PropertyObject, Error> {
82        Ok(crate::property::PropertyObject::new(
83            self.dispatch
84                .get(property_object_file::DATA)?
85                .into_object()?,
86        ))
87    }
88
89    /// The file's path (`Path`).
90    ///
91    /// # Errors
92    /// [`Error`] if the COM call fails or returns an unexpected type.
93    pub fn path(&self) -> Result<String, Error> {
94        Ok(self
95            .dispatch
96            .get(property_object_file::PATH)?
97            .into_string()?)
98    }
99
100    /// Sets the file's path (`Path`).
101    ///
102    /// # Errors
103    /// [`Error`] if the COM call fails.
104    pub fn set_path(&self, path: &str) -> Result<(), Error> {
105        self.dispatch
106            .put(property_object_file::PATH, Value::Str(path.to_owned()))?;
107        Ok(())
108    }
109}