abstreet/game/src/managed.rs

161 lines
4.2 KiB
Rust
Raw Normal View History

2020-02-03 22:14:17 +03:00
use crate::colors;
use crate::game::{DrawBaselayer, State, Transition};
use crate::ui::UI;
use ezgui::{
Button, Color, Composite, EventCtx, GfxCtx, Line, ManagedWidget, MultiKey, Outcome,
RewriteColor, Text,
};
use std::collections::HashMap;
pub type Callback = Box<dyn Fn(&mut EventCtx, &mut UI) -> Option<Transition>>;
pub enum WrappedOutcome {
Transition(Transition),
Clicked(String),
2019-11-30 21:09:31 +03:00
}
pub struct WrappedComposite {
pub inner: Composite,
callbacks: HashMap<String, Callback>,
2019-11-30 21:09:31 +03:00
}
impl WrappedComposite {
pub fn new(inner: Composite) -> WrappedComposite {
WrappedComposite {
inner,
callbacks: HashMap::new(),
}
2019-11-30 21:09:31 +03:00
}
2020-02-01 22:39:48 +03:00
pub fn cb(self, action: &str, cb: Callback) -> WrappedComposite {
if !self.inner.get_all_click_actions().contains(action) {
panic!("No button produces action {}", action);
}
2020-02-01 22:39:48 +03:00
self.maybe_cb(action, cb)
}
2020-02-01 22:39:48 +03:00
pub fn maybe_cb(mut self, action: &str, cb: Callback) -> WrappedComposite {
self.callbacks.insert(action.to_string(), cb);
self
}
pub fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<WrappedOutcome> {
match self.inner.event(ctx)? {
Outcome::Clicked(x) => {
if let Some(ref cb) = self.callbacks.get(&x) {
let t = (cb)(ctx, ui)?;
Some(WrappedOutcome::Transition(t))
} else {
Some(WrappedOutcome::Clicked(x))
}
}
2019-12-19 02:27:52 +03:00
}
}
pub fn draw(&self, g: &mut GfxCtx) {
self.inner.draw(g);
}
}
impl WrappedComposite {
pub fn svg_button(
ctx: &EventCtx,
filename: &str,
tooltip: &str,
hotkey: Option<MultiKey>,
) -> ManagedWidget {
ManagedWidget::btn(Button::rectangle_svg(
filename,
tooltip,
hotkey,
2020-02-03 22:14:17 +03:00
RewriteColor::Change(Color::WHITE, colors::HOVERING),
ctx,
))
}
pub fn nice_text_button(
ctx: &EventCtx,
txt: Text,
hotkey: Option<MultiKey>,
label: &str,
) -> ManagedWidget {
ManagedWidget::btn(Button::text_no_bg(
txt.clone(),
2020-02-03 22:14:17 +03:00
txt.change_fg(colors::HOVERING),
hotkey,
label,
true,
ctx,
))
.outline(2.0, Color::WHITE)
}
pub fn text_button(ctx: &EventCtx, label: &str, hotkey: Option<MultiKey>) -> ManagedWidget {
WrappedComposite::nice_text_button(ctx, Text::from(Line(label)), hotkey, label)
2019-11-24 18:21:30 +03:00
}
pub fn text_bg_button(ctx: &EventCtx, label: &str, hotkey: Option<MultiKey>) -> ManagedWidget {
ManagedWidget::btn(Button::text_bg(
Text::from(Line(label).fg(Color::BLACK)),
Color::WHITE,
2020-02-03 22:14:17 +03:00
colors::HOVERING,
hotkey,
label,
ctx,
))
}
}
pub struct ManagedGUIState {
composite: WrappedComposite,
fullscreen: bool,
}
impl ManagedGUIState {
pub fn fullscreen(composite: WrappedComposite) -> Box<dyn State> {
Box::new(ManagedGUIState {
composite,
fullscreen: true,
})
}
pub fn over_map(composite: WrappedComposite) -> Box<dyn State> {
Box::new(ManagedGUIState {
composite,
fullscreen: false,
})
}
}
impl State for ManagedGUIState {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
match self.composite.event(ctx, ui) {
Some(WrappedOutcome::Transition(t)) => t,
Some(WrappedOutcome::Clicked(x)) => panic!(
"Can't have a button {} without a callback in ManagedGUIState",
x
),
None => Transition::Keep,
}
}
fn draw_baselayer(&self) -> DrawBaselayer {
if self.fullscreen {
DrawBaselayer::Custom
} else {
DrawBaselayer::PreviousState
}
}
fn draw(&self, g: &mut GfxCtx, ui: &UI) {
if self.fullscreen {
// Happens to be a nice background color too ;)
g.clear(ui.cs.get("grass"));
} else {
2020-02-14 00:57:48 +03:00
State::grey_out_map(g);
}
self.composite.draw(g);
}
}