mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-25 11:44:25 +03:00
grey out irrelevant top menu items
This commit is contained in:
parent
875edddc7a
commit
2194ea38a5
@ -41,7 +41,7 @@ impl ContextMenu {
|
||||
None,
|
||||
actions
|
||||
.into_iter()
|
||||
.map(|(hotkey, action)| (Some(hotkey), action, hotkey))
|
||||
.map(|(hotkey, action)| (Some(hotkey), action, true, hotkey))
|
||||
.collect(),
|
||||
false,
|
||||
Position::TopLeft(origin),
|
||||
@ -114,6 +114,7 @@ impl UserInput {
|
||||
input.chosen_action = Some(action);
|
||||
}
|
||||
}
|
||||
menu.valid_actions.clear();
|
||||
}
|
||||
input.top_menu = top_menu;
|
||||
|
||||
@ -250,9 +251,10 @@ impl UserInput {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(ref menu) = self.top_menu {
|
||||
if let Some(key) = menu.actions.get(action) {
|
||||
self.unimportant_key_pressed(*key, action)
|
||||
if let Some(ref mut menu) = self.top_menu {
|
||||
if let Some(key) = menu.actions.get(action).cloned() {
|
||||
menu.valid_actions.insert(action.to_string());
|
||||
self.unimportant_key_pressed(key, action)
|
||||
} else {
|
||||
panic!(
|
||||
"action_chosen(\"{}\") doesn't match actions in the TopMenu!",
|
||||
|
@ -4,7 +4,8 @@ use geom::{Polygon, Pt2D};
|
||||
// Stores some associated data with each choice
|
||||
pub struct Menu<T: Clone> {
|
||||
prompt: Option<String>,
|
||||
choices: Vec<(Option<Key>, String, T)>,
|
||||
// The bool is whether this choice is active or not
|
||||
choices: Vec<(Option<Key>, String, bool, T)>,
|
||||
current_idx: Option<usize>,
|
||||
|
||||
top_left: Pt2D,
|
||||
@ -20,7 +21,7 @@ pub enum Position {
|
||||
impl<T: Clone> Menu<T> {
|
||||
pub fn new(
|
||||
prompt: Option<String>,
|
||||
choices: Vec<(Option<Key>, String, T)>,
|
||||
choices: Vec<(Option<Key>, String, bool, T)>,
|
||||
select_first: bool,
|
||||
pos: Position,
|
||||
canvas: &Canvas,
|
||||
@ -34,7 +35,7 @@ impl<T: Clone> Menu<T> {
|
||||
if let Some(ref line) = prompt {
|
||||
txt.add_line(line.to_string());
|
||||
}
|
||||
for (hotkey, choice, _) in &choices {
|
||||
for (hotkey, choice, _, _) in &choices {
|
||||
if let Some(key) = hotkey {
|
||||
txt.add_line(format!("{} - {}", key.describe(), choice));
|
||||
} else {
|
||||
@ -73,8 +74,12 @@ impl<T: Clone> Menu<T> {
|
||||
// Handle the mouse
|
||||
if ev == Event::LeftMouseButtonDown {
|
||||
if let Some(i) = self.current_idx {
|
||||
let (_, choice, data) = self.choices[i].clone();
|
||||
return InputResult::Done(choice, data);
|
||||
let (_, choice, active, data) = self.choices[i].clone();
|
||||
if active {
|
||||
return InputResult::Done(choice, data);
|
||||
} else {
|
||||
return InputResult::StillActive;
|
||||
}
|
||||
} else {
|
||||
return InputResult::Canceled;
|
||||
}
|
||||
@ -84,10 +89,11 @@ impl<T: Clone> Menu<T> {
|
||||
let cursor_pt = canvas.screen_to_map((x, y));
|
||||
let mut matched = false;
|
||||
for i in 0..self.choices.len() {
|
||||
if self
|
||||
.first_choice_row
|
||||
.translate(0.0, (i as f64) * self.row_height)
|
||||
.contains_pt(cursor_pt)
|
||||
if self.choices[i].2
|
||||
&& self
|
||||
.first_choice_row
|
||||
.translate(0.0, (i as f64) * self.row_height)
|
||||
.contains_pt(cursor_pt)
|
||||
{
|
||||
self.current_idx = Some(i);
|
||||
matched = true;
|
||||
@ -108,8 +114,12 @@ impl<T: Clone> Menu<T> {
|
||||
// TODO Disable arrow keys in context menus and the top menu?
|
||||
if let Some(idx) = self.current_idx {
|
||||
if ev == Event::KeyPress(Key::Enter) {
|
||||
let (_, name, data) = self.choices[idx].clone();
|
||||
return InputResult::Done(name, data);
|
||||
let (_, name, active, data) = self.choices[idx].clone();
|
||||
if active {
|
||||
return InputResult::Done(name, data);
|
||||
} else {
|
||||
return InputResult::StillActive;
|
||||
}
|
||||
} else if ev == Event::KeyPress(Key::UpArrow) {
|
||||
if idx > 0 {
|
||||
self.current_idx = Some(idx - 1);
|
||||
@ -133,17 +143,29 @@ impl<T: Clone> Menu<T> {
|
||||
Some(text::TEXT_QUERY_COLOR),
|
||||
);
|
||||
}
|
||||
for (idx, (hotkey, choice, _)) in self.choices.iter().enumerate() {
|
||||
for (idx, (hotkey, choice, active, _)) in self.choices.iter().enumerate() {
|
||||
let bg = if Some(idx) == self.current_idx {
|
||||
Some(Color::WHITE)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(key) = hotkey {
|
||||
txt.add_styled_line(key.describe(), Color::BLUE, bg);
|
||||
txt.append(format!(" - {}", choice), text::TEXT_FG_COLOR, bg);
|
||||
if *active {
|
||||
if let Some(key) = hotkey {
|
||||
txt.add_styled_line(key.describe(), Color::BLUE, bg);
|
||||
txt.append(format!(" - {}", choice), text::TEXT_FG_COLOR, bg);
|
||||
} else {
|
||||
txt.add_styled_line(choice.to_string(), text::TEXT_FG_COLOR, bg);
|
||||
}
|
||||
} else {
|
||||
txt.add_styled_line(choice.to_string(), text::TEXT_FG_COLOR, bg);
|
||||
if let Some(key) = hotkey {
|
||||
txt.add_styled_line(
|
||||
format!("{} - {}", key.describe(), choice),
|
||||
Color::grey(0.8),
|
||||
bg,
|
||||
);
|
||||
} else {
|
||||
txt.add_styled_line(format!("{}", choice), Color::grey(0.8), bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
canvas.draw_text_at_topleft(g, txt, self.top_left);
|
||||
@ -151,6 +173,6 @@ impl<T: Clone> Menu<T> {
|
||||
|
||||
pub fn current_choice(&self) -> Option<&T> {
|
||||
let idx = self.current_idx?;
|
||||
Some(&self.choices[idx].2)
|
||||
Some(&self.choices[idx].3)
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ pub struct TopMenu {
|
||||
|
||||
highlighted: Option<usize>,
|
||||
submenu: Option<(usize, Menu<Key>)>,
|
||||
// Reset every round
|
||||
pub(crate) valid_actions: HashSet<String>,
|
||||
}
|
||||
|
||||
impl TopMenu {
|
||||
@ -57,6 +59,7 @@ impl TopMenu {
|
||||
txt,
|
||||
highlighted: None,
|
||||
submenu: None,
|
||||
valid_actions: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,13 +83,22 @@ impl TopMenu {
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let f = &self.folders[idx];
|
||||
// valid_actions can't change once this submenu is created, so determine what
|
||||
// actions are valid right now.
|
||||
self.submenu = Some((
|
||||
idx,
|
||||
Menu::new(
|
||||
None,
|
||||
f.actions
|
||||
.iter()
|
||||
.map(|(key, action)| (Some(*key), action.to_string(), *key))
|
||||
.map(|(key, action)| {
|
||||
(
|
||||
Some(*key),
|
||||
action.to_string(),
|
||||
self.valid_actions.contains(action),
|
||||
*key,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
false,
|
||||
Position::TopLeft(canvas.screen_to_map((f.rectangle.x1, f.rectangle.y2))),
|
||||
|
@ -208,9 +208,9 @@ impl<'a> WrappedWizard<'a> {
|
||||
)]));
|
||||
return None;
|
||||
}
|
||||
let boxed_choices: Vec<(Option<Key>, String, Box<Cloneable>)> = choices
|
||||
let boxed_choices: Vec<(Option<Key>, String, bool, Box<Cloneable>)> = choices
|
||||
.iter()
|
||||
.map(|(s, item)| (None, s.to_string(), item.clone_box()))
|
||||
.map(|(s, item)| (None, s.to_string(), true, item.clone_box()))
|
||||
.collect();
|
||||
self.wizard.menu = Some(Menu::new(
|
||||
Some(query.to_string()),
|
||||
|
Loading…
Reference in New Issue
Block a user