use crate::error::{AltiumError, Result};
use crate::types::{CoordRect, ParameterCollection, UnknownFields};
use super::{SchGraphicalBase, SchPrimitive, SchPrimitiveBase, TextOrientations};
const KNOWN_KEYS: &[&str] = &[
"RECORD",
"OWNERINDEX",
"ISNOTACCESIBLE",
"OWNERPARTID",
"OWNERPARTDISPLAYMODE",
"GRAPHICALLYLOCKED",
"LOCATION.X",
"LOCATION.X_FRAC",
"LOCATION.Y",
"LOCATION.Y_FRAC",
"COLOR",
"AREACOLOR",
"LIBREFERENCE",
"DESIGNITEMID",
"COMPONENTDESCRIPTION",
"UNIQUEID",
"CURRENTPARTID",
"PARTCOUNT",
"DISPLAYMODECOUNT",
"DISPLAYMODE",
"SHOWHIDDENPINS",
"LIBRARYPATH",
"SOURCELIBRARYNAME",
"SHEETPARTFILENAME",
"TARGETFILENAME",
"OVERIDECOLORS",
"DESIGNATORLOCKED",
"PARTIDLOCKED",
"COMPONENTKIND",
"ALIASLIST",
"ORIENTATION",
];
#[derive(Debug, Clone)]
pub struct SchComponent {
pub graphical: SchGraphicalBase,
pub lib_reference: String,
pub component_description: String,
pub unique_id: String,
pub current_part_id: i32,
pub part_count: i32,
pub display_mode_count: i32,
pub display_mode: i32,
pub show_hidden_pins: bool,
pub library_path: String,
pub source_library_name: String,
pub sheet_part_filename: String,
pub target_filename: String,
pub override_colors: bool,
pub designator_locked: bool,
pub part_id_locked: bool,
pub component_kind: i32,
pub alias_list: String,
pub orientation: TextOrientations,
pub unknown_params: UnknownFields,
}
impl Default for SchComponent {
fn default() -> Self {
Self {
graphical: SchGraphicalBase {
base: SchPrimitiveBase {
owner_index: -1,
is_not_accessible: false,
owner_part_id: Some(-1), owner_part_display_mode: None,
graphically_locked: false,
},
location_x: 0,
location_y: 0,
color: 128, area_color: 11599871, },
lib_reference: String::new(),
component_description: String::new(),
unique_id: String::new(),
current_part_id: 1, part_count: 1, display_mode_count: 1, display_mode: 0, show_hidden_pins: false,
library_path: "*".to_string(), source_library_name: "*".to_string(), sheet_part_filename: "*".to_string(), target_filename: "*".to_string(), override_colors: false,
designator_locked: false,
part_id_locked: true, component_kind: 0,
alias_list: String::new(),
orientation: TextOrientations::NONE,
unknown_params: UnknownFields::default(),
}
}
}
impl SchComponent {
pub fn set_display_mode(&mut self, mode: i32) -> Result<()> {
if mode < 0 {
return Err(AltiumError::Validation(
"display_mode cannot be negative".into(),
));
}
if mode >= self.display_mode_count {
return Err(AltiumError::Validation(format!(
"display_mode {} exceeds display_mode_count {}",
mode, self.display_mode_count
)));
}
self.display_mode = mode;
Ok(())
}
}
impl SchPrimitive for SchComponent {
const RECORD_ID: i32 = 1;
fn location(&self) -> Option<crate::types::CoordPoint> {
Some(crate::types::CoordPoint::from_raw(
self.graphical.location_x,
self.graphical.location_y,
))
}
fn record_type_name(&self) -> &'static str {
"Component"
}
fn get_property(&self, name: &str) -> Option<String> {
match name {
"LIBREFERENCE" => Some(self.lib_reference.clone()),
"COMPONENTDESCRIPTION" => Some(self.component_description.clone()),
"UNIQUEID" => Some(self.unique_id.clone()),
_ => None,
}
}
fn import_from_params(params: &ParameterCollection) -> Result<Self> {
let graphical = SchGraphicalBase::import_from_params(params);
Ok(SchComponent {
graphical,
lib_reference: params
.get("LIBREFERENCE")
.map(|v| v.as_str().to_string())
.or_else(|| params.get("DESIGNITEMID").map(|v| v.as_str().to_string()))
.unwrap_or_default(),
component_description: params
.get("COMPONENTDESCRIPTION")
.map(|v| v.as_str().to_string())
.unwrap_or_default(),
unique_id: params
.get("UNIQUEID")
.map(|v| v.as_str().to_string())
.unwrap_or_default(),
current_part_id: params
.get("CURRENTPARTID")
.map(|v| v.as_int_or(1))
.unwrap_or(1),
part_count: params
.get("PARTCOUNT")
.map(|v| v.as_int_or(2) - 1)
.unwrap_or(1),
display_mode_count: params
.get("DISPLAYMODECOUNT")
.map(|v| v.as_int_or(1))
.unwrap_or(1),
display_mode: params
.get("DISPLAYMODE")
.map(|v| v.as_int_or(0))
.unwrap_or(0),
show_hidden_pins: params
.get("SHOWHIDDENPINS")
.map(|v| v.as_bool_or(false))
.unwrap_or(false),
library_path: params
.get("LIBRARYPATH")
.map(|v| v.as_str().to_string())
.unwrap_or_else(|| "*".to_string()),
source_library_name: params
.get("SOURCELIBRARYNAME")
.map(|v| v.as_str().to_string())
.unwrap_or_else(|| "*".to_string()),
sheet_part_filename: params
.get("SHEETPARTFILENAME")
.map(|v| v.as_str().to_string())
.unwrap_or_else(|| "*".to_string()),
target_filename: params
.get("TARGETFILENAME")
.map(|v| v.as_str().to_string())
.unwrap_or_else(|| "*".to_string()),
override_colors: params
.get("OVERIDECOLORS")
.map(|v| v.as_bool_or(false))
.unwrap_or(false),
designator_locked: params
.get("DESIGNATORLOCKED")
.map(|v| v.as_bool_or(false))
.unwrap_or(false),
part_id_locked: params
.get("PARTIDLOCKED")
.map(|v| v.as_bool_or(true))
.unwrap_or(true),
component_kind: params
.get("COMPONENTKIND")
.map(|v| v.as_int_or(0))
.unwrap_or(0),
alias_list: params
.get("ALIASLIST")
.map(|v| v.as_str().to_string())
.unwrap_or_default(),
orientation: params
.get("ORIENTATION")
.map(|v| TextOrientations::from_int(v.as_int_or(0)))
.unwrap_or_default(),
unknown_params: UnknownFields::from_remaining_params(params, KNOWN_KEYS),
})
}
fn export_to_params(&self) -> ParameterCollection {
let mut params = ParameterCollection::new();
params.add_int("RECORD", Self::RECORD_ID);
self.graphical.export_to_params(&mut params);
params.add("LIBREFERENCE", &self.lib_reference);
params.add("COMPONENTDESCRIPTION", &self.component_description);
params.add_int("PARTCOUNT", self.part_count + 1);
params.add_int("DISPLAYMODECOUNT", self.display_mode_count);
params.add_int("ORIENTATION", self.orientation.to_int());
params.add_int("CURRENTPARTID", self.current_part_id);
params.add_bool("SHOWHIDDENPINS", self.show_hidden_pins);
params.add("LIBRARYPATH", &self.library_path);
params.add("SOURCELIBRARYNAME", &self.source_library_name);
params.add("SHEETPARTFILENAME", &self.sheet_part_filename);
params.add("TARGETFILENAME", &self.target_filename);
params.add("UNIQUEID", &self.unique_id);
params.add_int("DISPLAYMODE", self.display_mode);
params.add_bool("OVERIDECOLORS", self.override_colors);
params.add_bool("DESIGNATORLOCKED", self.designator_locked);
params.add_bool("PARTIDLOCKED", self.part_id_locked);
params.add("ALIASLIST", &self.alias_list);
params.add("DESIGNITEMID", &self.lib_reference);
params.add_int("COMPONENTKIND", self.component_kind);
self.unknown_params.merge_into_params(&mut params);
params
}
fn owner_index(&self) -> i32 {
self.graphical.base.owner_index
}
fn calculate_bounds(&self) -> CoordRect {
CoordRect::empty()
}
}