use std::fmt::Display;
use std::str::FromStr;
use crate::errors::{FormError, ErrorKind};
use crate::files::common::Properties;
use crate::language::color::Color;
use crate::language::controls::{
Activation, Appearance, BackStyle, BorderStyle, CausesValidation, DragMode, MousePointer,
ReferenceOrValue, SizeMode, TabStop, Visibility,
};
use image::DynamicImage;
use num_enum::TryFromPrimitive;
use serde::Serialize;
#[derive(
Debug, PartialEq, Eq, Clone, Serialize, Default, TryFromPrimitive, Copy, Hash, PartialOrd, Ord,
)]
#[repr(i32)]
pub enum OLETypeAllowed {
Link = 0,
Embedded = 1,
#[default]
Either = 2,
}
impl TryFrom<&str> for OLETypeAllowed {
type Error = ErrorKind;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"0" => Ok(OLETypeAllowed::Link),
"1" => Ok(OLETypeAllowed::Embedded),
"2" => Ok(OLETypeAllowed::Either),
_ => Err(ErrorKind::Form(FormError::InvalidOLETypeAllowed {
value: value.to_string(),
})),
}
}
}
impl FromStr for OLETypeAllowed {
type Err = ErrorKind;
fn from_str(s: &str) -> Result<Self, Self::Err> {
OLETypeAllowed::try_from(s)
}
}
impl Display for OLETypeAllowed {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let text = match self {
OLETypeAllowed::Link => "Link",
OLETypeAllowed::Embedded => "Embedded",
OLETypeAllowed::Either => "Either",
};
write!(f, "{text}")
}
}
#[derive(
Debug, PartialEq, Eq, Clone, Serialize, Default, TryFromPrimitive, Copy, Hash, PartialOrd, Ord,
)]
#[repr(i32)]
pub enum UpdateOptions {
#[default]
Automatic = 0,
Frozen = 1,
Manual = 2,
}
impl TryFrom<&str> for UpdateOptions {
type Error = ErrorKind;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"0" => Ok(UpdateOptions::Automatic),
"1" => Ok(UpdateOptions::Frozen),
"2" => Ok(UpdateOptions::Manual),
_ => Err(ErrorKind::Form(FormError::InvalidUpdateOptions {
value: value.to_string(),
})),
}
}
}
impl FromStr for UpdateOptions {
type Err = ErrorKind;
fn from_str(s: &str) -> Result<Self, Self::Err> {
UpdateOptions::try_from(s)
}
}
impl Display for UpdateOptions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let text = match self {
UpdateOptions::Automatic => "Automatic",
UpdateOptions::Frozen => "Frozen",
UpdateOptions::Manual => "Manual",
};
write!(f, "{text}")
}
}
#[derive(
Debug, PartialEq, Eq, Clone, Serialize, Default, TryFromPrimitive, Copy, Hash, PartialOrd, Ord,
)]
#[repr(i32)]
pub enum AutoActivate {
Manual = 0,
GetFocus = 1,
#[default]
DoubleClick = 2,
Automatic = 3,
}
impl TryFrom<&str> for AutoActivate {
type Error = ErrorKind;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"0" => Ok(AutoActivate::Manual),
"1" => Ok(AutoActivate::GetFocus),
"2" => Ok(AutoActivate::DoubleClick),
"3" => Ok(AutoActivate::Automatic),
_ => Err(ErrorKind::Form(FormError::InvalidAutoActivate {
value: value.to_string(),
})),
}
}
}
impl FromStr for AutoActivate {
type Err = ErrorKind;
fn from_str(s: &str) -> Result<Self, Self::Err> {
AutoActivate::try_from(s)
}
}
impl Display for AutoActivate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let text = match self {
AutoActivate::Manual => "Manual",
AutoActivate::GetFocus => "GetFocus",
AutoActivate::DoubleClick => "DoubleClick",
AutoActivate::Automatic => "Automatic",
};
write!(f, "{text}")
}
}
#[derive(
Debug, PartialEq, Eq, Clone, Serialize, Default, TryFromPrimitive, Copy, Hash, PartialOrd, Ord,
)]
#[repr(i32)]
pub enum DisplayType {
#[default]
Content = 0,
Icon = 1,
}
impl TryFrom<&str> for DisplayType {
type Error = ErrorKind;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"0" => Ok(DisplayType::Content),
"1" => Ok(DisplayType::Icon),
_ => Err(ErrorKind::Form(FormError::InvalidDisplayType {
value: value.to_string(),
})),
}
}
}
impl FromStr for DisplayType {
type Err = ErrorKind;
fn from_str(s: &str) -> Result<Self, Self::Err> {
DisplayType::try_from(s)
}
}
impl Display for DisplayType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let text = match self {
DisplayType::Content => "Content",
DisplayType::Icon => "Icon",
};
write!(f, "{text}")
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct OLEProperties {
pub appearance: Appearance,
pub auto_activate: AutoActivate,
pub auto_verb_menu: bool,
pub back_color: Color,
pub back_style: BackStyle,
pub border_style: BorderStyle,
pub causes_validation: CausesValidation,
pub class: Option<String>,
pub data_field: String,
pub data_source: String,
pub display_type: DisplayType,
pub drag_icon: Option<ReferenceOrValue<DynamicImage>>,
pub drag_mode: DragMode,
pub enabled: Activation,
pub height: i32,
pub help_context_id: i32,
pub host_name: String,
pub left: i32,
pub misc_flags: i32,
pub mouse_icon: Option<ReferenceOrValue<DynamicImage>>,
pub mouse_pointer: MousePointer,
pub ole_drop_allowed: bool,
pub ole_type_allowed: OLETypeAllowed,
pub size_mode: SizeMode,
pub source_doc: String,
pub source_item: String,
pub tab_index: i32,
pub tab_stop: TabStop,
pub top: i32,
pub update_options: UpdateOptions,
pub verb: i32,
pub visible: Visibility,
pub whats_this_help_id: i32,
pub width: i32,
}
impl Default for OLEProperties {
fn default() -> Self {
OLEProperties {
appearance: Appearance::ThreeD,
auto_activate: AutoActivate::DoubleClick,
auto_verb_menu: true,
back_color: Color::System { index: 5 },
back_style: BackStyle::Opaque,
border_style: BorderStyle::FixedSingle,
causes_validation: CausesValidation::Yes,
class: None,
data_field: String::new(),
data_source: String::new(),
display_type: DisplayType::Content,
drag_icon: None,
drag_mode: DragMode::Manual,
enabled: Activation::Enabled,
height: 375,
help_context_id: 0,
host_name: String::new(),
left: 600,
misc_flags: 0,
mouse_icon: None,
mouse_pointer: MousePointer::Default,
ole_drop_allowed: false,
ole_type_allowed: OLETypeAllowed::Either,
size_mode: SizeMode::Clip,
source_doc: String::new(),
source_item: String::new(),
tab_index: 0,
tab_stop: TabStop::Included,
top: 1200,
update_options: UpdateOptions::Automatic,
verb: 0,
visible: Visibility::Visible,
whats_this_help_id: 0,
width: 1335,
}
}
}
impl Serialize for OLEProperties {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut s = serializer.serialize_struct("OLEProperties", 31)?;
s.serialize_field("appearance", &self.appearance)?;
s.serialize_field("auto_activate", &self.auto_activate)?;
s.serialize_field("auto_verb_menu", &self.auto_verb_menu)?;
s.serialize_field("back_color", &self.back_color)?;
s.serialize_field("back_style", &self.back_style)?;
s.serialize_field("border_style", &self.border_style)?;
s.serialize_field("causes_validation", &self.causes_validation)?;
s.serialize_field("class", &self.class)?;
s.serialize_field("data_field", &self.data_field)?;
s.serialize_field("data_source", &self.data_source)?;
s.serialize_field("display_type", &self.display_type)?;
let option_text = self.drag_icon.as_ref().map(|_| "Some(DynamicImage)");
s.serialize_field("drag_icon", &option_text)?;
s.serialize_field("drag_mode", &self.drag_mode)?;
s.serialize_field("enabled", &self.enabled)?;
s.serialize_field("height", &self.height)?;
s.serialize_field("help_context_id", &self.help_context_id)?;
s.serialize_field("host_name", &self.host_name)?;
s.serialize_field("left", &self.left)?;
s.serialize_field("misc_flags", &self.misc_flags)?;
let option_text = self.mouse_icon.as_ref().map(|_| "Some(DynamicImage)");
s.serialize_field("mouse_icon", &option_text)?;
s.serialize_field("mouse_pointer", &self.mouse_pointer)?;
s.serialize_field("ole_drop_allowed", &self.ole_drop_allowed)?;
s.serialize_field("ole_type_allowed", &self.ole_type_allowed)?;
s.serialize_field("size_mode", &self.size_mode)?;
s.serialize_field("source_doc", &self.source_doc)?;
s.serialize_field("source_item", &self.source_item)?;
s.serialize_field("tab_index", &self.tab_index)?;
s.serialize_field("tab_stop", &self.tab_stop)?;
s.serialize_field("top", &self.top)?;
s.serialize_field("update_options", &self.update_options)?;
s.serialize_field("verb", &self.verb)?;
s.serialize_field("visible", &self.visible)?;
s.serialize_field("whats_this_help_id", &self.whats_this_help_id)?;
s.serialize_field("width", &self.width)?;
s.end()
}
}
impl From<Properties> for OLEProperties {
fn from(prop: Properties) -> Self {
let mut ole_prop = OLEProperties::default();
ole_prop.appearance = prop.get_property("Appearance", ole_prop.appearance);
ole_prop.auto_activate = prop.get_property("AutoActivate", ole_prop.auto_activate);
ole_prop.auto_verb_menu = prop.get_bool("AutoVerbMenu", ole_prop.auto_verb_menu);
ole_prop.back_color = prop.get_color("BackColor", ole_prop.back_color);
ole_prop.back_style = prop.get_property("BackStyle", ole_prop.back_style);
ole_prop.border_style = prop.get_property("BorderStyle", ole_prop.border_style);
ole_prop.causes_validation =
prop.get_property("CausesValidation", ole_prop.causes_validation);
ole_prop.data_field = match prop.get("DataField") {
Some(data_field) => data_field.into(),
None => ole_prop.data_field,
};
ole_prop.data_source = match prop.get("DataSource") {
Some(data_source) => data_source.into(),
None => ole_prop.data_source,
};
ole_prop.display_type = prop.get_property("DisplayType", ole_prop.display_type);
ole_prop.drag_mode = prop.get_property("DragMode", ole_prop.drag_mode);
ole_prop.enabled = prop.get_property("Enabled", ole_prop.enabled);
ole_prop.height = prop.get_i32("Height", ole_prop.height);
ole_prop.help_context_id = prop.get_i32("HelpContextID", ole_prop.help_context_id);
ole_prop.host_name = match prop.get("HostName") {
Some(host_name) => host_name.into(),
None => ole_prop.host_name,
};
ole_prop.left = prop.get_i32("Left", ole_prop.left);
ole_prop.misc_flags = prop.get_i32("MiscFlags", ole_prop.misc_flags);
ole_prop.mouse_pointer = prop.get_property("MousePointer", ole_prop.mouse_pointer);
ole_prop.ole_drop_allowed = prop.get_bool("OLEDropAllowed", ole_prop.ole_drop_allowed);
ole_prop.ole_type_allowed = prop.get_property("OLETypeAllowed", ole_prop.ole_type_allowed);
ole_prop.size_mode = prop.get_property("SizeMode", ole_prop.size_mode);
ole_prop.tab_index = prop.get_i32("TabIndex", ole_prop.tab_index);
ole_prop.tab_stop = prop.get_property("TabStop", ole_prop.tab_stop);
ole_prop.top = prop.get_i32("Top", ole_prop.top);
ole_prop.update_options = prop.get_property("UpdateOptions", ole_prop.update_options);
ole_prop.verb = prop.get_i32("Verb", ole_prop.verb);
ole_prop.visible = prop.get_property("Visible", ole_prop.visible);
ole_prop.whats_this_help_id = prop.get_i32("WhatsThisHelpID", ole_prop.whats_this_help_id);
ole_prop.width = prop.get_i32("Width", ole_prop.width);
ole_prop
}
}