layout: Center views relative to each other and the layout bounds
This commit is contained in:
29
src/data.rs
29
src/data.rs
@ -417,8 +417,8 @@ impl Layout {
|
||||
)}
|
||||
);
|
||||
|
||||
let views = HashMap::from_iter(
|
||||
self.views.iter().map(|(name, view)| {
|
||||
let views: Vec<_> = self.views.iter()
|
||||
.map(|(name, view)| {
|
||||
let rows = view.iter().map(|row| {
|
||||
let buttons = row.split_ascii_whitespace()
|
||||
.map(|name| {
|
||||
@ -445,9 +445,26 @@ impl Layout {
|
||||
name.clone(),
|
||||
layout::View::new(rows)
|
||||
)
|
||||
})
|
||||
}).collect();
|
||||
|
||||
// Center views on the same point.
|
||||
let views = {
|
||||
let total_size = layout::View::calculate_super_size(
|
||||
views.iter().map(|(_name, view)| view).collect()
|
||||
);
|
||||
|
||||
HashMap::from_iter(views.into_iter().map(|(name, view)| (
|
||||
name,
|
||||
(
|
||||
layout::c::Point {
|
||||
x: (total_size.width - view.get_width()) / 2.0,
|
||||
y: (total_size.height - view.get_height()) / 2.0,
|
||||
},
|
||||
view,
|
||||
),
|
||||
)))
|
||||
};
|
||||
|
||||
(
|
||||
Ok(::layout::LayoutData {
|
||||
views: views,
|
||||
@ -742,7 +759,7 @@ mod tests {
|
||||
.build(ProblemPanic).0
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.views["base"]
|
||||
out.views["base"].1
|
||||
.get_rows()[0].1
|
||||
.buttons[0].1
|
||||
.label,
|
||||
@ -757,7 +774,7 @@ mod tests {
|
||||
.build(ProblemPanic).0
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.views["base"]
|
||||
out.views["base"].1
|
||||
.get_rows()[0].1
|
||||
.buttons[0].1
|
||||
.label,
|
||||
@ -773,7 +790,7 @@ mod tests {
|
||||
.build(ProblemPanic).0
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.views["base"]
|
||||
out.views["base"].1
|
||||
.get_rows()[0].1
|
||||
.buttons[0].1
|
||||
.state.borrow()
|
||||
|
||||
@ -47,14 +47,16 @@ mod c {
|
||||
let layout = unsafe { &mut *layout };
|
||||
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
||||
|
||||
let view = layout.get_current_view();
|
||||
let (view_offset, view) = layout.get_current_view_position();
|
||||
for (row_offset, row) in &view.get_rows() {
|
||||
for (x_offset, button) in &row.buttons {
|
||||
let state = RefCell::borrow(&button.state).clone();
|
||||
if state.pressed == keyboard::PressType::Pressed || state.locked {
|
||||
render_button_at_position(
|
||||
renderer, &cr,
|
||||
row_offset + Point { x: *x_offset, y: 0.0 },
|
||||
view_offset
|
||||
+ row_offset.clone()
|
||||
+ Point { x: *x_offset, y: 0.0 },
|
||||
button.as_ref(),
|
||||
state.pressed, state.locked,
|
||||
);
|
||||
@ -72,12 +74,14 @@ mod c {
|
||||
) {
|
||||
let layout = unsafe { &mut *layout };
|
||||
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
||||
let view = layout.get_current_view();
|
||||
let (view_offset, view) = layout.get_current_view_position();
|
||||
for (row_offset, row) in &view.get_rows() {
|
||||
for (x_offset, button) in &row.buttons {
|
||||
render_button_at_position(
|
||||
renderer, &cr,
|
||||
row_offset + Point { x: *x_offset, y: 0.0 },
|
||||
view_offset
|
||||
+ row_offset.clone()
|
||||
+ Point { x: *x_offset, y: 0.0 },
|
||||
button.as_ref(),
|
||||
keyboard::PressType::Released, false,
|
||||
);
|
||||
|
||||
@ -329,11 +329,8 @@ pub mod c {
|
||||
Point { x: x_widget, y: y_widget }
|
||||
);
|
||||
|
||||
let state = {
|
||||
let view = layout.get_current_view();
|
||||
view.find_button_by_position(point)
|
||||
.map(|place| place.button.state.clone())
|
||||
};
|
||||
let state = layout.find_button_by_position(point)
|
||||
.map(|place| place.button.state.clone());
|
||||
|
||||
if let Some(state) = state {
|
||||
seat::handle_press_key(
|
||||
@ -374,8 +371,7 @@ pub mod c {
|
||||
|
||||
let pressed = layout.pressed_keys.clone();
|
||||
let button_info = {
|
||||
let view = layout.get_current_view();
|
||||
let place = view.find_button_by_position(point);
|
||||
let place = layout.find_button_by_position(point);
|
||||
place.map(|place| {(
|
||||
place.button.state.clone(),
|
||||
place.button.clone(),
|
||||
@ -552,14 +548,14 @@ impl View {
|
||||
})
|
||||
}
|
||||
|
||||
fn get_width(&self) -> f64 {
|
||||
pub fn get_width(&self) -> f64 {
|
||||
// No need to call `get_rows()`,
|
||||
// as the biggest row is the most far reaching in both directions
|
||||
// because they are all centered.
|
||||
find_max_double(self.rows.iter(), |(_offset, row)| row.get_width())
|
||||
}
|
||||
|
||||
fn get_height(&self) -> f64 {
|
||||
pub fn get_height(&self) -> f64 {
|
||||
self.rows.iter().next_back()
|
||||
.map(|(y_offset, row)| row.get_height() + y_offset)
|
||||
.unwrap_or(0.0)
|
||||
@ -576,6 +572,21 @@ impl View {
|
||||
row,
|
||||
)}).collect()
|
||||
}
|
||||
|
||||
/// Returns a size which contains all the views
|
||||
/// if they are all centered on the same point.
|
||||
pub fn calculate_super_size(views: Vec<&View>) -> Size {
|
||||
Size {
|
||||
height: find_max_double(
|
||||
views.iter(),
|
||||
|view| view.get_height(),
|
||||
),
|
||||
width: find_max_double(
|
||||
views.iter(),
|
||||
|view| view.get_width(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The physical characteristic of layout for the purpose of styling
|
||||
@ -603,7 +614,8 @@ pub struct Layout {
|
||||
// Views own the actual buttons which have state
|
||||
// Maybe they should own UI only,
|
||||
// and keys should be owned by a dedicated non-UI-State?
|
||||
pub views: HashMap<String, View>,
|
||||
/// Point is the offset within the layout
|
||||
pub views: HashMap<String, (c::Point, View)>,
|
||||
|
||||
// Non-UI stuff
|
||||
/// xkb keymap applicable to the contained keys. Unchangeable
|
||||
@ -622,7 +634,8 @@ pub struct Layout {
|
||||
|
||||
/// A builder structure for picking up layout data from storage
|
||||
pub struct LayoutData {
|
||||
pub views: HashMap<String, View>,
|
||||
/// Point is the offset within layout
|
||||
pub views: HashMap<String, (c::Point, View)>,
|
||||
pub keymap_str: CString,
|
||||
pub margins: Margins,
|
||||
}
|
||||
@ -653,8 +666,13 @@ impl Layout {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_current_view_position(&self) -> &(c::Point, View) {
|
||||
&self.views
|
||||
.get(&self.current_view).expect("Selected nonexistent view")
|
||||
}
|
||||
|
||||
pub fn get_current_view(&self) -> &View {
|
||||
self.views.get(&self.current_view).expect("Selected nonexistent view")
|
||||
&self.get_current_view_position().1
|
||||
}
|
||||
|
||||
fn set_view(&mut self, view: String) -> Result<(), NoSuchView> {
|
||||
@ -668,16 +686,9 @@ impl Layout {
|
||||
|
||||
/// Calculates size without margins
|
||||
fn calculate_inner_size(&self) -> Size {
|
||||
Size {
|
||||
height: find_max_double(
|
||||
self.views.iter(),
|
||||
|(_name, view)| view.get_height(),
|
||||
),
|
||||
width: find_max_double(
|
||||
self.views.iter(),
|
||||
|(_name, view)| view.get_width(),
|
||||
),
|
||||
}
|
||||
View::calculate_super_size(
|
||||
self.views.iter().map(|(_, (_offset, v))| v).collect()
|
||||
)
|
||||
}
|
||||
|
||||
/// Size including margins
|
||||
@ -712,6 +723,11 @@ impl Layout {
|
||||
scale: 1.0,
|
||||
})
|
||||
}
|
||||
|
||||
fn find_button_by_position(&self, point: c::Point) -> Option<ButtonPlace> {
|
||||
let (offset, layout) = self.get_current_view_position();
|
||||
layout.find_button_by_position(point - offset)
|
||||
}
|
||||
}
|
||||
|
||||
mod procedures {
|
||||
@ -1068,7 +1084,7 @@ mod test {
|
||||
bottom: 1.0,
|
||||
},
|
||||
views: hashmap! {
|
||||
String::new() => view,
|
||||
String::new() => (c::Point { x: 0.0, y: 0.0 }, view),
|
||||
},
|
||||
};
|
||||
assert_eq!(
|
||||
|
||||
@ -60,7 +60,7 @@ fn check_layout(layout: Layout) {
|
||||
let state = xkb::State::new(&keymap);
|
||||
|
||||
// "Press" each button with keysyms
|
||||
for view in layout.views.values() {
|
||||
for (_pos, view) in layout.views.values() {
|
||||
for (_y, row) in &view.get_rows() {
|
||||
for (_x, button) in &row.buttons {
|
||||
let keystate = button.state.borrow();
|
||||
|
||||
Reference in New Issue
Block a user