abstreet/game/src/managed.rs

152 lines
3.9 KiB
Rust
Raw Normal View History

use crate::game::{State, Transition};
use crate::ui::UI;
use ezgui::{
Button, Color, EventCtx, GfxCtx, Line, ManagedWidget, MultiKey, RewriteColor, Slider, Text,
};
use std::collections::HashMap;
type Callback = Box<dyn Fn(&mut EventCtx, &mut UI) -> Option<Transition>>;
pub enum Outcome {
Transition(Transition),
Clicked(String),
2019-11-30 21:09:31 +03:00
}
pub struct Composite {
inner: ezgui::Composite,
callbacks: HashMap<String, Callback>,
2019-11-30 21:09:31 +03:00
}
impl Composite {
pub fn new(inner: ezgui::Composite) -> Composite {
Composite {
inner,
callbacks: HashMap::new(),
}
2019-11-30 21:09:31 +03:00
}
pub fn cb(mut self, action: &str, cb: Callback) -> Composite {
if !self.inner.get_all_click_actions().contains(action) {
panic!("No button produces action {}", action);
}
self.callbacks.insert(action.to_string(), cb);
self
}
pub fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Outcome> {
self.event_with_sliders(ctx, ui, HashMap::new())
}
2019-12-19 02:27:52 +03:00
pub fn event_with_sliders(
&mut self,
ctx: &mut EventCtx,
ui: &mut UI,
sliders: HashMap<String, &mut Slider>,
) -> Option<Outcome> {
match self.inner.event_with_sliders(ctx, sliders)? {
ezgui::Outcome::Clicked(x) => {
if let Some(ref cb) = self.callbacks.get(&x) {
let t = (cb)(ctx, ui)?;
Some(Outcome::Transition(t))
} else {
Some(Outcome::Clicked(x))
}
}
2019-12-19 02:27:52 +03:00
}
}
pub fn draw(&self, g: &mut GfxCtx) {
self.inner.draw(g);
}
pub fn draw_with_sliders(&self, g: &mut GfxCtx, sliders: HashMap<String, &Slider>) {
self.inner.draw_with_sliders(g, sliders);
}
}
impl Composite {
pub fn img_button(
ctx: &EventCtx,
filename: &str,
hotkey: Option<MultiKey>,
label: &str,
) -> ManagedWidget {
ManagedWidget::btn(Button::rectangle_img(filename, hotkey, ctx, label))
}
pub fn svg_button(
ctx: &EventCtx,
filename: &str,
tooltip: &str,
hotkey: Option<MultiKey>,
) -> ManagedWidget {
ManagedWidget::btn(Button::rectangle_svg(
filename,
tooltip,
hotkey,
RewriteColor::Change(Color::WHITE, Color::ORANGE),
ctx,
))
}
pub fn text_button(ctx: &EventCtx, label: &str, hotkey: Option<MultiKey>) -> ManagedWidget {
Composite::detailed_text_button(
ctx,
Text::from(Line(label).fg(Color::BLACK)),
hotkey,
label,
)
2019-11-24 18:21:30 +03:00
}
pub fn detailed_text_button(
ctx: &EventCtx,
txt: Text,
hotkey: Option<MultiKey>,
label: &str,
) -> ManagedWidget {
// TODO Default style. Lots of variations.
ManagedWidget::btn(Button::text(
txt,
Color::WHITE,
Color::ORANGE,
hotkey,
label,
ctx,
))
}
}
pub struct ManagedGUIState {
composite: Composite,
}
impl ManagedGUIState {
pub fn new(composite: Composite) -> Box<dyn State> {
Box::new(ManagedGUIState { composite })
}
}
impl State for ManagedGUIState {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
match self.composite.event(ctx, ui) {
Some(Outcome::Transition(t)) => t,
Some(Outcome::Clicked(x)) => panic!(
"Can't have a button {} without a callback in ManagedGUIState",
x
),
None => Transition::Keep,
}
}
fn draw_default_ui(&self) -> bool {
false
}
fn draw(&self, g: &mut GfxCtx, ui: &UI) {
// Happens to be a nice background color too ;)
g.clear(ui.cs.get("grass"));
self.composite.draw(g);
}
}