diff --git a/ezgui/src/managed.rs b/ezgui/src/managed.rs index f42767bb60..a4a6a71568 100644 --- a/ezgui/src/managed.rs +++ b/ezgui/src/managed.rs @@ -473,7 +473,7 @@ impl ManagedWidget { pub struct CompositeBuilder { top_level: ManagedWidget, - pos: CompositePosition, + layout: Layout, sliders: HashMap, menus: HashMap, fillers: HashMap, @@ -481,7 +481,7 @@ pub struct CompositeBuilder { pub struct Composite { top_level: ManagedWidget, - pos: CompositePosition, + layout: Layout, sliders: HashMap, menus: HashMap, @@ -497,10 +497,12 @@ pub enum Outcome { Clicked(String), } -enum CompositePosition { - FillScreen, - Aligned(HorizontalAlignment, VerticalAlignment), - AlignedSizePercent(HorizontalAlignment, VerticalAlignment, f64, f64), +struct Layout { + horiz: HorizontalAlignment, + vert: VerticalAlignment, + // If None, then be just as large as needed. But still don't exceed screen. + percent_width: Option, + percent_height: Option, } const SCROLL_SPEED: f64 = 5.0; @@ -511,7 +513,12 @@ impl Composite { pub fn new(top_level: ManagedWidget) -> CompositeBuilder { CompositeBuilder { top_level, - pos: CompositePosition::FillScreen, + layout: Layout { + horiz: HorizontalAlignment::Center, + vert: VerticalAlignment::Center, + percent_width: None, + percent_height: None, + }, sliders: HashMap::new(), menus: HashMap::new(), fillers: HashMap::new(), @@ -522,29 +529,20 @@ impl Composite { let mut stretch = Stretch::new(); let root = stretch .new_node( - match self.pos { - CompositePosition::FillScreen => Style { - size: Size { - width: Dimension::Points(ctx.canvas.window_width as f32), - height: Dimension::Points(ctx.canvas.window_height as f32), + Style { + size: Size { + width: if let Some(pct) = self.layout.percent_width { + Dimension::Points((ctx.canvas.window_width * pct) as f32) + } else { + Dimension::Undefined }, - ..Default::default() - }, - CompositePosition::Aligned(_, _) => Style { - // TODO There a way to encode the offset in stretch? - ..Default::default() - }, - CompositePosition::AlignedSizePercent(_, _, pct_width, pct_height) => Style { - size: Size { - width: Dimension::Points( - (ctx.canvas.window_width * (pct_width / 100.0)) as f32, - ), - height: Dimension::Points( - (ctx.canvas.window_height * pct_height / 100.0) as f32, - ), + height: if let Some(pct) = self.layout.percent_height { + Dimension::Points((ctx.canvas.window_height * pct) as f32) + } else { + Dimension::Undefined }, - ..Default::default() }, + ..Default::default() }, Vec::new(), ) @@ -562,18 +560,12 @@ impl Composite { nodes.reverse(); stretch.compute_layout(root, Size::undefined()).unwrap(); - let top_left = match self.pos { - CompositePosition::FillScreen => ScreenPt::new(0.0, 0.0), - CompositePosition::Aligned(horiz, vert) - | CompositePosition::AlignedSizePercent(horiz, vert, _, _) => { - let result = stretch.layout(root).unwrap(); - ctx.canvas.align_window( - ScreenDims::new(result.size.width.into(), result.size.height.into()), - horiz, - vert, - ) - } - }; + let result = stretch.layout(root).unwrap(); + let top_left = ctx.canvas.align_window( + ScreenDims::new(result.size.width.into(), result.size.height.into()), + self.layout.horiz, + self.layout.vert, + ); let offset = self.scroll_y_offset(ctx); self.top_level.apply_flexbox( &mut self.sliders, @@ -685,7 +677,7 @@ impl CompositeBuilder { pub fn build(self, ctx: &mut EventCtx) -> Composite { let mut c = Composite { top_level: self.top_level, - pos: self.pos, + layout: self.layout, sliders: self.sliders, menus: self.menus, fillers: self.fillers, @@ -698,7 +690,7 @@ impl CompositeBuilder { pub fn build_scrollable(self, ctx: &mut EventCtx) -> Composite { let mut c = Composite { top_level: self.top_level, - pos: self.pos, + layout: self.layout, sliders: self.sliders, menus: self.menus, fillers: self.fillers, @@ -706,6 +698,7 @@ impl CompositeBuilder { }; // If the panel fits without a scrollbar, don't add one. c.recompute_layout(ctx); + // TODO Max size is a little different... if c.top_level.rect.height() > ctx.canvas.window_height { c.scrollable = true; c.sliders.insert( @@ -724,19 +717,19 @@ impl CompositeBuilder { horiz: HorizontalAlignment, vert: VerticalAlignment, ) -> CompositeBuilder { - self.pos = CompositePosition::Aligned(horiz, vert); + self.layout.horiz = horiz; + self.layout.vert = vert; self } - pub fn aligned_size_percent( - mut self, - horiz: HorizontalAlignment, - vert: VerticalAlignment, - pct_width: usize, - pct_height: usize, - ) -> CompositeBuilder { - self.pos = - CompositePosition::AlignedSizePercent(horiz, vert, pct_width as f64, pct_height as f64); + pub fn size_percent(mut self, pct_width: usize, pct_height: usize) -> CompositeBuilder { + self.layout.percent_width = Some((pct_width as f64) / 100.0); + self.layout.percent_height = Some((pct_height as f64) / 100.0); + self + } + pub fn fullscreen(mut self) -> CompositeBuilder { + self.layout.percent_width = Some(1.0); + self.layout.percent_height = Some(1.0); self } diff --git a/ezgui/src/widgets/wizard.rs b/ezgui/src/widgets/wizard.rs index e7288ada09..68e09e8387 100644 --- a/ezgui/src/widgets/wizard.rs +++ b/ezgui/src/widgets/wizard.rs @@ -1,8 +1,8 @@ use crate::widgets::text_box::TextBox; use crate::widgets::PopupMenu; use crate::{ - hotkey, layout, Button, Color, Composite, EventCtx, GfxCtx, HorizontalAlignment, InputResult, - Key, Line, ManagedWidget, MultiKey, Outcome, SliderWithTextBox, Text, VerticalAlignment, + hotkey, layout, Button, Color, Composite, EventCtx, GfxCtx, InputResult, Key, Line, + ManagedWidget, MultiKey, Outcome, SliderWithTextBox, Text, }; use abstutil::Cloneable; use geom::Time; @@ -280,7 +280,6 @@ impl<'a, 'b> WrappedWizard<'a, 'b> { ]) .bg(Color::grey(0.4)), ) - .aligned(HorizontalAlignment::Center, VerticalAlignment::Center) .menu( "menu", PopupMenu::new( @@ -398,7 +397,6 @@ impl<'a, 'b> WrappedWizard<'a, 'b> { ]) .bg(Color::grey(0.4)), ) - .aligned(HorizontalAlignment::Center, VerticalAlignment::Center) .build(self.ctx), ); } diff --git a/game/src/pregame.rs b/game/src/pregame.rs index bc258016bc..d87a83b552 100644 --- a/game/src/pregame.rs +++ b/game/src/pregame.rs @@ -26,26 +26,22 @@ impl TitleScreen { pub fn new(ctx: &mut EventCtx, ui: &UI) -> TitleScreen { let mut rng = ui.primary.current_flags.sim_flags.make_rng(); TitleScreen { - // TODO Double column to get the vertical centering. For some reason, the horizontal - // centering isn't working. composite: Composite::new( - ezgui::Composite::new( - ManagedWidget::col(vec![ManagedWidget::col(vec![ - ManagedWidget::just_draw(JustDraw::image("assets/pregame/logo.png", ctx)) - .bg(Color::GREEN.alpha(0.2)), - // TODO that nicer font - // TODO Any key - ManagedWidget::btn(Button::text( - Text::from(Line("PLAY")), - Color::BLUE, - Color::ORANGE, - hotkey(Key::Space), - "start game", - ctx, - )), - ])]) + ezgui::Composite::new(ManagedWidget::col(vec![ + ManagedWidget::just_draw(JustDraw::image("assets/pregame/logo.png", ctx)) + .bg(Color::GREEN.alpha(0.2)), + // TODO that nicer font + // TODO Any key + ManagedWidget::row(vec![ManagedWidget::btn(Button::text( + Text::from(Line("PLAY")), + Color::BLUE, + Color::ORANGE, + hotkey(Key::Space), + "start game", + ctx, + ))]) .centered(), - ) + ])) .build(ctx), ) .cb( @@ -122,42 +118,43 @@ pub fn main_menu(ctx: &mut EventCtx, ui: &UI) -> Box { } col.push(Composite::text_button(ctx, "About A/B Street", None)); - let mut c = - Composite::new(ezgui::Composite::new(ManagedWidget::col(col).centered()).build(ctx)) - .cb( - "quit", - Box::new(|_, _| { - // TODO before_quit? - std::process::exit(0); - }), - ) - .cb( - "Tutorial", - Box::new(|ctx, _| Some(Transition::Push(Box::new(TutorialMode::new(ctx))))), - ) - .cb( - "Sandbox mode", - Box::new(|ctx, ui| { - Some(Transition::PushWithMode( - Box::new(SandboxMode::new( - ctx, - ui, - GameplayMode::PlayScenario( - "random scenario with some agents".to_string(), - ), - )), - EventLoopMode::Animation, - )) - }), - ) - .cb( - "Challenges", - Box::new(|ctx, _| Some(Transition::Push(challenges_picker(ctx)))), - ) - .cb( - "About A/B Street", - Box::new(|ctx, _| Some(Transition::Push(about(ctx)))), - ); + let mut c = Composite::new( + ezgui::Composite::new(ManagedWidget::col(col).centered()) + .fullscreen() + .build(ctx), + ) + .cb( + "quit", + Box::new(|_, _| { + // TODO before_quit? + std::process::exit(0); + }), + ) + .cb( + "Tutorial", + Box::new(|ctx, _| Some(Transition::Push(Box::new(TutorialMode::new(ctx))))), + ) + .cb( + "Sandbox mode", + Box::new(|ctx, ui| { + Some(Transition::PushWithMode( + Box::new(SandboxMode::new( + ctx, + ui, + GameplayMode::PlayScenario("random scenario with some agents".to_string()), + )), + EventLoopMode::Animation, + )) + }), + ) + .cb( + "Challenges", + Box::new(|ctx, _| Some(Transition::Push(challenges_picker(ctx)))), + ) + .cb( + "About A/B Street", + Box::new(|ctx, _| Some(Transition::Push(about(ctx)))), + ); if ui.opts.dev { c = c .cb( diff --git a/game/src/sandbox/dashboards.rs b/game/src/sandbox/dashboards.rs index bebb1f7760..e9d43b4206 100644 --- a/game/src/sandbox/dashboards.rs +++ b/game/src/sandbox/dashboards.rs @@ -7,8 +7,7 @@ use crate::ui::UI; use abstutil::prettyprint_usize; use abstutil::Counter; use ezgui::{ - hotkey, Color, EventCtx, EventLoopMode, Histogram, HorizontalAlignment, Key, Line, - ManagedWidget, Plot, Series, Text, VerticalAlignment, + hotkey, Color, EventCtx, EventLoopMode, Histogram, Key, Line, ManagedWidget, Plot, Series, Text, }; use geom::{Duration, Statistic, Time}; use map_model::BusRouteID; @@ -63,7 +62,7 @@ pub fn make(ctx: &mut EventCtx, ui: &UI, tab: Tab) -> Box { .padding(10), content, ])) - .aligned(HorizontalAlignment::Left, VerticalAlignment::Top) + .fullscreen() .build_scrollable(ctx), ) .cb("BACK", Box::new(|_, _| Some(Transition::Pop))); diff --git a/game/src/sandbox/gameplay/optimize_bus.rs b/game/src/sandbox/gameplay/optimize_bus.rs index 2f6927712b..15436dd14e 100644 --- a/game/src/sandbox/gameplay/optimize_bus.rs +++ b/game/src/sandbox/gameplay/optimize_bus.rs @@ -9,8 +9,7 @@ use crate::sandbox::{bus_explorer, SandboxMode}; use crate::ui::UI; use ezgui::{ hotkey, Button, Choice, Color, Composite, DrawBoth, EventCtx, EventLoopMode, GeomBatch, - HorizontalAlignment, JustDraw, Key, Line, ManagedWidget, ModalMenu, Plot, Series, Text, - VerticalAlignment, + JustDraw, Key, Line, ManagedWidget, ModalMenu, Plot, Series, Text, }; use geom::{Circle, Distance, Polygon, Pt2D, Statistic, Time}; use map_model::BusRouteID; @@ -260,9 +259,7 @@ fn bus_passengers(id: BusRouteID, ui: &UI, ctx: &mut EventCtx) -> crate::managed ])); let mut c = crate::managed::Composite::new( - Composite::new(ManagedWidget::col(master_col).bg(Color::grey(0.4))) - .aligned(HorizontalAlignment::Center, VerticalAlignment::Center) - .build(ctx), + Composite::new(ManagedWidget::col(master_col).bg(Color::grey(0.4))).build(ctx), ); for (idx, stop) in route.stops.iter().enumerate() { let id = ID::BusStop(*stop); @@ -315,6 +312,5 @@ fn bus_delays(id: BusRouteID, ui: &UI, ctx: &mut EventCtx) -> Composite { ]) .bg(Color::grey(0.3)), ) - .aligned(HorizontalAlignment::Center, VerticalAlignment::Center) .build(ctx) } diff --git a/game/src/sandbox/overlays.rs b/game/src/sandbox/overlays.rs index dd782edc64..bea4617b32 100644 --- a/game/src/sandbox/overlays.rs +++ b/game/src/sandbox/overlays.rs @@ -172,12 +172,7 @@ impl Overlays { ]) .bg(Color::hex("#5B5B5B")), ) - .aligned_size_percent( - HorizontalAlignment::Center, - VerticalAlignment::Center, - 30, - 50, - ) + .size_percent(30, 50) .build(ctx), ) .cb("X", Box::new(|_, _| Some(Transition::Pop)))