use chrono::{DateTime, Local, Utc};
#[cfg(test)]
use chrono::NaiveDateTime;
-use core::cmp::min;
+use core::cmp::{min, max};
use std::collections::{HashMap, BTreeMap, BTreeSet};
use unicode_width::UnicodeWidthStr;
fn render(&self, width: usize) -> Vec<ColouredString>;
fn as_extendable_indicator(&self) -> Option<&ExtendableIndicator> { None }
+ fn as_menu_keypress_mut(&mut self) -> Option<&mut MenuKeypressLine> {
+ None
+ }
}
pub struct BlankLine {}
}
}
- // FIXME: get rid of this silly trait method if I turn out not to need it
- fn as_extendable_indicator(&self) -> Option<&ExtendableIndicator> {
+ fn as_extendable_indicator_mut(&self) -> Option<&ExtendableIndicator> {
Some(self)
}
}
});
}
-// TODO:
-// MenuKeypressLine
+pub struct MenuKeypressLine {
+ keypress: Keypress,
+ lwid: usize,
+ lmaxwid: usize,
+ rmaxwid: usize,
+}
+
+impl MenuKeypressLine {
+ pub fn new(key: Key, description: ColouredString) -> Box<dyn TextFragment> {
+ let lwid = UnicodeWidthStr::width(&key as &str) + 2; // [] around it
+ let rwid = description.width();
+ Box::new(MenuKeypressLine {
+ keypress: Keypress {
+ key: key,
+ description: description,
+ },
+ lwid: lwid,
+ lmaxwid: lwid,
+ rmaxwid: rwid,
+ })
+ }
+
+ pub fn get_widths(&self) -> (usize, usize) { (self.lmaxwid, self.rmaxwid) }
+ pub fn ensure_widths(&mut self, lmaxwid: usize, rmaxwid: usize) {
+ self.lmaxwid = max(self.lmaxwid, lmaxwid);
+ self.rmaxwid = max(self.rmaxwid, rmaxwid);
+ }
+}
+
+impl TextFragment for MenuKeypressLine {
+ fn render(&self, width: usize) -> Vec<ColouredString> {
+ let ourwidth = self.lmaxwid + self.rmaxwid + 3; // " = " in the middle
+ let space = width - min(width, ourwidth + 1);
+ let leftpad = min(space * 3 / 4, width - min(width, self.lmaxwid + 2));
+
+ let lspace = self.lmaxwid - self.lwid;
+ let llspace = lspace / 2;
+ let lrspace = lspace - llspace;
+
+ let line = ColouredString::plain(" ").repeat(leftpad + llspace) +
+ ColouredString::plain("[") +
+ ColouredString::uniform(&self.keypress.key, 'k') +
+ ColouredString::plain("]") +
+ ColouredString::plain(" ").repeat(lrspace) +
+ ColouredString::plain(" = ") +
+ &self.keypress.description;
+
+ vec! {
+ line.truncate(width).to_owned()
+ }
+ }
+
+ fn as_menu_keypress_mut(&mut self) -> Option<&mut MenuKeypressLine> {
+ Some(self)
+ }
+}
+
+#[test]
+fn test_menu_keypress() {
+ let mut mk = MenuKeypressLine::new("S".to_owned(), ColouredString::general(
+ "Something or other",
+ "K "));
+
+ assert_eq!(mk.render(40), vec! {
+ ColouredString::general(
+ " [S] = Something or other",
+ " k K "),
+ });
+
+ assert_eq!(mk.render(29), vec! {
+ ColouredString::general(
+ " [S] = Something or other",
+ " k K "),
+ });
+
+ mk.as_menu_keypress_mut().unwrap().ensure_widths(5, 0);
+
+ assert_eq!(mk.render(40), vec! {
+ ColouredString::general(
+ " [S] = Something or other",
+ " k K "),
+ });
+}