}
Good([a, b]) => {
// todo: take account of the space used by the markers themselves
- let lhs = min(a[0], b[0]);
- let rhs = max(a[0], b[0]);
- let top = min(a[1], b[1]);
- let bot = max(a[1], b[1]);
+ let lhs = min(a.0[0], b.0[0]);
+ let rhs = max(a.0[0], b.0[0]);
+ let top = min(a.0[1], b.0[1]);
+ let bot = max(a.0[1], b.0[1]);
Placement {
lhs, rhs, top, bot,
cline_upto: lhs,
const USERLIST : &str = "/etc/userlist";
const CREATE_PIECES_MAX : u32 = 300;
-const DEFAULT_POS_START : Pos = [20,20];
-const DEFAULT_POS_DELTA : Pos = [5,5];
+const DEFAULT_POS_START : Pos = PosC([20,20]);
+const DEFAULT_POS_DELTA : Pos = PosC([5,5]);
pub struct CommandListener {
listener : UnixListener,
(U{ pcs: vec![],
log: vec![ LogEntry {
html: Html(format!("The table was resized to {}x{}",
- size[0], size[1])),
+ size.0[0], size.0[1])),
}],
raw: Some(vec![ PreparedUpdateEntry::SetTableSize(size) ]) },
Fine)
let piece = gs.pieces.as_mut(modperm).insert(pc);
ig.pieces.as_mut(modperm).insert(piece, p);
updates.push((piece, PieceUpdateOp::Insert(())));
- pos[0] += posd[0];
- pos[1] += posd[1];
+ pos += posd;
}
(U{ pcs: updates,
#[serde(transparent)]
pub struct Html (pub String);
-pub const DEFAULT_TABLE_SIZE : Pos = [ 400, 200 ];
+pub const DEFAULT_TABLE_SIZE : Pos = PosC([ 400, 200 ]);
// ---------- general data types ----------
fn clamped(self, range: Pos) -> (Pos, bool) {
let mut output = ArrayVec::new();
let mut did = false;
- for (npos, tdid) in self.iter().zip(range.iter())
+ for (npos, tdid) in self.0.iter().zip(range.0.iter())
.map(|(&pos, &rng)| pos.clamped(rng)) {
output.push(npos);
did |= tdid;
}
- (output.into_inner().unwrap(), did)
+ (PosC(output.into_inner().unwrap()), did)
}
}
}
#[throws(SE)]
-pub fn svg_rectangle_path([x, y] : [f64;2]) -> Html {
+pub fn svg_rectangle_path(PosC([x,y]) : PosC<f64>) -> Html {
Html(format!("M {} {} h {} v {} h {} z",
-x*0.5, -y*0.5, x, y, -x))
}
impl PieceSpec for piece_specs::Square {
#[throws(SpecError)]
fn load(&self) -> Box<dyn Piece> {
- let (x, y) = match *self.size.as_slice() {
- [s,] => (s,s),
- [x, y] => (x,y),
+ let xy = match *self.size.as_slice() {
+ [s,] => PosC([s,s]),
+ [x,y] => PosC([x,y]),
_ => throw!(SpecError::ImproperSizeSpec),
};
- let outline = Box::new(shapelib::Square { xy: [x as f64, y as f64] });
- let path = svg_rectangle_path([x as f64, y as f64])?;
+ let outline = Box::new(shapelib::Square { xy: xy.map(|v| v as f64) });
+ let path = svg_rectangle_path(xy.promote())?;
let itemname = self.itemname.clone()
.unwrap_or_else(||"simple-square".to_string());
SimpleShape::new_from_path(Html::lit("square"), path,
}
fn bbox_approx(&self) -> [Pos;2] {
let d = (self.diam * 0.5).ceil() as Coord;
- [[-d,-d], [d, d]]
+ [PosC([-d,-d]), PosC([d, d])]
}
}
}
#[derive(Serialize,Deserialize,Debug)]
-pub struct Square { pub xy: [f64;2] }
+pub struct Square { pub xy: PosC<f64> }
#[typetag::serde(name="Square")]
impl Outline for Square {
#[throws(IE)]
fn surround_path(&self, _pri : &PieceRenderInstructions) -> Html {
- let size : ArrayVec<_> =
- self.xy.iter().map(|s| s * SELECT_SCALE)
- .collect();
- svg_rectangle_path(size.into_inner().unwrap())?
+ let size = self.xy * SELECT_SCALE;
+ svg_rectangle_path(size)?
}
#[throws(IE)]
fn thresh_dragraise(&self, _pri : &PieceRenderInstructions)
-> Option<Coord> {
- let smallest : f64 = self.xy.iter().cloned()
+ let smallest : f64 = self.xy.0.iter().cloned()
.map(OrderedFloat::from).min().unwrap().into();
Some((smallest * 0.5) as Coord)
}
fn bbox_approx(&self) -> [Pos;2] {
- let pos : Pos = self.xy.iter().map(
+ let pos : Pos = (self.xy * 0.5).map(
|v| ((v * 0.5).ceil()) as Coord
- ).collect::<ArrayVec<_>>().into_inner().unwrap();
- let neg : Pos = pos.iter().map(
- |v| -v
- ).collect::<ArrayVec<_>>().into_inner().unwrap();
+ );
+ let neg = -pos;
[ neg, pos ]
}
}
impl SquareDefn {
#[throws(LibraryLoadError)]
fn get(group: &GroupData) -> Square {
- match group.d.size.as_slice() {
- &[s] => Square { xy: [s,s] },
- s if s.len() == 2 => Square { xy: s.try_into().unwrap() },
- size => throw!(LLE::WrongNumberOfSizeDimensions
- { got: size.len(), expected : [1,2]}),
- }
+ Square { xy: PosC(
+ match group.d.size.as_slice() {
+ &[s] => [s,s],
+ s if s.len() == 2 => s.try_into().unwrap(),
+ size => throw!(LLE::WrongNumberOfSizeDimensions
+ { got: size.len(), expected : [1,2]}),
+ }
+ )}
}
}
pub type Coord = isize;
-pub type Pos = [Coord; 2];
+#[derive(Clone,Copy,Debug,Serialize,Deserialize,Hash)]
+#[derive(Eq,PartialEq,Ord,PartialOrd)]
+#[serde(transparent)]
+pub struct PosC<T> (pub [T; 2]);
+pub type Pos = PosC<Coord>;
#[derive(Clone,Eq,PartialEq,Ord,PartialOrd,Hash,Serialize,Deserialize)]
#[serde(transparent)]
}
+//---------- Pos ----------
+
+pub mod pos_traits {
+ use std::ops::{Add,Sub,Mul,Neg,AddAssign,SubAssign};
+ use crate::imports::*;
+
+ impl<T:Add<T,Output=T>+Copy+Clone+Debug> Add<PosC<T>> for PosC<T> {
+ type Output = PosC<T>;
+ fn add(self, rhs: PosC<T>) -> PosC<T> {
+ PosC(
+ itertools::zip_eq(
+ self.0.iter().cloned(),
+ rhs .0.iter().cloned(),
+ ).map(|(a,b)| a + b)
+ .collect::<ArrayVec<_>>().into_inner().unwrap()
+ )
+ }
+ }
+
+ impl<T:Sub<T,Output=T>+Copy+Clone+Debug> Sub<PosC<T>> for PosC<T> {
+ type Output = PosC<T>;
+ fn sub(self, rhs: PosC<T>) -> PosC<T> {
+ PosC(
+ itertools::zip_eq(
+ self.0.iter().cloned(),
+ rhs .0.iter().cloned(),
+ ).map(|(a,b)| a - b)
+ .collect::<ArrayVec<_>>().into_inner().unwrap()
+ )
+ }
+ }
+
+ impl<T:Add<T,Output=T>+Copy+Clone+Debug> AddAssign<PosC<T>> for PosC<T> {
+ fn add_assign(&mut self, rhs: PosC<T>) {
+ *self = *self + rhs;
+ }
+ }
+
+ impl<T:Sub<T,Output=T>+Copy+Clone+Debug> SubAssign<PosC<T>> for PosC<T> {
+ fn sub_assign(&mut self, rhs: PosC<T>) {
+ *self = *self - rhs;
+ }
+ }
+
+ impl<T:Mul<T,Output=T>+Copy+Clone+Debug> Mul<T> for PosC<T> {
+ type Output = PosC<T>;
+ fn mul(self, rhs: T) -> PosC<T> {
+ PosC(
+ self.0.iter().cloned().map(|a| a * rhs)
+ .collect::<ArrayVec<_>>().into_inner().unwrap()
+ )
+ }
+ }
+
+ impl<T:Neg<Output=T>+Copy+Clone+Debug> Neg for PosC<T> {
+ type Output = Self;
+ fn neg(self) -> Self {
+ PosC(
+ self.0.iter().cloned().map(|a| -a)
+ .collect::<ArrayVec<_>>().into_inner().unwrap()
+ )
+ }
+ }
+
+ impl<T:Copy+Clone+Debug> PosC<T> {
+ pub fn map<U:Copy+Clone+Debug, F: FnMut(T) -> U>(self, f: F) -> PosC<U> {
+ PosC(
+ self.0.iter().cloned().map(f)
+ .collect::<ArrayVec<_>>().into_inner().unwrap()
+ )
+ }
+ }
+
+ impl PosC<Coord> {
+ pub fn promote(&self) -> PosC<f64> { self.map(|v| v as f64) }
+ }
+}
+
//---------- Implementation ----------
pub mod implementation {