Merge branch 'margins' into 'master'
Use margins, remove bounds See merge request Librem5/squeekboard!283
This commit is contained in:
@ -1,18 +1,11 @@
|
|||||||
# Maintained by: Mark Müller <markmueller86@gmail.com>
|
# Maintained by: Mark Müller <markmueller86@gmail.com>
|
||||||
---
|
---
|
||||||
bounds: { x: 0, y: 1, width: 360, height: 208 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 35.33, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
|
altline: { width: 52.67, height: 52 }
|
||||||
altline:
|
wide: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
|
spaceline: { width: 99.67, height: 52 }
|
||||||
wide:
|
special: { width: 35.33, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 99.67, height: 52 }
|
|
||||||
special:
|
|
||||||
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -1,18 +1,11 @@
|
|||||||
# Maintained by: Mark Müller <markmueller86@gmail.com>
|
# Maintained by: Mark Müller <markmueller86@gmail.com>
|
||||||
---
|
---
|
||||||
bounds: { x: 0, y: 1, width: 540, height: 168 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 48, height: 42 }
|
||||||
bounds: { x: 0, y: 0, width: 48, height: 42 }
|
altline: { width: 81, height: 42 }
|
||||||
altline:
|
wide: { width: 108, height: 42 }
|
||||||
bounds: { x: 0, y: 0, width: 81, height: 42 }
|
spaceline: { width: 216, height: 42 }
|
||||||
wide:
|
special: { width: 48, height: 42 }
|
||||||
bounds: { x: 0, y: 0, width: 108, height: 42 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 216, height: 42 }
|
|
||||||
special:
|
|
||||||
bounds: { x: 0, y: 0, width: 48, height: 42 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -2,19 +2,12 @@
|
|||||||
# University of the Aegean, Department of Mathematics, atsol@aegean.gr
|
# University of the Aegean, Department of Mathematics, atsol@aegean.gr
|
||||||
# Sep 2019
|
# Sep 2019
|
||||||
---
|
---
|
||||||
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 32, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 32, height: 52 }
|
altline: { width: 48.39024, height: 52 }
|
||||||
altline:
|
wide: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
outline7: { width: 88.97561, height: 52 }
|
||||||
wide:
|
spaceline: { width: 150.5853, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
outline7:
|
|
||||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -1,17 +1,10 @@
|
|||||||
---
|
---
|
||||||
bounds: { x: 0, y: 1, width: 360, height: 210 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 35.33, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
|
altline: { width: 52.67, height: 52 }
|
||||||
altline:
|
wide: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
|
spaceline: { width: 99.67, height: 52 }
|
||||||
wide:
|
special: { width: 44, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 99.67, height: 52 }
|
|
||||||
special:
|
|
||||||
bounds: { x: 0, y: 0, width: 44, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -1,17 +1,10 @@
|
|||||||
---
|
---
|
||||||
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 32, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 32, height: 52 }
|
altline: { width: 48.39024, height: 52 }
|
||||||
altline:
|
wide: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
outline7: { width: 88.97561, height: 52 }
|
||||||
wide:
|
spaceline: { width: 150.5853, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
outline7:
|
|
||||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -1,19 +1,12 @@
|
|||||||
# Italian layout created by Antonio Pandolfo
|
# Italian layout created by Antonio Pandolfo
|
||||||
# 03 october 2019
|
# 03 october 2019
|
||||||
---
|
---
|
||||||
bounds: { x: 0, y: 1, width: 360, height: 210 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 35.33, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
|
altline: { width: 52.67, height: 52 }
|
||||||
altline:
|
wide: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
|
spaceline: { width: 99.67, height: 52 }
|
||||||
wide:
|
special: { width: 44, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 99.67, height: 52 }
|
|
||||||
special:
|
|
||||||
bounds: { x: 0, y: 0, width: 44, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -1,18 +1,11 @@
|
|||||||
# Maintained by: Mark Müller <markmueller86@gmail.com>
|
# Maintained by: Mark Müller <markmueller86@gmail.com>
|
||||||
---
|
---
|
||||||
bounds: { x: 0, y: 1, width: 360, height: 208 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
default-wide: { width: 62, height: 52 }
|
||||||
default-wide:
|
altline: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
wide: { width: 62, height: 52 }
|
||||||
altline:
|
special: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
wide:
|
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
special:
|
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base: # hiragana
|
base: # hiragana
|
||||||
|
|||||||
@ -1,18 +1,11 @@
|
|||||||
# Maintained by: Mark Müller <markmueller86@gmail.com>
|
# Maintained by: Mark Müller <markmueller86@gmail.com>
|
||||||
---
|
---
|
||||||
bounds: { x: 0, y: 1, width: 540, height: 168 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 62, height: 42 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 42 }
|
default-wide: { width: 62, height: 42 }
|
||||||
default-wide:
|
altline: { width: 62, height: 42 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 42 }
|
wide: { width: 62, height: 42 }
|
||||||
altline:
|
special: { width: 62, height: 42 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 42 }
|
|
||||||
wide:
|
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 42 }
|
|
||||||
special:
|
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 42 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base: # hiragana
|
base: # hiragana
|
||||||
|
|||||||
@ -1,17 +1,10 @@
|
|||||||
---
|
---
|
||||||
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 32, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 32, height: 52 }
|
altline: { width: 48.39024, height: 52 }
|
||||||
altline:
|
wide: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
outline7: { width: 88.97561, height: 52 }
|
||||||
wide:
|
spaceline: { width: 150.5853, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
outline7:
|
|
||||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -1,15 +1,9 @@
|
|||||||
---
|
---
|
||||||
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 37.46341, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 37.46341, height: 52 }
|
altline: { width: 48.39024, height: 52 }
|
||||||
altline:
|
outline7: { width: 88.97561, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
spaceline: { width: 120.5853, height: 52 }
|
||||||
outline7:
|
|
||||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 120.5853, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -1,17 +1,10 @@
|
|||||||
---
|
---
|
||||||
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 32, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 32, height: 52 }
|
altline: { width: 48.39024, height: 52 }
|
||||||
altline:
|
wide: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
outline7: { width: 88.97561, height: 52 }
|
||||||
wide:
|
spaceline: { width: 150.5853, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
outline7:
|
|
||||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -1,17 +1,10 @@
|
|||||||
---
|
---
|
||||||
bounds: { x: 0, y: 1, width: 360, height: 208 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 35.33, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
|
altline: { width: 52.67, height: 52 }
|
||||||
altline:
|
wide: { width: 62, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
|
spaceline: { width: 142, height: 52 }
|
||||||
wide:
|
special: { width: 44, height: 52 }
|
||||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 142, height: 52 }
|
|
||||||
special:
|
|
||||||
bounds: { x: 0, y: 0, width: 44, height: 52 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
@ -1,17 +1,10 @@
|
|||||||
---
|
---
|
||||||
bounds: { x: 0, y: 1, width: 540, height: 168 }
|
|
||||||
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 54, height: 42 }
|
||||||
bounds: { x: 0, y: 0, width: 54, height: 42 }
|
altline: { width: 81, height: 42 }
|
||||||
altline:
|
wide: { width: 108, height: 42 }
|
||||||
bounds: { x: 0, y: 0, width: 81, height: 42 }
|
spaceline: { width: 216, height: 42 }
|
||||||
wide:
|
special: { width: 54, height: 42 }
|
||||||
bounds: { x: 0, y: 0, width: 108, height: 42 }
|
|
||||||
spaceline:
|
|
||||||
bounds: { x: 0, y: 0, width: 216, height: 42 }
|
|
||||||
special:
|
|
||||||
bounds: { x: 0, y: 0, width: 54, height: 42 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
|
|||||||
62
src/data.rs
62
src/data.rs
@ -1,5 +1,7 @@
|
|||||||
/**! The parsing of the data files for layouts */
|
/**! The parsing of the data files for layouts */
|
||||||
|
|
||||||
|
// TODO: find a nice way to make sure non-positive sizes don't break layouts
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{ HashMap, HashSet };
|
use std::collections::{ HashMap, HashSet };
|
||||||
use std::env;
|
use std::env;
|
||||||
@ -216,21 +218,20 @@ fn load_layout_data_with_fallback(
|
|||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
/// FIXME: deprecate in favor of margins
|
#[serde(default)]
|
||||||
bounds: Bounds,
|
margins: Margins,
|
||||||
views: HashMap<String, Vec<ButtonIds>>,
|
views: HashMap<String, Vec<ButtonIds>>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
buttons: HashMap<String, ButtonMeta>,
|
buttons: HashMap<String, ButtonMeta>,
|
||||||
outlines: HashMap<String, Outline>
|
outlines: HashMap<String, Outline>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Deserialize, PartialEq, Default)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
struct Bounds {
|
struct Margins {
|
||||||
x: f64,
|
top: f64,
|
||||||
y: f64,
|
bottom: f64,
|
||||||
width: f64,
|
side: f64,
|
||||||
height: f64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Buttons are embedded in a single string
|
/// Buttons are embedded in a single string
|
||||||
@ -271,8 +272,8 @@ enum Action {
|
|||||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
struct Outline {
|
struct Outline {
|
||||||
/// FIXME: replace with Size
|
width: f64,
|
||||||
bounds: Bounds,
|
height: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Errors encountered loading the layout into yaml
|
/// Errors encountered loading the layout into yaml
|
||||||
@ -460,10 +461,10 @@ impl Layout {
|
|||||||
},
|
},
|
||||||
// FIXME: use a dedicated field
|
// FIXME: use a dedicated field
|
||||||
margins: layout::Margins {
|
margins: layout::Margins {
|
||||||
top: self.bounds.x,
|
top: self.margins.top,
|
||||||
left: self.bounds.y,
|
left: self.margins.side,
|
||||||
bottom: 0.0,
|
bottom: self.margins.bottom,
|
||||||
right: self.bounds.y,
|
right: self.margins.side,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
warning_handler,
|
warning_handler,
|
||||||
@ -649,9 +650,7 @@ fn create_button<H: WarningHandler>(
|
|||||||
warning_handler.handle(
|
warning_handler.handle(
|
||||||
&format!("No default outline defined! Using 1x1!")
|
&format!("No default outline defined! Using 1x1!")
|
||||||
);
|
);
|
||||||
Outline {
|
Outline { width: 1f64, height: 1f64 }
|
||||||
bounds: Bounds { x: 0f64, y: 0f64, width: 1f64, height: 1f64 },
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
layout::Button {
|
layout::Button {
|
||||||
@ -659,8 +658,8 @@ fn create_button<H: WarningHandler>(
|
|||||||
outline_name: CString::new(outline_name).expect("Bad outline"),
|
outline_name: CString::new(outline_name).expect("Bad outline"),
|
||||||
// TODO: do layout before creating buttons
|
// TODO: do layout before creating buttons
|
||||||
size: layout::Size {
|
size: layout::Size {
|
||||||
width: outline.bounds.width,
|
width: outline.width,
|
||||||
height: outline.bounds.height,
|
height: outline.height,
|
||||||
},
|
},
|
||||||
label: label,
|
label: label,
|
||||||
state: state,
|
state: state,
|
||||||
@ -686,7 +685,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Layout::from_file(PathBuf::from("tests/layout.yaml")).unwrap(),
|
Layout::from_file(PathBuf::from("tests/layout.yaml")).unwrap(),
|
||||||
Layout {
|
Layout {
|
||||||
bounds: Bounds { x: 0f64, y: 0f64, width: 0f64, height: 0f64 },
|
margins: Margins { top: 0f64, bottom: 0f64, side: 0f64 },
|
||||||
views: hashmap!(
|
views: hashmap!(
|
||||||
"base".into() => vec!("test".into()),
|
"base".into() => vec!("test".into()),
|
||||||
),
|
),
|
||||||
@ -701,11 +700,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
outlines: hashmap!{
|
outlines: hashmap!{
|
||||||
"default".into() => Outline {
|
"default".into() => Outline { width: 0f64, height: 0f64 },
|
||||||
bounds: Bounds {
|
|
||||||
x: 0f64, y: 0f64, width: 0f64, height: 0f64
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -855,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)]
|
#[repr(C)]
|
||||||
pub struct Transformation {
|
pub struct Transformation {
|
||||||
pub origin_x: f64,
|
pub origin_x: f64,
|
||||||
@ -108,6 +108,14 @@ pub mod c {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Transformation {
|
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 {
|
fn forward(&self, p: Point) -> Point {
|
||||||
Point {
|
Point {
|
||||||
x: (p.x - self.origin_x) / self.scale,
|
x: (p.x - self.origin_x) / self.scale,
|
||||||
@ -195,7 +203,8 @@ pub mod c {
|
|||||||
println!("{:?}", button);
|
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]
|
#[no_mangle]
|
||||||
pub extern "C"
|
pub extern "C"
|
||||||
fn squeek_layout_calculate_transformation(
|
fn squeek_layout_calculate_transformation(
|
||||||
@ -204,15 +213,10 @@ pub mod c {
|
|||||||
allocation_height: f64,
|
allocation_height: f64,
|
||||||
) -> Transformation {
|
) -> Transformation {
|
||||||
let layout = unsafe { &*layout };
|
let layout = unsafe { &*layout };
|
||||||
let size = layout.calculate_size();
|
layout.calculate_transformation(Size {
|
||||||
let h_scale = allocation_width / size.width;
|
width: allocation_width,
|
||||||
let v_scale = allocation_height / size.height;
|
height: allocation_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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -427,7 +431,7 @@ pub struct ButtonPlace<'a> {
|
|||||||
offset: c::Point,
|
offset: c::Point,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Size {
|
pub struct Size {
|
||||||
pub width: f64,
|
pub width: f64,
|
||||||
pub height: f64,
|
pub height: f64,
|
||||||
@ -560,6 +564,7 @@ pub enum ArrangementKind {
|
|||||||
Wide = 1,
|
Wide = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Margins {
|
pub struct Margins {
|
||||||
pub top: f64,
|
pub top: f64,
|
||||||
pub bottom: 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 {
|
Size {
|
||||||
height: find_max_double(
|
height: find_max_double(
|
||||||
self.views.iter(),
|
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 {
|
mod procedures {
|
||||||
@ -907,4 +946,58 @@ mod test {
|
|||||||
.is_none()
|
.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,9 @@
|
|||||||
---
|
---
|
||||||
bounds:
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
- "test"
|
- "test"
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 0, height: 0 }
|
||||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
|
||||||
|
|
||||||
buttons:
|
buttons:
|
||||||
test:
|
test:
|
||||||
|
|||||||
@ -1,11 +1,5 @@
|
|||||||
---
|
---
|
||||||
# missing views
|
# missing views
|
||||||
bounds:
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 0, height: 0 }
|
||||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,9 @@
|
|||||||
---
|
---
|
||||||
# extra field
|
# extra field
|
||||||
bounds:
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
- "test"
|
- "test"
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 0, height: 0 }
|
||||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
|
||||||
|
|
||||||
bad_field: false
|
bad_field: false
|
||||||
|
|||||||
@ -1,16 +1,10 @@
|
|||||||
---
|
---
|
||||||
# punctuation
|
# punctuation
|
||||||
bounds:
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
- "."
|
- "."
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 0, height: 0 }
|
||||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
|
||||||
|
|
||||||
buttons:
|
buttons:
|
||||||
".":
|
".":
|
||||||
|
|||||||
@ -1,16 +1,10 @@
|
|||||||
---
|
---
|
||||||
# punctuation
|
# punctuation
|
||||||
bounds:
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
- "å"
|
- "å"
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 0, height: 0 }
|
||||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
|
||||||
|
|
||||||
buttons:
|
buttons:
|
||||||
å:
|
å:
|
||||||
|
|||||||
@ -1,14 +1,8 @@
|
|||||||
---
|
---
|
||||||
# punctuation
|
# punctuation
|
||||||
bounds:
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
- "か゚" # 2 codepoints
|
- "か゚" # 2 codepoints
|
||||||
outlines:
|
outlines:
|
||||||
default:
|
default: { width: 0, height: 0 }
|
||||||
bounds: { x: 0, y: 0, width: 0, height: 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