use std::iter::once;
-use strum::IntoEnumIterator;
use sys_locale::get_locale;
use super::client::{Client, ClientError};
ml_post: MenuKeypressLine,
ml_cancel: MenuKeypressLine,
ml_edit: MenuKeypressLine,
- ml_vis: MenuKeypressLine,
+ cl_vis: CyclingMenuLine<Visibility>,
el_content_warning: EditableMenuLine<Option<String>>,
el_language: EditableMenuLine<String>,
}
Pr('Q'), ColouredString::plain("Cancel post"));
let ml_edit = MenuKeypressLine::new(
Pr('A'), ColouredString::plain("Re-edit post"));
- let ml_vis = Self::visibility_item(post.m.visibility);
+ let cl_vis = CyclingMenuLine::new(
+ Pr('V'), ColouredString::plain("Visibility: "), &[
+ (Visibility::Public, ColouredString::uniform("public", 'f')),
+ (Visibility::Unlisted, ColouredString::plain(
+ "unlisted (anyone can see it, but feeds omit it)")),
+ (Visibility::Private, ColouredString::general(
+ "private (followees and @mentioned users can see it)",
+ "rrrrrrr ")),
+ (Visibility::Direct, ColouredString::general(
+ "direct (only @mentioned users can see it)",
+ "rrrrrr ")),
+ ], post.m.visibility);
let el_content_warning = EditableMenuLine::new(
Pr('W'), ColouredString::plain("Content warning: "),
post.m.content_warning.clone());
ml_post,
ml_cancel,
ml_edit,
- ml_vis,
+ cl_vis,
el_content_warning,
el_language,
};
self.ml_post.check_widths(&mut lmaxwid, &mut rmaxwid);
self.ml_cancel.check_widths(&mut lmaxwid, &mut rmaxwid);
self.ml_edit.check_widths(&mut lmaxwid, &mut rmaxwid);
+ self.cl_vis.check_widths(&mut lmaxwid, &mut rmaxwid);
self.el_content_warning.check_widths(&mut lmaxwid, &mut rmaxwid);
self.el_language.check_widths(&mut lmaxwid, &mut rmaxwid);
- for vis in Visibility::iter() {
- Self::visibility_item(vis).check_widths(&mut lmaxwid, &mut rmaxwid);
- }
self.ml_post.reset_widths();
self.ml_cancel.reset_widths();
self.ml_edit.reset_widths();
- self.ml_vis.reset_widths();
+ self.cl_vis.reset_widths();
self.el_content_warning.reset_widths();
self.el_language.reset_widths();
self.ml_post.ensure_widths(lmaxwid, rmaxwid);
self.ml_cancel.ensure_widths(lmaxwid, rmaxwid);
self.ml_edit.ensure_widths(lmaxwid, rmaxwid);
- self.ml_vis.ensure_widths(lmaxwid, rmaxwid);
+ self.cl_vis.ensure_widths(lmaxwid, rmaxwid);
self.el_content_warning.ensure_widths(lmaxwid, rmaxwid);
self.el_language.ensure_widths(lmaxwid, rmaxwid);
(lmaxwid, rmaxwid)
}
- fn visibility_item(vis: Visibility) -> MenuKeypressLine {
- let text = match vis {
- Visibility::Public => ColouredString::general(
- "Visibility: public",
- " ffffff"),
- Visibility::Unlisted => ColouredString::general(
- "Visibility: unlisted (anyone can see it, but feeds omit it)",
- " "),
- Visibility::Private => ColouredString::general(
- "Visibility: private (followees and @mentioned users can see it)",
- " rrrrrrr "),
- Visibility::Direct => ColouredString::general(
- "Visibility: direct (only @mentioned users can see it)",
- " rrrrrr "),
- };
- MenuKeypressLine::new(Pr('V'), text)
- }
-
- fn cycle_visibility(&mut self) -> LogicalAction {
- self.post.m.visibility = match self.post.m.visibility {
- Visibility::Public => Visibility::Unlisted,
- Visibility::Unlisted => Visibility::Private,
- Visibility::Private => Visibility::Direct,
- Visibility::Direct => Visibility::Public,
- };
- self.ml_vis = Self::visibility_item(self.post.m.visibility);
- self.fix_widths();
- LogicalAction::Nothing
- }
-
fn post(&mut self, client: &mut Client) -> LogicalAction {
+ self.post.m.visibility = self.cl_vis.get_value();
self.post.m.content_warning =
self.el_content_warning.get_data().clone();
self.post.m.language = self.el_language.get_data().clone();
lines.extend_from_slice(&self.ml_cancel.render(w));
lines.extend_from_slice(&self.ml_edit.render(w));
lines.extend_from_slice(&BlankLine::render_static());
- lines.extend_from_slice(&self.ml_vis.render(w));
+ lines.extend_from_slice(&self.cl_vis.render(w));
lines.push(self.el_content_warning.render(
w, &mut cursorpos, lines.len()));
lines.push(self.el_language.render(
Pr('q') | Pr('Q') => LogicalAction::Pop,
Pr('a') | Pr('A') => LogicalAction::PostReEdit(
self.post.clone()),
- Pr('v') | Pr('V') => self.cycle_visibility(),
+ Pr('v') | Pr('V') => self.cl_vis.cycle(),
Pr('w') | Pr('W') => self.el_content_warning.start_editing(),
Pr('l') | Pr('L') => self.el_language.start_editing(),
_ => LogicalAction::Nothing,
use super::html;
use super::client::{Client, ClientError};
use super::types::*;
-use super::tui::OurKey;
+use super::tui::{OurKey, LogicalAction};
use super::coloured_string::*;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
}
}
+pub struct CyclingMenuLine<Value: Eq + Copy> {
+ menulines: Vec<(Value, MenuKeypressLine)>,
+ index: usize,
+}
+
+impl<Value: Eq + Copy> CyclingMenuLine<Value> {
+ pub fn new(key: OurKey, description: ColouredString,
+ values: &[(Value, ColouredString)], value: Value) -> Self {
+ let menulines = values.iter().map( |(val, desc)| {
+ (*val, MenuKeypressLine::new(key, &description + desc))
+ }).collect();
+
+ let index = values.iter().position(|(val, _desc)| *val == value)
+ .expect("Input value must match one of the provided options");
+
+ CyclingMenuLine {
+ menulines,
+ index,
+ }
+ }
+
+ // Returns a LogicalAction just to make it more convenient to put
+ // in matches on keypresses
+ pub fn cycle(&mut self) -> LogicalAction {
+ self.index += 1;
+ if self.index >= self.menulines.len() {
+ self.index = 0;
+ }
+ LogicalAction::Nothing
+ }
+
+ pub fn get_value(&self) -> Value { self.menulines[self.index].0 }
+}
+
+impl<Value: Eq + Copy> MenuKeypressLineGeneral for CyclingMenuLine<Value> {
+ fn check_widths(&self, lmaxwid: &mut usize, rmaxwid: &mut usize) {
+ for (_value, ml) in self.menulines.iter() {
+ ml.check_widths(lmaxwid, rmaxwid);
+ }
+ }
+ fn reset_widths(&mut self) {
+ for (_value, ml) in self.menulines.iter_mut() {
+ ml.reset_widths();
+ }
+ }
+ fn ensure_widths(&mut self, lmaxwid: usize, rmaxwid: usize) {
+ for (_value, ml) in self.menulines.iter_mut() {
+ ml.ensure_widths(lmaxwid, rmaxwid);
+ }
+ }
+}
+
+impl<Value: Eq + Copy> TextFragmentOneLine for CyclingMenuLine<Value> {
+ fn render_oneline(&self, width: usize, highlight: Option<Highlight>,
+ style: &dyn DisplayStyleGetter) -> ColouredString
+ {
+ self.menulines[self.index].1.render_oneline(width, highlight, style)
+ }
+}
+
+impl<Value: Eq + Copy> TextFragment for CyclingMenuLine<Value> {
+ fn render_highlighted(&self, width: usize, highlight: Option<Highlight>,
+ style: &dyn DisplayStyleGetter)
+ -> Vec<ColouredString>
+ {
+ vec! {
+ self.render_oneline(width, highlight, style)
+ }
+ }
+}
+
#[test]
fn test_menu_keypress() {
let mut mk = MenuKeypressLine::new(OurKey::Pr('S'), ColouredString::general(