diff --git a/apps/game/src/sandbox/speed.rs b/apps/game/src/sandbox/speed.rs index 7d1478deb1..d046de622d 100644 --- a/apps/game/src/sandbox/speed.rs +++ b/apps/game/src/sandbox/speed.rs @@ -5,8 +5,8 @@ use sim::AlertLocation; use widgetry::tools::PopupMsg; use widgetry::{ Choice, Color, ControlState, DrawWithTooltips, EdgeInsets, EventCtx, GeomBatch, GfxCtx, - HorizontalAlignment, Key, Line, Outcome, Panel, PersistentSplit, ScreenDims, Text, TextExt, - VerticalAlignment, Widget, + HorizontalAlignment, Key, Line, Outcome, Panel, PanelDims, PersistentSplit, ScreenDims, Text, + TextExt, VerticalAlignment, Widget, }; use crate::app::{App, Transition}; @@ -155,7 +155,7 @@ impl TimePanel { ])) .aligned(HorizontalAlignment::Left, VerticalAlignment::Top); if let Some(h) = self.override_height { - panel = panel.exact_height_pixels(h); + panel = panel.dims_height(PanelDims::ExactPixels(h)); } self.panel = panel.build(ctx); } diff --git a/apps/game/src/sandbox/time_warp.rs b/apps/game/src/sandbox/time_warp.rs index 828efaa4c8..7035298844 100644 --- a/apps/game/src/sandbox/time_warp.rs +++ b/apps/game/src/sandbox/time_warp.rs @@ -7,7 +7,7 @@ use map_gui::tools::grey_out_map; use map_gui::ID; use widgetry::tools::PopupMsg; use widgetry::{ - Choice, DrawBaselayer, EventCtx, GeomBatch, GfxCtx, Key, Line, Outcome, Panel, ScreenDims, + Choice, DrawBaselayer, EventCtx, GeomBatch, GfxCtx, Key, Line, Outcome, Panel, PanelDims, Slider, State, TabController, Text, Toggle, UpdateType, Widget, }; @@ -103,7 +103,8 @@ impl JumpToTime { ctx.style().btn_close_widget(ctx), tabs.build_widget(ctx), ])) - .exact_size(ScreenDims::new(640.0, 360.0)) + .dims_width(PanelDims::ExactPixels(640.0)) + .dims_height(PanelDims::ExactPixels(360.0)) .build(ctx), tabs, }) diff --git a/apps/game/src/ungap/mod.rs b/apps/game/src/ungap/mod.rs index 8213a231d9..17d27021d5 100644 --- a/apps/game/src/ungap/mod.rs +++ b/apps/game/src/ungap/mod.rs @@ -9,7 +9,7 @@ mod trip; use geom::CornerRadii; use map_gui::tools::CityPicker; use widgetry::{ - EventCtx, HorizontalAlignment, Key, Line, Panel, ScreenDims, State, VerticalAlignment, Widget, + EventCtx, HorizontalAlignment, Key, Line, Panel, PanelDims, State, VerticalAlignment, Widget, DEFAULT_CORNER_RADIUS, }; @@ -119,10 +119,8 @@ impl Tab { let mut panel = Panel::new_builder(Widget::col(vec![header, tabs])) // The different tabs have different widths. To avoid the UI bouncing around as the user // navigates, this is hardcoded to be a bit wider than the widest tab. - .exact_size(ScreenDims { - width: 620.0, - height: ctx.canvas.window_height, - }) + .dims_width(PanelDims::ExactPixels(620.0)) + .dims_height(PanelDims::ExactPercent(1.0)) .aligned(HorizontalAlignment::Left, VerticalAlignment::Top); if self == Tab::Trip { // Hovering on a card diff --git a/apps/ltn/src/common/mod.rs b/apps/ltn/src/common/mod.rs index a26832ca58..9a22e7ab9e 100644 --- a/apps/ltn/src/common/mod.rs +++ b/apps/ltn/src/common/mod.rs @@ -1,5 +1,5 @@ use widgetry::{ - lctrl, EventCtx, HorizontalAlignment, Key, Line, Outcome, Panel, PanelBuilder, + lctrl, EventCtx, HorizontalAlignment, Key, Line, Outcome, Panel, PanelBuilder, PanelDims, VerticalAlignment, Widget, }; @@ -21,7 +21,7 @@ pub fn app_top_panel(ctx: &mut EventCtx, app: &App) -> Panel { .align_right(), ])) .aligned(HorizontalAlignment::Left, VerticalAlignment::Top) - .exact_width_percent(1.0) + .dims_width(PanelDims::ExactPercent(1.0)) .build(ctx) } @@ -58,5 +58,5 @@ pub fn left_panel_builder(contents: Widget) -> PanelBuilder { HorizontalAlignment::Percent(0.0), VerticalAlignment::Percent(0.1), ) - .exact_height_percent(0.9) + .dims_height(PanelDims::ExactPercent(0.9)) } diff --git a/map_gui/src/tools/city_picker.rs b/map_gui/src/tools/city_picker.rs index 2744418e5b..3503086666 100644 --- a/map_gui/src/tools/city_picker.rs +++ b/map_gui/src/tools/city_picker.rs @@ -6,8 +6,8 @@ use map_model::City; use widgetry::tools::FileLoader; use widgetry::{ lctrl, Autocomplete, ClickOutcome, ControlState, DrawBaselayer, DrawWithTooltips, EventCtx, - GeomBatch, GfxCtx, Image, Key, Line, Outcome, Panel, RewriteColor, State, Text, TextExt, - Transition, Widget, + GeomBatch, GfxCtx, Image, Key, Line, Outcome, Panel, PanelDims, RewriteColor, State, Text, + TextExt, Transition, Widget, }; use crate::load::MapLoader; @@ -278,7 +278,8 @@ impl AllCityPicker { .padding(8), Widget::custom_row(buttons).flex_wrap(ctx, Percent::int(70)), ])) - .exact_size_percent(80, 80) + .dims_width(PanelDims::ExactPercent(0.8)) + .dims_height(PanelDims::ExactPercent(0.8)) .build(ctx), }) } @@ -404,7 +405,8 @@ impl CitiesInCountryPicker { Box::new(CitiesInCountryPicker { on_load: Some(on_load), panel: Panel::new_builder(Widget::col(col)) - .exact_size_percent(80, 80) + .dims_width(PanelDims::ExactPercent(0.8)) + .dims_height(PanelDims::ExactPercent(0.8)) .build(ctx), }) } diff --git a/widgetry/src/event_ctx.rs b/widgetry/src/event_ctx.rs index 5625ab5e20..035f25b341 100644 --- a/widgetry/src/event_ctx.rs +++ b/widgetry/src/event_ctx.rs @@ -7,7 +7,8 @@ use geom::{Percent, Polygon}; use crate::{ svg, Canvas, CanvasSettings, Color, Drawable, Event, GeomBatch, GfxCtx, HorizontalAlignment, - Key, Line, Panel, Prerender, ScreenDims, Style, Text, UserInput, VerticalAlignment, Widget, + Key, Line, Panel, PanelDims, Prerender, ScreenDims, Style, Text, UserInput, VerticalAlignment, + Widget, }; #[derive(Clone, PartialEq, Debug)] @@ -203,7 +204,8 @@ impl<'a> EventCtx<'a> { .padding(16) .bg(Color::grey(0.3)), ])) - .exact_size_percent(80, 80) + .dims_width(PanelDims::ExactPercent(0.8)) + .dims_height(PanelDims::ExactPercent(0.8)) .aligned(HorizontalAlignment::Center, VerticalAlignment::Center) .build_custom(self) } diff --git a/widgetry/src/lib.rs b/widgetry/src/lib.rs index 3ace03b7c4..368b636f7f 100644 --- a/widgetry/src/lib.rs +++ b/widgetry/src/lib.rs @@ -75,8 +75,8 @@ pub use crate::widgets::text_box::TextBox; pub use crate::widgets::toggle::Toggle; pub use crate::widgets::DEFAULT_CORNER_RADIUS; pub use crate::widgets::{ - ClickOutcome, CornerRounding, EdgeInsets, Outcome, Panel, PanelBuilder, Widget, WidgetImpl, - WidgetOutput, + ClickOutcome, CornerRounding, EdgeInsets, Outcome, Panel, PanelBuilder, PanelDims, Widget, + WidgetImpl, WidgetOutput, }; mod app_state; diff --git a/widgetry/src/widgets/mod.rs b/widgetry/src/widgets/mod.rs index 9adc668129..03a4dd0c59 100644 --- a/widgetry/src/widgets/mod.rs +++ b/widgetry/src/widgets/mod.rs @@ -11,7 +11,7 @@ use abstutil::CloneableAny; use geom::{CornerRadii, Distance, Percent, Polygon}; use crate::widgets::containers::{Container, Nothing}; -pub use crate::widgets::panel::{Panel, PanelBuilder}; +pub use crate::widgets::panel::{Panel, PanelBuilder, PanelDims}; use crate::{ Button, Choice, Color, DeferDraw, Drawable, Dropdown, EventCtx, GeomBatch, GfxCtx, JustDraw, OutlineStyle, ScreenDims, ScreenPt, ScreenRectangle, Toggle, diff --git a/widgetry/src/widgets/panel.rs b/widgetry/src/widgets/panel.rs index 96bb2824aa..2abb21389d 100644 --- a/widgetry/src/widgets/panel.rs +++ b/widgetry/src/widgets/panel.rs @@ -7,7 +7,7 @@ use stretch::node::{Node, Stretch}; use stretch::number::Number; use stretch::style::{Dimension, Style}; -use geom::{Percent, Polygon}; +use geom::Polygon; use crate::widgets::slider; use crate::widgets::spinner::SpinnerValue; @@ -24,7 +24,8 @@ pub struct Panel { cached_flexbox: Option<(Stretch, Vec, ScreenDims)>, horiz: HorizontalAlignment, vert: VerticalAlignment, - dims: Dims, + dims_x: PanelDims, + dims_y: PanelDims, scrollable_x: bool, scrollable_y: bool, @@ -39,7 +40,8 @@ impl Panel { top_level, horiz: HorizontalAlignment::Center, vert: VerticalAlignment::Center, - dims: Dims::MaxPercent(Percent::int(100), Percent::int(100)), + dims_x: PanelDims::MaxPercent(1.0), + dims_y: PanelDims::MaxPercent(1.0), ignore_initial_events: false, } } @@ -50,30 +52,17 @@ impl Panel { } fn update_container_dims_for_canvas_dims(&mut self, canvas_dims: ScreenDims) { - let new_container_dims = match self.dims { - Dims::MaxPercent(w, h) => ScreenDims::new( - self.contents_dims.width.min(w.inner() * canvas_dims.width), - self.contents_dims - .height - .min(h.inner() * canvas_dims.height), - ), - Dims::ExactPercent(w, h) => { - ScreenDims::new(w * canvas_dims.width, h * canvas_dims.height) - } - Dims::ExactSize(dims) => dims, - Dims::ExactHeightPixels(h) => { - ScreenDims::new(self.contents_dims.width.min(canvas_dims.width), h) - } - Dims::ExactHeightPercent(pct) => ScreenDims::new( - self.contents_dims.width.min(canvas_dims.width), - pct * canvas_dims.height, - ), - Dims::ExactWidthPercent(pct) => ScreenDims::new( - pct * canvas_dims.width, - self.contents_dims.height.min(canvas_dims.height), - ), + let width = match self.dims_x { + PanelDims::MaxPercent(pct) => self.contents_dims.width.min(pct * canvas_dims.width), + PanelDims::ExactPercent(pct) => pct * canvas_dims.width, + PanelDims::ExactPixels(x) => x, }; - self.container_dims = new_container_dims; + let height = match self.dims_y { + PanelDims::MaxPercent(pct) => self.contents_dims.height.min(pct * canvas_dims.height), + PanelDims::ExactPercent(pct) => pct * canvas_dims.height, + PanelDims::ExactPixels(x) => x, + }; + self.container_dims = ScreenDims::new(width, height); } fn recompute_scrollbar_layout(&mut self, ctx: &EventCtx) { @@ -589,17 +578,16 @@ pub struct PanelBuilder { top_level: Widget, horiz: HorizontalAlignment, vert: VerticalAlignment, - dims: Dims, + dims_x: PanelDims, + dims_y: PanelDims, ignore_initial_events: bool, } -enum Dims { - MaxPercent(Percent, Percent), - ExactPercent(f64, f64), - ExactHeightPixels(f64), - ExactHeightPercent(f64), - ExactWidthPercent(f64), - ExactSize(ScreenDims), +#[derive(Clone, Copy)] +pub enum PanelDims { + MaxPercent(f64), + ExactPercent(f64), + ExactPixels(f64), } impl PanelBuilder { @@ -615,7 +603,8 @@ impl PanelBuilder { horiz: self.horiz, vert: self.vert, - dims: self.dims, + dims_x: self.dims_x, + dims_y: self.dims_y, scrollable_x: false, scrollable_y: false, @@ -624,30 +613,27 @@ impl PanelBuilder { clip_rect: None, cached_flexbox: None, }; - match panel.dims { - Dims::ExactPercent(w, h) => { + match self.dims_x { + PanelDims::MaxPercent(_) => {} + PanelDims::ExactPercent(pct) => { // Don't set size, because then scrolling breaks -- the actual size has to be based // on the contents. - panel.top_level.layout.style.min_size = Size { - width: Dimension::Points((w * ctx.canvas.window_width) as f32), - height: Dimension::Points((h * ctx.canvas.window_height) as f32), - }; - } - Dims::ExactHeightPixels(h) => { - panel.top_level.layout.style.min_size.height = Dimension::Points(h as f32); - } - Dims::ExactHeightPercent(pct) => { - panel.top_level.layout.style.min_size.height = - Dimension::Points((pct * ctx.canvas.window_height) as f32); - } - Dims::ExactWidthPercent(pct) => { panel.top_level.layout.style.min_size.width = Dimension::Points((pct * ctx.canvas.window_width) as f32); } - Dims::ExactSize(dims) => { - panel.top_level.layout.style.min_size = dims.into(); + PanelDims::ExactPixels(x) => { + panel.top_level.layout.style.min_size.width = Dimension::Points(x as f32); + } + } + match self.dims_y { + PanelDims::MaxPercent(_) => {} + PanelDims::ExactPercent(pct) => { + panel.top_level.layout.style.min_size.height = + Dimension::Points((pct * ctx.canvas.window_height) as f32); + } + PanelDims::ExactPixels(x) => { + panel.top_level.layout.style.min_size.height = Dimension::Points(x as f32); } - Dims::MaxPercent(_, _) => {} } // There is a dependency cycle in our layout logic. As a consequence: @@ -692,37 +678,20 @@ impl PanelBuilder { self } - pub fn max_size(mut self, width: Percent, height: Percent) -> PanelBuilder { - if width == Percent::int(100) && height == Percent::int(100) { - panic!("By default, Panels are capped at 100% of the screen. This is redundant."); - } - self.dims = Dims::MaxPercent(width, height); + pub fn dims_width(mut self, dims: PanelDims) -> PanelBuilder { + self.dims_x = dims; self } - pub fn exact_size_percent(mut self, pct_width: usize, pct_height: usize) -> PanelBuilder { - self.dims = Dims::ExactPercent((pct_width as f64) / 100.0, (pct_height as f64) / 100.0); + pub fn dims_height(mut self, dims: PanelDims) -> PanelBuilder { + self.dims_y = dims; self } - pub fn exact_height_pixels(mut self, height: f64) -> PanelBuilder { - self.dims = Dims::ExactHeightPixels(height); - self - } - - pub fn exact_height_percent(mut self, pct: f64) -> PanelBuilder { - self.dims = Dims::ExactHeightPercent(pct); - self - } - - pub fn exact_width_percent(mut self, pct: f64) -> PanelBuilder { - self.dims = Dims::ExactWidthPercent(pct); - self - } - - pub fn exact_size(mut self, size: ScreenDims) -> PanelBuilder { - self.dims = Dims::ExactSize(size); - self + // TODO Change all callers + pub fn exact_size_percent(self, x: usize, y: usize) -> PanelBuilder { + self.dims_width(PanelDims::ExactPercent((x as f64) / 100.0)) + .dims_height(PanelDims::ExactPercent((y as f64) / 100.0)) } /// When a panel is built, a fake, "no-op" mouseover event is immediately fired, to let all diff --git a/widgetry_demo/src/lib.rs b/widgetry_demo/src/lib.rs index abbe1bc73e..9db11c73f9 100644 --- a/widgetry_demo/src/lib.rs +++ b/widgetry_demo/src/lib.rs @@ -1,12 +1,12 @@ use rand::SeedableRng; use rand_xorshift::XorShiftRng; -use geom::{Angle, Duration, Percent, Polygon, Pt2D, Time, UnitFmt}; +use geom::{Angle, Duration, Polygon, Pt2D, Time, UnitFmt}; use widgetry::{ lctrl, Choice, Color, ContentMode, DragDrop, Drawable, EventCtx, Fill, GeomBatch, GfxCtx, - HorizontalAlignment, Image, Key, Line, LinePlot, Outcome, Panel, PersistentSplit, PlotOptions, - ScreenDims, Series, Settings, SharedAppState, StackAxis, State, TabController, Text, TextExt, - Texture, Toggle, Transition, UpdateType, VerticalAlignment, Widget, + HorizontalAlignment, Image, Key, Line, LinePlot, Outcome, Panel, PanelDims, PersistentSplit, + PlotOptions, ScreenDims, Series, Settings, SharedAppState, StackAxis, State, TabController, + Text, TextExt, Texture, Toggle, Transition, UpdateType, VerticalAlignment, Widget, }; pub fn main() { @@ -121,7 +121,8 @@ impl Demo { ])) // Don't let the panel exceed this percentage of the window. Scrollbars appear // automatically if needed. - .max_size(Percent::int(30), Percent::int(40)) + .dims_width(PanelDims::MaxPercent(0.3)) + .dims_height(PanelDims::MaxPercent(0.4)) // We take up 30% width, and we want to leave 10% window width as buffer. .aligned(HorizontalAlignment::Percent(0.6), VerticalAlignment::Center) .build(ctx);