Merge branch 'center' into 'master'
Center views relative to layout space See merge request Librem5/squeekboard!326
This commit is contained in:
34
src/data.rs
34
src/data.rs
@ -424,8 +424,8 @@ impl Layout {
|
|||||||
)}
|
)}
|
||||||
);
|
);
|
||||||
|
|
||||||
let views = HashMap::from_iter(
|
let views: Vec<_> = self.views.iter()
|
||||||
self.views.iter().map(|(name, view)| {
|
.map(|(name, view)| {
|
||||||
let rows = view.iter().map(|row| {
|
let rows = view.iter().map(|row| {
|
||||||
let buttons = row.split_ascii_whitespace()
|
let buttons = row.split_ascii_whitespace()
|
||||||
.map(|name| {
|
.map(|name| {
|
||||||
@ -439,8 +439,7 @@ impl Layout {
|
|||||||
&mut warning_handler,
|
&mut warning_handler,
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
::layout::Row {
|
layout::Row {
|
||||||
angle: 0,
|
|
||||||
buttons: add_offsets(
|
buttons: add_offsets(
|
||||||
buttons,
|
buttons,
|
||||||
|button| button.size.width,
|
|button| button.size.width,
|
||||||
@ -453,8 +452,25 @@ impl Layout {
|
|||||||
name.clone(),
|
name.clone(),
|
||||||
layout::View::new(rows)
|
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 {
|
Ok(::layout::LayoutData {
|
||||||
@ -751,7 +767,7 @@ mod tests {
|
|||||||
.build(ProblemPanic).0
|
.build(ProblemPanic).0
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
out.views["base"]
|
out.views["base"].1
|
||||||
.get_rows()[0].1
|
.get_rows()[0].1
|
||||||
.buttons[0].1
|
.buttons[0].1
|
||||||
.label,
|
.label,
|
||||||
@ -766,7 +782,7 @@ mod tests {
|
|||||||
.build(ProblemPanic).0
|
.build(ProblemPanic).0
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
out.views["base"]
|
out.views["base"].1
|
||||||
.get_rows()[0].1
|
.get_rows()[0].1
|
||||||
.buttons[0].1
|
.buttons[0].1
|
||||||
.label,
|
.label,
|
||||||
@ -782,7 +798,7 @@ mod tests {
|
|||||||
.build(ProblemPanic).0
|
.build(ProblemPanic).0
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
out.views["base"]
|
out.views["base"].1
|
||||||
.get_rows()[0].1
|
.get_rows()[0].1
|
||||||
.buttons[0].1
|
.buttons[0].1
|
||||||
.state.borrow()
|
.state.borrow()
|
||||||
|
|||||||
@ -48,21 +48,18 @@ mod c {
|
|||||||
let layout = unsafe { &mut *layout };
|
let layout = unsafe { &mut *layout };
|
||||||
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
||||||
|
|
||||||
let view = layout.get_current_view();
|
layout.foreach_visible_button(|offset, button| {
|
||||||
for (row_offset, row) in &view.get_rows() {
|
let state = RefCell::borrow(&button.state).clone();
|
||||||
for (x_offset, button) in &row.buttons {
|
let locked = state.action.is_active(&layout.current_view);
|
||||||
let state = RefCell::borrow(&button.state).clone();
|
if state.pressed == keyboard::PressType::Pressed || locked {
|
||||||
let locked = state.action.is_active(&layout.current_view);
|
render_button_at_position(
|
||||||
if state.pressed == keyboard::PressType::Pressed || locked {
|
renderer, &cr,
|
||||||
render_button_at_position(
|
offset,
|
||||||
renderer, &cr,
|
button.as_ref(),
|
||||||
row_offset + Point { x: *x_offset, y: 0.0 },
|
state.pressed, locked,
|
||||||
button.as_ref(),
|
);
|
||||||
state.pressed, locked,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -74,17 +71,15 @@ mod c {
|
|||||||
) {
|
) {
|
||||||
let layout = unsafe { &mut *layout };
|
let layout = unsafe { &mut *layout };
|
||||||
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
||||||
let view = layout.get_current_view();
|
|
||||||
for (row_offset, row) in &view.get_rows() {
|
layout.foreach_visible_button(|offset, button| {
|
||||||
for (x_offset, button) in &row.buttons {
|
render_button_at_position(
|
||||||
render_button_at_position(
|
renderer, &cr,
|
||||||
renderer, &cr,
|
offset,
|
||||||
row_offset + Point { x: *x_offset, y: 0.0 },
|
button.as_ref(),
|
||||||
button.as_ref(),
|
keyboard::PressType::Released, false,
|
||||||
keyboard::PressType::Released, false,
|
);
|
||||||
);
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -329,11 +329,8 @@ pub mod c {
|
|||||||
Point { x: x_widget, y: y_widget }
|
Point { x: x_widget, y: y_widget }
|
||||||
);
|
);
|
||||||
|
|
||||||
let state = {
|
let state = layout.find_button_by_position(point)
|
||||||
let view = layout.get_current_view();
|
.map(|place| place.button.state.clone());
|
||||||
view.find_button_by_position(point)
|
|
||||||
.map(|place| place.button.state.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(state) = state {
|
if let Some(state) = state {
|
||||||
seat::handle_press_key(
|
seat::handle_press_key(
|
||||||
@ -374,8 +371,7 @@ pub mod c {
|
|||||||
|
|
||||||
let pressed = layout.pressed_keys.clone();
|
let pressed = layout.pressed_keys.clone();
|
||||||
let button_info = {
|
let button_info = {
|
||||||
let view = layout.get_current_view();
|
let place = layout.find_button_by_position(point);
|
||||||
let place = view.find_button_by_position(point);
|
|
||||||
place.map(|place| {(
|
place.map(|place| {(
|
||||||
place.button.state.clone(),
|
place.button.state.clone(),
|
||||||
place.button.clone(),
|
place.button.clone(),
|
||||||
@ -486,8 +482,6 @@ pub struct Button {
|
|||||||
pub struct Row {
|
pub struct Row {
|
||||||
/// Buttons together with their offset from the left
|
/// Buttons together with their offset from the left
|
||||||
pub buttons: Vec<(f64, Box<Button>)>,
|
pub buttons: Vec<(f64, Box<Button>)>,
|
||||||
/// Angle is not really used anywhere...
|
|
||||||
pub angle: i32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Row {
|
impl Row {
|
||||||
@ -554,14 +548,14 @@ impl View {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_width(&self) -> f64 {
|
pub fn get_width(&self) -> f64 {
|
||||||
// No need to call `get_rows()`,
|
// No need to call `get_rows()`,
|
||||||
// as the biggest row is the most far reaching in both directions
|
// as the biggest row is the most far reaching in both directions
|
||||||
// because they are all centered.
|
// because they are all centered.
|
||||||
find_max_double(self.rows.iter(), |(_offset, row)| row.get_width())
|
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()
|
self.rows.iter().next_back()
|
||||||
.map(|(y_offset, row)| row.get_height() + y_offset)
|
.map(|(y_offset, row)| row.get_height() + y_offset)
|
||||||
.unwrap_or(0.0)
|
.unwrap_or(0.0)
|
||||||
@ -578,6 +572,21 @@ impl View {
|
|||||||
row,
|
row,
|
||||||
)}).collect()
|
)}).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
|
/// The physical characteristic of layout for the purpose of styling
|
||||||
@ -605,7 +614,8 @@ pub struct Layout {
|
|||||||
// Views own the actual buttons which have state
|
// Views own the actual buttons which have state
|
||||||
// Maybe they should own UI only,
|
// Maybe they should own UI only,
|
||||||
// and keys should be owned by a dedicated non-UI-State?
|
// 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
|
// Non-UI stuff
|
||||||
/// xkb keymap applicable to the contained keys. Unchangeable
|
/// xkb keymap applicable to the contained keys. Unchangeable
|
||||||
@ -623,7 +633,8 @@ pub struct Layout {
|
|||||||
|
|
||||||
/// A builder structure for picking up layout data from storage
|
/// A builder structure for picking up layout data from storage
|
||||||
pub struct LayoutData {
|
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 keymap_str: CString,
|
||||||
pub margins: Margins,
|
pub margins: Margins,
|
||||||
}
|
}
|
||||||
@ -653,8 +664,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 {
|
pub fn get_current_view(&self) -> &View {
|
||||||
self.views.get(&self.current_view).expect("Selected nonexistent view")
|
&self.views.get(&self.current_view).expect("Selected nonexistent view").1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_view(&mut self, view: String) -> Result<(), NoSuchView> {
|
fn set_view(&mut self, view: String) -> Result<(), NoSuchView> {
|
||||||
@ -668,16 +684,9 @@ impl Layout {
|
|||||||
|
|
||||||
/// Calculates size without margins
|
/// Calculates size without margins
|
||||||
fn calculate_inner_size(&self) -> Size {
|
fn calculate_inner_size(&self) -> Size {
|
||||||
Size {
|
View::calculate_super_size(
|
||||||
height: find_max_double(
|
self.views.iter().map(|(_, (_offset, v))| v).collect()
|
||||||
self.views.iter(),
|
)
|
||||||
|(_name, view)| view.get_height(),
|
|
||||||
),
|
|
||||||
width: find_max_double(
|
|
||||||
self.views.iter(),
|
|
||||||
|(_name, view)| view.get_width(),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Size including margins
|
/// Size including margins
|
||||||
@ -713,6 +722,25 @@ impl Layout {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn foreach_visible_button<F>(&self, mut f: F)
|
||||||
|
where F: FnMut(c::Point, &Box<Button>)
|
||||||
|
{
|
||||||
|
let (view_offset, view) = self.get_current_view_position();
|
||||||
|
for (row_offset, row) in &view.get_rows() {
|
||||||
|
for (x_offset, button) in &row.buttons {
|
||||||
|
let offset = view_offset
|
||||||
|
+ row_offset.clone()
|
||||||
|
+ c::Point { x: *x_offset, y: 0.0 };
|
||||||
|
f(offset, button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_locked_keys(&self) -> Vec<Rc<RefCell<KeyState>>> {
|
pub fn get_locked_keys(&self) -> Vec<Rc<RefCell<KeyState>>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
let view = self.get_current_view();
|
let view = self.get_current_view();
|
||||||
@ -780,7 +808,6 @@ mod procedures {
|
|||||||
|
|
||||||
let row = Row {
|
let row = Row {
|
||||||
buttons: vec!((0.1, button)),
|
buttons: vec!((0.1, button)),
|
||||||
angle: 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let view = View {
|
let view = View {
|
||||||
@ -853,7 +880,6 @@ mod seat {
|
|||||||
// This is guaranteed because pressing a lock button unlocks all others.
|
// This is guaranteed because pressing a lock button unlocks all others.
|
||||||
// TODO: Make some broader guarantee about the resulting view,
|
// TODO: Make some broader guarantee about the resulting view,
|
||||||
// e.g. by maintaining a stack of stuck keys.
|
// e.g. by maintaining a stack of stuck keys.
|
||||||
// FIXME: This doesn't record changes in layout.locked_keys
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn unstick_locks(layout: &mut Layout) -> ViewChange {
|
fn unstick_locks(layout: &mut Layout) -> ViewChange {
|
||||||
let mut new_view = None;
|
let mut new_view = None;
|
||||||
@ -1010,7 +1036,6 @@ mod test {
|
|||||||
(
|
(
|
||||||
0.0,
|
0.0,
|
||||||
Row {
|
Row {
|
||||||
angle: 0,
|
|
||||||
buttons: vec![(
|
buttons: vec![(
|
||||||
0.0,
|
0.0,
|
||||||
Box::new(Button {
|
Box::new(Button {
|
||||||
@ -1023,7 +1048,6 @@ mod test {
|
|||||||
(
|
(
|
||||||
10.0,
|
10.0,
|
||||||
Row {
|
Row {
|
||||||
angle: 0,
|
|
||||||
buttons: vec![(
|
buttons: vec![(
|
||||||
0.0,
|
0.0,
|
||||||
Box::new(Button {
|
Box::new(Button {
|
||||||
@ -1047,7 +1071,6 @@ mod test {
|
|||||||
(
|
(
|
||||||
0.0,
|
0.0,
|
||||||
Row {
|
Row {
|
||||||
angle: 0,
|
|
||||||
buttons: vec![(
|
buttons: vec![(
|
||||||
0.0,
|
0.0,
|
||||||
Box::new(Button {
|
Box::new(Button {
|
||||||
@ -1071,7 +1094,7 @@ mod test {
|
|||||||
bottom: 1.0,
|
bottom: 1.0,
|
||||||
},
|
},
|
||||||
views: hashmap! {
|
views: hashmap! {
|
||||||
String::new() => view,
|
String::new() => (c::Point { x: 0.0, y: 0.0 }, view),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@ -60,7 +60,7 @@ fn check_layout(layout: Layout) {
|
|||||||
let state = xkb::State::new(&keymap);
|
let state = xkb::State::new(&keymap);
|
||||||
|
|
||||||
// "Press" each button with keysyms
|
// "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 (_y, row) in &view.get_rows() {
|
||||||
for (_x, button) in &row.buttons {
|
for (_x, button) in &row.buttons {
|
||||||
let keystate = button.state.borrow();
|
let keystate = button.state.borrow();
|
||||||
|
|||||||
Reference in New Issue
Block a user