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}