layout: Respect margins
This commit is contained in:
17
src/data.rs
17
src/data.rs
@ -850,4 +850,21 @@ mod tests {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_layout_margins() {
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout_margins.yaml"))
|
||||
.unwrap()
|
||||
.build(PanicWarn).0
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.margins,
|
||||
layout::Margins {
|
||||
top: 1.0,
|
||||
bottom: 3.0,
|
||||
left: 2.0,
|
||||
right: 2.0,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
119
src/layout.rs
119
src/layout.rs
@ -99,7 +99,7 @@ pub mod c {
|
||||
}
|
||||
}
|
||||
|
||||
/// Scale + translate
|
||||
/// Translate and then scale
|
||||
#[repr(C)]
|
||||
pub struct Transformation {
|
||||
pub origin_x: f64,
|
||||
@ -108,6 +108,14 @@ pub mod c {
|
||||
}
|
||||
|
||||
impl Transformation {
|
||||
/// Applies the new transformation after this one
|
||||
pub fn chain(self, next: Transformation) -> Transformation {
|
||||
Transformation {
|
||||
origin_x: self.origin_x + self.scale * next.origin_x,
|
||||
origin_y: self.origin_y + self.scale * next.origin_y,
|
||||
scale: self.scale * next.scale,
|
||||
}
|
||||
}
|
||||
fn forward(&self, p: Point) -> Point {
|
||||
Point {
|
||||
x: (p.x - self.origin_x) / self.scale,
|
||||
@ -195,7 +203,8 @@ pub mod c {
|
||||
println!("{:?}", button);
|
||||
}
|
||||
|
||||
/// Positions the layout within the available space
|
||||
/// Positions the layout contents within the available space.
|
||||
/// The origin of the transformation is the point inside the margins.
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_calculate_transformation(
|
||||
@ -204,15 +213,10 @@ pub mod c {
|
||||
allocation_height: f64,
|
||||
) -> Transformation {
|
||||
let layout = unsafe { &*layout };
|
||||
let size = layout.calculate_size();
|
||||
let h_scale = allocation_width / size.width;
|
||||
let v_scale = allocation_height / size.height;
|
||||
let scale = if h_scale < v_scale { h_scale } else { v_scale };
|
||||
Transformation {
|
||||
origin_x: (allocation_width - (scale * size.width)) / 2.0,
|
||||
origin_y: (allocation_height - (scale * size.height)) / 2.0,
|
||||
scale: scale,
|
||||
}
|
||||
layout.calculate_transformation(Size {
|
||||
width: allocation_width,
|
||||
height: allocation_height,
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -427,7 +431,7 @@ pub struct ButtonPlace<'a> {
|
||||
offset: c::Point,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Size {
|
||||
pub width: f64,
|
||||
pub height: f64,
|
||||
@ -560,6 +564,7 @@ pub enum ArrangementKind {
|
||||
Wide = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Margins {
|
||||
pub top: f64,
|
||||
pub bottom: f64,
|
||||
@ -713,7 +718,8 @@ impl Layout {
|
||||
};
|
||||
}
|
||||
|
||||
fn calculate_size(&self) -> Size {
|
||||
/// Calculates size without margins
|
||||
fn calculate_inner_size(&self) -> Size {
|
||||
Size {
|
||||
height: find_max_double(
|
||||
self.views.iter(),
|
||||
@ -725,6 +731,39 @@ impl Layout {
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Size including margins
|
||||
fn calculate_size(&self) -> Size {
|
||||
let inner_size = self.calculate_inner_size();
|
||||
Size {
|
||||
width: self.margins.left + inner_size.width + self.margins.right,
|
||||
height: (
|
||||
self.margins.top
|
||||
+ inner_size.height
|
||||
+ self.margins.bottom
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calculate_transformation(
|
||||
&self,
|
||||
available: Size,
|
||||
) -> c::Transformation {
|
||||
let size = self.calculate_size();
|
||||
let h_scale = available.width / size.width;
|
||||
let v_scale = available.height / size.height;
|
||||
let scale = if h_scale < v_scale { h_scale } else { v_scale };
|
||||
let outside_margins = c::Transformation {
|
||||
origin_x: (available.width - (scale * size.width)) / 2.0,
|
||||
origin_y: (available.height - (scale * size.height)) / 2.0,
|
||||
scale: scale,
|
||||
};
|
||||
outside_margins.chain(c::Transformation {
|
||||
origin_x: self.margins.left,
|
||||
origin_y: self.margins.top,
|
||||
scale: 1.0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
mod procedures {
|
||||
@ -907,4 +946,58 @@ mod test {
|
||||
.is_none()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_bottom_margin() {
|
||||
// just one button
|
||||
let view = View::new(vec![
|
||||
(
|
||||
0.0,
|
||||
Row {
|
||||
angle: 0,
|
||||
buttons: vec![(
|
||||
0.0,
|
||||
Box::new(Button {
|
||||
size: Size { width: 1.0, height: 1.0 },
|
||||
..*make_button_with_state("foo".into(), make_state())
|
||||
}),
|
||||
)]
|
||||
},
|
||||
),
|
||||
]);
|
||||
let layout = Layout {
|
||||
current_view: String::new(),
|
||||
keymap_str: CString::new("").unwrap(),
|
||||
kind: ArrangementKind::Base,
|
||||
locked_keys: HashSet::new(),
|
||||
pressed_keys: HashSet::new(),
|
||||
// Lots of bottom margin
|
||||
margins: Margins {
|
||||
top: 0.0,
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
bottom: 1.0,
|
||||
},
|
||||
views: hashmap! {
|
||||
String::new() => view,
|
||||
},
|
||||
};
|
||||
assert_eq!(
|
||||
layout.calculate_inner_size(),
|
||||
Size { width: 1.0, height: 1.0 }
|
||||
);
|
||||
assert_eq!(
|
||||
layout.calculate_size(),
|
||||
Size { width: 1.0, height: 2.0 }
|
||||
);
|
||||
// Don't change those values randomly!
|
||||
// They take advantage of incidental precise float representation
|
||||
// to even be comparable.
|
||||
let transformation = layout.calculate_transformation(
|
||||
Size { width: 2.0, height: 2.0 }
|
||||
);
|
||||
assert_eq!(transformation.scale, 1.0);
|
||||
assert_eq!(transformation.origin_x, 0.5);
|
||||
assert_eq!(transformation.origin_y, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
9
tests/layout_margins.yaml
Normal file
9
tests/layout_margins.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
# Margins present
|
||||
margins: { top: 1, side: 2, bottom: 3 }
|
||||
views:
|
||||
base:
|
||||
- "test"
|
||||
outlines:
|
||||
default: { width: 1, height: 1 }
|
||||
|
||||
9
tests/layout_position.yaml
Normal file
9
tests/layout_position.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
# Margins present
|
||||
margins: { top: 1, side: 2, bottom: 3 }
|
||||
views:
|
||||
base:
|
||||
- "test"
|
||||
outlines:
|
||||
default: { width: 1, height: 1 }
|
||||
|
||||
Reference in New Issue
Block a user