prompts on top of menus, too

This commit is contained in:
Dustin Carlino 2018-09-20 19:49:31 -07:00
parent b66e6891f6
commit f1f0683026
6 changed files with 18 additions and 28 deletions

View File

@ -196,3 +196,5 @@ previous answers. The caller could even build a branching workflow -- as long
as the calls to the wizard are deterministic. as the calls to the wizard are deterministic.
Menus are super awkward -- drawing extra effects, mainly. Menus are super awkward -- drawing extra effects, mainly.
cursive crate is good inspiration for the API

View File

@ -33,6 +33,7 @@ impl ColorPicker {
ColorPicker::Inactive => { ColorPicker::Inactive => {
if input.unimportant_key_pressed(Key::D8, "configure colors") { if input.unimportant_key_pressed(Key::D8, "configure colors") {
new_state = Some(ColorPicker::Choosing(Menu::new( new_state = Some(ColorPicker::Choosing(Menu::new(
"Pick a color to change",
Colors::iter().map(|c| c.to_string()).collect(), Colors::iter().map(|c| c.to_string()).collect(),
))); )));
} }

View File

@ -53,7 +53,7 @@ impl DrawPolygonState {
println!("Sorry, no existing polygons"); println!("Sorry, no existing polygons");
} else { } else {
new_state = Some(DrawPolygonState::ListingPolygons( new_state = Some(DrawPolygonState::ListingPolygons(
Menu::new(polygons.keys().cloned().collect()), Menu::new("Load which polygon?", polygons.keys().cloned().collect()),
polygons, polygons,
)); ));
} }

View File

@ -1,4 +1,4 @@
use ezgui::{Canvas, GfxCtx, InputResult, Menu, TextBox, TextOSD, UserInput}; use ezgui::{Canvas, GfxCtx, InputResult, Menu, TextBox, UserInput};
use geom::Polygon; use geom::Polygon;
use map_model::Map; use map_model::Map;
use piston::input::Key; use piston::input::Key;
@ -32,7 +32,7 @@ impl WizardSample {
WizardSample::Inactive WizardSample::Inactive
} }
pub fn event(&mut self, input: &mut UserInput, map: &Map, osd: &mut TextOSD) -> bool { pub fn event(&mut self, input: &mut UserInput, map: &Map) -> bool {
let mut new_state: Option<WizardSample> = None; let mut new_state: Option<WizardSample> = None;
match self { match self {
WizardSample::Inactive => { WizardSample::Inactive => {
@ -41,7 +41,7 @@ impl WizardSample {
} }
} }
WizardSample::Active(ref mut wizard) => { WizardSample::Active(ref mut wizard) => {
if let Some(spec) = workflow(wizard.wrap(input, map, osd)) { if let Some(spec) = workflow(wizard.wrap(input, map)) {
println!("Got answer: {:?}", spec); println!("Got answer: {:?}", spec);
new_state = Some(WizardSample::Inactive); new_state = Some(WizardSample::Inactive);
} else if wizard.aborted() { } else if wizard.aborted() {
@ -120,12 +120,7 @@ impl Wizard {
} }
} }
fn wrap<'a>( fn wrap<'a>(&'a mut self, input: &'a mut UserInput, map: &'a Map) -> WrappedWizard<'a> {
&'a mut self,
input: &'a mut UserInput,
map: &'a Map,
osd: &'a mut TextOSD,
) -> WrappedWizard<'a> {
assert!(self.alive); assert!(self.alive);
let ready_usize = VecDeque::from(self.state_usize.clone()); let ready_usize = VecDeque::from(self.state_usize.clone());
@ -136,7 +131,6 @@ impl Wizard {
wizard: self, wizard: self,
input, input,
map, map,
osd,
ready_usize, ready_usize,
ready_tick, ready_tick,
ready_percent, ready_percent,
@ -153,7 +147,6 @@ impl Wizard {
query: &str, query: &str,
choices: Vec<String>, choices: Vec<String>,
input: &mut UserInput, input: &mut UserInput,
osd: &mut TextOSD,
) -> Option<String> { ) -> Option<String> {
assert!(self.alive); assert!(self.alive);
@ -163,7 +156,7 @@ impl Wizard {
} }
if self.menu.is_none() { if self.menu.is_none() {
self.menu = Some(Menu::new(choices)); self.menu = Some(Menu::new(query, choices));
} }
match self.menu.as_mut().unwrap().event(input) { match self.menu.as_mut().unwrap().event(input) {
@ -172,13 +165,7 @@ impl Wizard {
self.alive = false; self.alive = false;
None None
} }
InputResult::StillActive => { InputResult::StillActive => None,
// TODO We want to draw this at the top of the menu with choices. Menu should
// probably itself have an optional header line?
osd.pad_if_nonempty();
osd.add_line(query.to_string());
None
}
InputResult::Done(choice) => { InputResult::Done(choice) => {
self.menu = None; self.menu = None;
Some(choice) Some(choice)
@ -228,7 +215,6 @@ struct WrappedWizard<'a> {
wizard: &'a mut Wizard, wizard: &'a mut Wizard,
input: &'a mut UserInput, input: &'a mut UserInput,
map: &'a Map, map: &'a Map,
osd: &'a mut TextOSD,
ready_usize: VecDeque<usize>, ready_usize: VecDeque<usize>,
ready_tick: VecDeque<Tick>, ready_tick: VecDeque<Tick>,
@ -292,6 +278,7 @@ impl<'a> WrappedWizard<'a> {
} }
} }
#[allow(dead_code)]
fn choose(&mut self, query: &str, choices: Vec<&str>) -> Option<String> { fn choose(&mut self, query: &str, choices: Vec<&str>) -> Option<String> {
if !self.ready_choices.is_empty() { if !self.ready_choices.is_empty() {
return self.ready_choices.pop_front(); return self.ready_choices.pop_front();
@ -300,7 +287,6 @@ impl<'a> WrappedWizard<'a> {
query, query,
choices.iter().map(|s| s.to_string()).collect(), choices.iter().map(|s| s.to_string()).collect(),
self.input, self.input,
self.osd,
) { ) {
self.wizard.state_choices.push(choice.clone()); self.wizard.state_choices.push(choice.clone());
Some(choice) Some(choice)
@ -324,10 +310,7 @@ impl<'a> WrappedWizard<'a> {
.keys() .keys()
.cloned() .cloned()
.collect(); .collect();
let result = if let Some(choice) = self let result = if let Some(choice) = self.wizard.input_with_menu(query, names, self.input) {
.wizard
.input_with_menu(query, names, self.input, self.osd)
{
self.wizard.state_choices.push(choice.clone()); self.wizard.state_choices.push(choice.clone());
Some(choice) Some(choice)
} else { } else {

View File

@ -245,7 +245,7 @@ impl UIWrapper {
}), }),
Box::new(|ui, input, _osd| ui.turn_cycler.event(input, ui.current_selection)), Box::new(|ui, input, _osd| ui.turn_cycler.event(input, ui.current_selection)),
Box::new(|ui, input, osd| ui.draw_polygon.event(input, &ui.canvas, &ui.map, osd)), Box::new(|ui, input, osd| ui.draw_polygon.event(input, &ui.canvas, &ui.map, osd)),
Box::new(|ui, input, osd| ui.wizard_sample.event(input, &ui.map, osd)), Box::new(|ui, input, _osd| ui.wizard_sample.event(input, &ui.map)),
], ],
} }
} }

View File

@ -2,13 +2,15 @@ use piston::input::{Button, Key, PressEvent};
use {InputResult, TextOSD, UserInput}; use {InputResult, TextOSD, UserInput};
pub struct Menu { pub struct Menu {
prompt: String,
choices: Vec<String>, choices: Vec<String>,
current_idx: usize, current_idx: usize,
} }
impl Menu { impl Menu {
pub fn new(choices: Vec<String>) -> Menu { pub fn new(prompt: &str, choices: Vec<String>) -> Menu {
Menu { Menu {
prompt: prompt.to_string(),
choices, choices,
current_idx: 0, current_idx: 0,
} }
@ -44,6 +46,8 @@ impl Menu {
// display one size for the menu, just dont fill everything out // display one size for the menu, just dont fill everything out
pub fn get_osd(&self) -> TextOSD { pub fn get_osd(&self) -> TextOSD {
let mut osd = TextOSD::new(); let mut osd = TextOSD::new();
// TODO different color
osd.add_line(self.prompt.clone());
for (idx, line) in self.choices.iter().enumerate() { for (idx, line) in self.choices.iter().enumerate() {
if self.current_idx == idx { if self.current_idx == idx {
osd.add_highlighted_line(line.clone()); osd.add_highlighted_line(line.clone());