use crate::oxml::writer::XmlWriter;
use crate::units::Emu;
pub const OLE_GRAPHIC_DATA_URI: &str = "http://schemas.openxmlformats.org/presentationml/2006/ole";
#[derive(Clone, Debug)]
pub struct OleObject {
pub rid: String,
pub image_rid: String,
pub prog_id: String,
pub name: String,
pub show_as_icon: bool,
pub image_width: Emu,
pub image_height: Emu,
pub pic_id: u32,
pub pic_name: String,
}
impl Default for OleObject {
fn default() -> Self {
OleObject {
rid: String::new(),
image_rid: String::new(),
prog_id: "Package".to_string(),
name: "OLE Object".to_string(),
show_as_icon: true,
image_width: Emu(914400), image_height: Emu(914400),
pic_id: 0,
pic_name: "OLE Icon".to_string(),
}
}
}
impl OleObject {
pub fn new(prog_id: impl Into<String>, name: impl Into<String>) -> Self {
OleObject {
prog_id: prog_id.into(),
name: name.into(),
..Default::default()
}
}
pub fn write_xml(&self, w: &mut XmlWriter) {
let spid = format!("_x0000_s{}", self.pic_id);
let img_w = self.image_width.0.to_string();
let img_h = self.image_height.0.to_string();
let show_as_icon = if self.show_as_icon { "1" } else { "0" };
let rid = if self.rid.is_empty() {
"rId1"
} else {
self.rid.as_str()
};
w.open_with(
"p:oleObj",
&[
("spid", spid.as_str()),
("name", self.name.as_str()),
("r:id", rid),
("imgW", img_w.as_str()),
("imgH", img_h.as_str()),
("progId", self.prog_id.as_str()),
("showAsIcon", show_as_icon),
],
);
w.empty("p:embed");
if !self.image_rid.is_empty() {
self.write_pic_xml(w);
}
w.close("p:oleObj");
}
fn write_pic_xml(&self, w: &mut XmlWriter) {
let pic_id_s = self.pic_id.to_string();
let img_rid = self.image_rid.as_str();
let cx_s = self.image_width.0.to_string();
let cy_s = self.image_height.0.to_string();
w.open("p:pic");
w.open("p:nvPicPr");
w.empty_with(
"p:cNvPr",
&[("id", pic_id_s.as_str()), ("name", self.pic_name.as_str())],
);
w.empty("p:cNvPicPr");
w.empty("p:nvPr");
w.close("p:nvPicPr");
w.open("p:blipFill");
w.empty_with(
"a:blip",
&[
(
"xmlns:r",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships",
),
("r:embed", img_rid),
],
);
w.open("a:stretch");
w.empty("a:fillRect");
w.close("a:stretch");
w.close("p:blipFill");
w.open("p:spPr");
w.open("a:xfrm");
w.empty_with("a:off", &[("x", "0"), ("y", "0")]);
w.empty_with("a:ext", &[("cx", cx_s.as_str()), ("cy", cy_s.as_str())]);
w.close("a:xfrm");
w.open_with("a:prstGeom", &[("prst", "rect")]);
w.empty("a:avLst");
w.close("a:prstGeom");
w.close("p:spPr");
w.close("p:pic");
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_ole_object_basics() {
let ole = OleObject::new("Excel.Sheet.12", "Worksheet");
assert_eq!(ole.prog_id, "Excel.Sheet.12");
assert_eq!(ole.name, "Worksheet");
assert_eq!(ole.rid, "");
assert_eq!(ole.image_rid, "");
assert!(ole.show_as_icon);
assert_eq!(ole.image_width, Emu(914400));
}
#[test]
fn write_xml_without_icon() {
let mut ole = OleObject::new("Package", "OLE Object");
ole.rid = "rIdOle1".to_string();
let mut w = XmlWriter::new();
ole.write_xml(&mut w);
let xml = w.into_string();
assert!(xml.contains("<p:oleObj"));
assert!(xml.contains("r:id=\"rIdOle1\""));
assert!(xml.contains("progId=\"Package\""));
assert!(xml.contains("<p:embed/>"));
assert!(!xml.contains("<p:pic>"));
}
#[test]
fn write_xml_with_icon() {
let mut ole = OleObject::new("Word.Document.12", "Document");
ole.rid = "rIdOle1".to_string();
ole.image_rid = "rIdImg1".to_string();
ole.pic_id = 1026;
let mut w = XmlWriter::new();
ole.write_xml(&mut w);
let xml = w.into_string();
assert!(xml.contains("<p:pic>"));
assert!(xml.contains("r:embed=\"rIdImg1\""));
assert!(xml.contains("spid=\"_x0000_s1026\""));
}
#[test]
fn write_xml_show_as_icon_false() {
let mut ole = OleObject::new("Package", "Object");
ole.rid = "rId1".to_string();
ole.show_as_icon = false;
let mut w = XmlWriter::new();
ole.write_xml(&mut w);
let xml = w.into_string();
assert!(xml.contains("showAsIcon=\"0\""));
}
}