mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-23 17:07:12 +03:00
Simplify the combinatorial explosion of Panel sizing APIs
This commit is contained in:
parent
04f00b4c8a
commit
477783e430
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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<A: AppLike + 'static> AllCityPicker<A> {
|
||||
.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<A: AppLike + 'static> CitiesInCountryPicker<A> {
|
||||
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),
|
||||
})
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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<Node>, 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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user