diff --git a/game/src/challenges/cutscene.rs b/game/src/challenges/cutscene.rs index 1ed96a85ed..b13d650dfa 100644 --- a/game/src/challenges/cutscene.rs +++ b/game/src/challenges/cutscene.rs @@ -251,7 +251,7 @@ fn make_panel( .fill_height() .padding(42) .bg(Color::WHITE) - .outline(ctx.style().btn_tab.outline), + .outline(ctx.style().btn_solid.outline), ]; Panel::new(Widget::custom_col(col)) diff --git a/game/src/challenges/mod.rs b/game/src/challenges/mod.rs index 73c4be13a0..40c9d39b31 100644 --- a/game/src/challenges/mod.rs +++ b/game/src/challenges/mod.rs @@ -149,7 +149,7 @@ impl ChallengesPicker { .centered_horiz() .bg(app.cs.panel_bg) .padding(16) - .outline(ctx.style().btn_tab.outline), + .outline(ctx.style().btn_solid.outline), ]; // First list challenges @@ -174,7 +174,7 @@ impl ChallengesPicker { .flex_wrap(ctx, Percent::int(80)) .bg(app.cs.panel_bg) .padding(16) - .outline(ctx.style().btn_tab.outline), + .outline(ctx.style().btn_solid.outline), ); let mut main_row = Vec::new(); @@ -201,7 +201,7 @@ impl ChallengesPicker { Widget::col(col) .bg(app.cs.panel_bg) .padding(16) - .outline(ctx.style().btn_tab.outline), + .outline(ctx.style().btn_solid.outline), ); } @@ -243,7 +243,7 @@ impl ChallengesPicker { Widget::col(inner_col) .bg(app.cs.panel_bg) .padding(16) - .outline(ctx.style().btn_tab.outline), + .outline(ctx.style().btn_solid.outline), ); current_challenge = Some(challenge); } diff --git a/game/src/info/mod.rs b/game/src/info/mod.rs index ee6e9c797c..dad9b42d24 100644 --- a/game/src/info/mod.rs +++ b/game/src/info/mod.rs @@ -11,8 +11,8 @@ use sim::{ VehicleType, }; use widgetry::{ - Color, ControlState, Drawable, EventCtx, GeomBatch, GfxCtx, Key, Line, LinePlot, Outcome, - Panel, PlotOptions, Series, TextExt, Toggle, Widget, + Drawable, EventCtx, GeomBatch, GfxCtx, Key, Line, LinePlot, Outcome, Panel, PlotOptions, + Series, TextExt, Toggle, Widget, }; use crate::app::{App, Transition}; @@ -711,32 +711,16 @@ fn make_tabs( ctx.style() .btn_tab .text(name) - // We use "disabled" to denote "currently selected", but we want to style it like - // normal + // We abuse "disabled" to denote "currently selected" .disabled(current_tab.variant() == link.variant()) - .bg_color(ctx.style().btn_tab.bg, ControlState::Disabled) - .label_color(ctx.style().btn_tab.fg, ControlState::Disabled) - .outline(ctx.style().btn_tab.outline, ControlState::Disabled) - // Hide the hit area for selectable tabs unless hovered - .bg_color(Color::CLEAR, ControlState::Default) - .outline((0.0, Color::CLEAR), ControlState::Default) - .bg_color(ctx.style().btn_tab.bg.alpha(0.6), ControlState::Hovered) .build_def(ctx), ); hyperlinks.insert(name.to_string(), link); } { - // stop-gap color that is semi-legible across themes until the tab redesign is completed - let tab_bg = ctx - .style() - .btn_tab - .bg - .lerp(ctx.style().btn_tab.fg, 0.3) - .alpha(1.0); - // TODO Centered, but actually, we need to set the padding of each button to divide the // available space evenly. Fancy fill rules... hmmm. - Widget::custom_row(row).bg(tab_bg).margin_vert(16) + Widget::custom_row(row).margin_vert(16) } } diff --git a/game/src/info/person.rs b/game/src/info/person.rs index 48614a58dd..1a322be77f 100644 --- a/game/src/info/person.rs +++ b/game/src/info/person.rs @@ -212,7 +212,7 @@ pub fn trips( .to_geom(ctx, Some(0.3)); rows.push( ctx.style() - .btn_floating + .btn_solid .btn() .custom_batch(row_btn.clone(), ControlState::Default) .custom_batch( diff --git a/game/src/sandbox/dashboards/trip_table.rs b/game/src/sandbox/dashboards/trip_table.rs index 6aa2aa5c16..c9390461dd 100644 --- a/game/src/sandbox/dashboards/trip_table.rs +++ b/game/src/sandbox/dashboards/trip_table.rs @@ -4,7 +4,7 @@ use abstutil::prettyprint_usize; use geom::{Duration, Time}; use sim::{TripEndpoint, TripID, TripMode}; use widgetry::table::{Col, Filter, Table}; -use widgetry::{ControlState, EventCtx, Filler, Line, Panel, State, Text, Toggle, Widget}; +use widgetry::{EventCtx, Filler, Line, Panel, State, Text, Toggle, Widget}; use crate::app::App; use crate::common::{checkbox_per_mode, cmp_duration_shorter, color_for_mode}; @@ -585,14 +585,11 @@ fn trip_category_selector(ctx: &mut EventCtx, app: &App, tab: DashTab) -> Widget let total = finished + cancelled + unfinished; let btn = |dash, action, label| { - let mut button = ctx.style().btn_tab.text(label); - if dash == tab { - button = button - .disabled(true) - .bg_color(ctx.style().btn_floating.bg, ControlState::Disabled) - .label_underlined_text(label); - } - button.build_widget(ctx, action) + ctx.style() + .btn_tab + .text(label) + .disabled(dash == tab) + .build_widget(ctx, action) }; Widget::custom_row(vec![ diff --git a/widgetry/src/style/button_style.rs b/widgetry/src/style/button_style.rs index d6bb1a84e4..c5276b45ee 100644 --- a/widgetry/src/style/button_style.rs +++ b/widgetry/src/style/button_style.rs @@ -106,15 +106,14 @@ impl<'a, 'c> Style { pub fn btn_popup_icon_text(&self, icon_path: &'a str, text: &'a str) -> ButtonBuilder<'a, 'c> { // The text is styled like an "outline" button, while the image is styled like a "solid" // button. - let solid_style = &self.btn_tab; self.btn_outline .btn() .label_text(text) .image_path(icon_path) .image_dims(25.0) - .image_color(solid_style.fg, ControlState::Default) - .image_bg_color(solid_style.bg, ControlState::Default) - .image_bg_color(solid_style.bg_hover, ControlState::Hovered) + .image_color(self.btn_solid.fg, ControlState::Default) + .image_bg_color(self.btn_solid.bg, ControlState::Default) + .image_bg_color(self.btn_solid.bg_hover, ControlState::Hovered) // Move the padding from the *entire button* to just the image, so we get a colored // padded area around the image. .padding(0) diff --git a/widgetry/src/style/mod.rs b/widgetry/src/style/mod.rs index 4d57554311..cc405ea1a5 100644 --- a/widgetry/src/style/mod.rs +++ b/widgetry/src/style/mod.rs @@ -20,6 +20,7 @@ pub struct Style { pub btn_plain: ButtonStyle, pub btn_outline: ButtonStyle, pub btn_floating: ButtonStyle, + pub btn_solid: ButtonStyle, pub btn_tab: ButtonStyle, pub btn_solid_destructive: ButtonStyle, pub btn_plain_destructive: ButtonStyle, @@ -161,14 +162,15 @@ impl Style { text_tooltip_color: Color::WHITE, text_destructive_color: hex("#FF5E5E"), btn_outline: ButtonStyle::outline_dark_fg(), + btn_solid: ButtonStyle::solid_light_fg(), btn_plain: ButtonStyle::plain_dark_fg(), btn_tab: ButtonStyle { - fg: Color::WHITE, - fg_disabled: Color::WHITE.alpha(0.3), - bg: hex("#4C4C4C").alpha(0.8), - bg_hover: hex("#4C4C4C"), - bg_disabled: Color::grey(0.6), - outline: (DEFAULT_OUTLINE_THICKNESS, hex("#4C4C4C").alpha(0.6)), + fg: hex("#4C4C4C").tint(0.2), + fg_disabled: hex("#4C4C4C"), + bg: Color::CLEAR, + bg_hover: hex("#4C4C4C").alpha(0.1), + bg_disabled: Color::WHITE, + outline: (0.0, Color::CLEAR), }, btn_floating: ButtonStyle::solid_dark_fg(), btn_solid_destructive: ButtonStyle::solid_destructive(), @@ -194,6 +196,7 @@ impl Style { text_destructive_color: hex("#EB3223"), btn_tab: ButtonStyle::solid_dark_fg(), btn_outline: ButtonStyle::outline_light_fg(), + btn_solid: ButtonStyle::solid_dark_fg(), btn_plain: ButtonStyle::plain_light_fg(), btn_floating: ButtonStyle::solid_light_fg(), btn_solid_destructive: ButtonStyle::solid_destructive(), @@ -220,8 +223,16 @@ impl Style { text_tooltip_color: Color::WHITE, text_destructive_color: hex("#FF5E5E"), btn_outline: ButtonStyle::outline_light_fg(), + btn_solid: ButtonStyle::solid_dark_fg(), btn_plain: ButtonStyle::plain_light_fg(), - btn_tab: ButtonStyle::solid_dark_fg(), + btn_tab: ButtonStyle { + fg: hex("#F2F2F2").shade(0.4), + fg_disabled: hex("#F2F2F2"), + bg: Color::CLEAR, + bg_hover: hex("#F2F2F2").alpha(0.1), + bg_disabled: navy, + outline: (0.0, Color::CLEAR), + }, btn_floating: ButtonStyle::solid_light_fg(), btn_solid_destructive: ButtonStyle::solid_destructive(), btn_plain_destructive: ButtonStyle::plain_destructive(), diff --git a/widgetry/src/widgets/dropdown.rs b/widgetry/src/widgets/dropdown.rs index 973365f061..0094df7b74 100644 --- a/widgetry/src/widgets/dropdown.rs +++ b/widgetry/src/widgets/dropdown.rs @@ -179,7 +179,7 @@ fn make_btn(ctx: &EventCtx, label: &str, tooltip: &str, is_persisten_split: bool // It's not ideal, but we only use one persistent split in the whole app // and it's front and center - we'll notice if something breaks. ctx.style() - .btn_tab + .btn_solid .dropdown() .padding(EdgeInsets { top: 15.0, diff --git a/widgetry/src/widgets/menu.rs b/widgetry/src/widgets/menu.rs index 5ed51fff67..1659b3d767 100644 --- a/widgetry/src/widgets/menu.rs +++ b/widgetry/src/widgets/menu.rs @@ -41,7 +41,7 @@ impl Menu { for (idx, choice) in self.choices.iter().enumerate() { let is_hovered = idx == self.current_idx; let mut text_color = if is_hovered { - choice.fg.unwrap_or(style.btn_tab.fg) + choice.fg.unwrap_or(style.btn_solid.fg) } else { choice.fg.unwrap_or(style.text_fg_color) }; @@ -71,7 +71,7 @@ impl Menu { // TODO BG color should be on the TextSpan, so this isn't so terrible? if is_hovered { - txt.highlight_last_line(style.btn_tab.bg); + txt.highlight_last_line(style.btn_solid.bg); } } txt diff --git a/widgetry/src/widgets/mod.rs b/widgetry/src/widgets/mod.rs index 70a588e361..bf2c6303ea 100644 --- a/widgetry/src/widgets/mod.rs +++ b/widgetry/src/widgets/mod.rs @@ -37,6 +37,8 @@ pub mod tabs; pub mod text_box; pub mod toggle; +pub const DEFAULT_CORNER_RADIUS: f64 = 5.0; + /// Create a new widget by implementing this trait. You can instantiate your widget by calling /// `Widget::new(Box::new(instance of your new widget))`, which gives you the usual style options. pub trait WidgetImpl: downcast_rs::Downcast { @@ -341,7 +343,7 @@ impl Widget { layout: LayoutStyle { bg_color: None, outline: None, - corner_rounding: CornerRounding::from(5.0), + corner_rounding: CornerRounding::from(DEFAULT_CORNER_RADIUS), style: Style { ..Default::default() }, diff --git a/widgetry/src/widgets/slider.rs b/widgetry/src/widgets/slider.rs index 3cc6bba6f0..345a111e8c 100644 --- a/widgetry/src/widgets/slider.rs +++ b/widgetry/src/widgets/slider.rs @@ -115,9 +115,9 @@ impl Slider { // The draggy thing batch.push( if self.mouse_on_slider { - ctx.style.btn_tab.bg_hover + ctx.style.btn_solid.bg_hover } else { - ctx.style.btn_tab.bg + ctx.style.btn_solid.bg }, self.button_geom(), ); @@ -140,12 +140,12 @@ impl Slider { // The circle dragger batch.push( if self.mouse_on_slider { - ctx.style.btn_tab.bg_hover + ctx.style.btn_solid.bg_hover } else { // we don't want to use `ctx.style.btn_solid.bg` because it achieves it's // "dulling" with opacity, which causes the slider to "peak through" and // looks weird. - ctx.style.btn_tab.bg_hover.dull(0.2) + ctx.style.btn_solid.bg_hover.dull(0.2) }, self.button_geom(), ); diff --git a/widgetry/src/widgets/tabs.rs b/widgetry/src/widgets/tabs.rs index dd3339d7ed..21dfff57e2 100644 --- a/widgetry/src/widgets/tabs.rs +++ b/widgetry/src/widgets/tabs.rs @@ -1,4 +1,6 @@ +use crate::widgets::DEFAULT_CORNER_RADIUS; use crate::{ButtonBuilder, EventCtx, Panel, Widget}; +use geom::CornerRadii; struct Tab { tab_id: String, @@ -18,6 +20,12 @@ impl Tab { fn build_bar_item_widget(&self, ctx: &EventCtx, active: bool) -> Widget { self.bar_item .clone() + .corner_rounding(CornerRadii { + top_left: DEFAULT_CORNER_RADIUS, + top_right: DEFAULT_CORNER_RADIUS, + bottom_left: 0.0, + bottom_right: 0.0, + }) .disabled(active) .build_widget(ctx, &self.tab_id) } @@ -57,10 +65,16 @@ impl TabController { /// A widget containing the tab bar and a content pane with the currently active tab. pub fn build_widget(&mut self, ctx: &EventCtx) -> Widget { - Widget::col(vec![ + Widget::custom_col(vec![ self.build_bar_items(ctx), self.pop_active_content() .container() + .corner_rounding(CornerRadii { + top_left: 0.0, + top_right: DEFAULT_CORNER_RADIUS, + bottom_left: DEFAULT_CORNER_RADIUS, + bottom_right: DEFAULT_CORNER_RADIUS, + }) .padding(16) .bg(ctx.style().section_bg) .named(self.active_content_id()), @@ -108,9 +122,9 @@ impl TabController { .enumerate() .map(|(idx, tab)| tab.build_bar_item_widget(ctx, idx == self.active_child)) .collect(); + Widget::row(bar_items) .container() - .bg(ctx.style().section_bg) .named(self.bar_items_id()) } diff --git a/widgetry/src/widgets/toggle.rs b/widgetry/src/widgets/toggle.rs index e4f050b3bb..61698300e2 100644 --- a/widgetry/src/widgets/toggle.rs +++ b/widgetry/src/widgets/toggle.rs @@ -48,16 +48,16 @@ impl Toggle { let (label, bytes) = include_labeled_bytes!("../../icons/switch_off.svg"); let (batch, bounds) = load_svg_bytes(ctx.prerender, label, bytes).expect("invalid SVG"); let batch = batch - .color(RewriteColor::Change(Color::WHITE, ctx.style.btn_tab.bg)) - .color(RewriteColor::Change(Color::BLACK, ctx.style.btn_tab.fg)); + .color(RewriteColor::Change(Color::WHITE, ctx.style.btn_solid.bg)) + .color(RewriteColor::Change(Color::BLACK, ctx.style.btn_solid.fg)); (batch, bounds) }; let (on_batch, on_bounds) = { let (label, bytes) = include_labeled_bytes!("../../icons/switch_on.svg"); let (batch, bounds) = load_svg_bytes(ctx.prerender, label, bytes).expect("invalid SVG"); let batch = batch - .color(RewriteColor::Change(Color::WHITE, ctx.style.btn_tab.bg)) - .color(RewriteColor::Change(Color::BLACK, ctx.style.btn_tab.fg)); + .color(RewriteColor::Change(Color::WHITE, ctx.style.btn_solid.bg)) + .color(RewriteColor::Change(Color::BLACK, ctx.style.btn_solid.fg)); (batch, bounds) }; @@ -208,16 +208,16 @@ impl Toggle { let (label, bytes) = include_labeled_bytes!("../../icons/toggle_left.svg"); let (batch, bounds) = load_svg_bytes(ctx.prerender, label, bytes).expect("invalid SVG"); let batch = batch - .color(RewriteColor::Change(Color::WHITE, ctx.style.btn_tab.bg)) - .color(RewriteColor::Change(Color::BLACK, ctx.style.btn_tab.fg)); + .color(RewriteColor::Change(Color::WHITE, ctx.style.btn_solid.bg)) + .color(RewriteColor::Change(Color::BLACK, ctx.style.btn_solid.fg)); (batch, bounds) }; let (right_batch, right_bounds) = { let (label, bytes) = include_labeled_bytes!("../../icons/toggle_right.svg"); let (batch, bounds) = load_svg_bytes(ctx.prerender, label, bytes).expect("invalid SVG"); let batch = batch - .color(RewriteColor::Change(Color::WHITE, ctx.style.btn_tab.bg)) - .color(RewriteColor::Change(Color::BLACK, ctx.style.btn_tab.fg)); + .color(RewriteColor::Change(Color::WHITE, ctx.style.btn_solid.bg)) + .color(RewriteColor::Change(Color::BLACK, ctx.style.btn_solid.fg)); (batch, bounds) }; diff --git a/widgetry_demo/src/lib.rs b/widgetry_demo/src/lib.rs index b680b27548..a9529e8592 100644 --- a/widgetry_demo/src/lib.rs +++ b/widgetry_demo/src/lib.rs @@ -25,6 +25,8 @@ pub fn main() { |ctx| { // TODO: remove Style::pregame and make light_bg the default. ctx.set_style(widgetry::Style::light_bg()); + // TODO: Add a toggle to switch theme in demo (and recreate UI in that new theme) + // ctx.set_style(widgetry::Style::dark_bg()); (App {}, vec![Box::new(Demo::new(ctx))]) }, @@ -332,42 +334,45 @@ fn make_tabs(ctx: &mut EventCtx) -> TabController { style .btn_solid_primary .text("Primary") - .build_widget(ctx, "btn_primary_text"), + .build_widget(ctx, "btn_solid_primary_text"), Widget::row(vec![ style .btn_solid_primary .icon("system/assets/tools/map.svg") - .build_widget(ctx, "btn_primary_icon_1"), + .build_widget(ctx, "btn_solid_primary_icon"), style .btn_plain_primary .icon("system/assets/tools/map.svg") - .build_widget(ctx, "btn_primary_icon_2"), + .build_widget(ctx, "btn_plain_primary_icon"), ]), style .btn_solid_primary .icon_text("system/assets/tools/location.svg", "Primary") - .build_widget(ctx, "btn_primary_icon_text"), + .build_widget(ctx, "btn_solid_primary_icon_text"), ]), Widget::row(vec![ style .btn_outline .text("Secondary") - .build_widget(ctx, "btn_outline_dark_text"), + .build_widget(ctx, "btn_outline_text"), Widget::row(vec![ style .btn_outline .icon("system/assets/tools/map.svg") - .build_widget(ctx, "btn_outline_dark_icon_1"), + .build_widget(ctx, "btn_outline_icon"), style .btn_plain .icon("system/assets/tools/map.svg") - .build_widget(ctx, "btn_outline_dark_icon_2"), + .build_widget(ctx, "btn_plain_icon"), ]), style .btn_outline .icon_text("system/assets/tools/home.svg", "Secondary") .build_widget(ctx, "btn_outline.icon_text"), ]), + Widget::row(vec![style + .btn_popup_icon_text("system/assets/tools/map.svg", "Popup") + .build_widget(ctx, "btn_popup_icon_text")]), Text::from_multiline(vec![ Line("Images").big_heading_styled().size(18), Line( @@ -502,95 +507,99 @@ fn make_tabs(ctx: &mut EventCtx) -> TabController { fn make_controls(ctx: &mut EventCtx, tabs: &mut TabController) -> Panel { Panel::new(Widget::col(vec![ - Text::from_multiline(vec![ - Line("widgetry demo").big_heading_styled(), - Line("Click and drag the background to pan, use touchpad or scroll wheel to zoom"), - ]) - .into_widget(ctx), - Widget::row(vec![ - ctx.style() - .btn_outline - .text("New faces") - .hotkey(Key::F) - .build_widget(ctx, "generate new faces"), - Toggle::switch(ctx, "Draw scrollable canvas", None, true), - Toggle::switch(ctx, "Show timeseries", lctrl(Key::T), false), - ]), - "Stopwatch: ..." - .text_widget(ctx) - .named("stopwatch") + Text::from(Line("widgetry demo").big_heading_styled()).into_widget(ctx), + Widget::col(vec![ + Text::from(Line( + "Click and drag the background to pan, use touchpad or scroll wheel to zoom", + )) + .into_widget(ctx), + Widget::row(vec![ + ctx.style() + .btn_outline + .text("New faces") + .hotkey(Key::F) + .build_widget(ctx, "generate new faces"), + Toggle::switch(ctx, "Draw scrollable canvas", None, true), + Toggle::switch(ctx, "Show timeseries", lctrl(Key::T), false), + ]), + "Stopwatch: ..." + .text_widget(ctx) + .named("stopwatch") + .margin_above(30), + Widget::row(vec![ + Toggle::new( + false, + ctx.style() + .btn_outline + .text("Pause") + .hotkey(Key::Space) + .build(ctx, "pause the stopwatch"), + ctx.style() + .btn_outline + .text("Resume") + .hotkey(Key::Space) + .build(ctx, "resume the stopwatch"), + ) + .named("paused"), + PersistentSplit::widget( + ctx, + "adjust timer", + Duration::seconds(20.0), + None, + vec![ + Choice::new("+20s", Duration::seconds(20.0)), + Choice::new("-10s", Duration::seconds(-10.0)), + ], + ), + ctx.style() + .btn_outline + .text("Reset Timer") + .build_widget(ctx, "reset the stopwatch"), + ]) + .evenly_spaced(), + Widget::row(vec![ + Widget::dropdown( + ctx, + "alignment", + (HorizontalAlignment::Center, VerticalAlignment::Top), + vec![ + Choice::new("Top", (HorizontalAlignment::Center, VerticalAlignment::Top)), + Choice::new( + "Left", + (HorizontalAlignment::Left, VerticalAlignment::Center), + ), + Choice::new( + "Bottom", + (HorizontalAlignment::Center, VerticalAlignment::Bottom), + ), + Choice::new( + "Right", + (HorizontalAlignment::Right, VerticalAlignment::Center), + ), + Choice::new( + "Center", + (HorizontalAlignment::Center, VerticalAlignment::Center), + ), + ], + ), + Widget::dropdown( + ctx, + "texture", + (Texture::SAND, Texture::CACTUS), + vec![ + Choice::new("Cold", (Texture::SNOW, Texture::SNOW_PERSON)), + Choice::new("Hot", (Texture::SAND, Texture::CACTUS)), + ], + ), + ctx.style() + .btn_solid_primary + .text("Apply") + .build_widget(ctx, "apply"), + ]) .margin_above(30), - Widget::row(vec![ - Toggle::new( - false, - ctx.style() - .btn_outline - .text("Pause") - .hotkey(Key::Space) - .build(ctx, "pause the stopwatch"), - ctx.style() - .btn_outline - .text("Resume") - .hotkey(Key::Space) - .build(ctx, "resume the stopwatch"), - ) - .named("paused"), - PersistentSplit::widget( - ctx, - "adjust timer", - Duration::seconds(20.0), - None, - vec![ - Choice::new("+20s", Duration::seconds(20.0)), - Choice::new("-10s", Duration::seconds(-10.0)), - ], - ), - ctx.style() - .btn_outline - .text("Reset Timer") - .build_widget(ctx, "reset the stopwatch"), ]) - .evenly_spaced(), - Widget::row(vec![ - Widget::dropdown( - ctx, - "alignment", - (HorizontalAlignment::Center, VerticalAlignment::Top), - vec![ - Choice::new("Top", (HorizontalAlignment::Center, VerticalAlignment::Top)), - Choice::new( - "Left", - (HorizontalAlignment::Left, VerticalAlignment::Center), - ), - Choice::new( - "Bottom", - (HorizontalAlignment::Center, VerticalAlignment::Bottom), - ), - Choice::new( - "Right", - (HorizontalAlignment::Right, VerticalAlignment::Center), - ), - Choice::new( - "Center", - (HorizontalAlignment::Center, VerticalAlignment::Center), - ), - ], - ), - Widget::dropdown( - ctx, - "texture", - (Texture::SAND, Texture::CACTUS), - vec![ - Choice::new("Cold", (Texture::SNOW, Texture::SNOW_PERSON)), - Choice::new("Hot", (Texture::SAND, Texture::CACTUS)), - ], - ), - ctx.style() - .btn_solid_primary - .text("Apply") - .build_widget(ctx, "apply"), - ]) - .margin_above(30), + .padding(16) + .bg(ctx.style().section_bg), tabs.build_widget(ctx), ])) // end panel .aligned(HorizontalAlignment::Center, VerticalAlignment::Top)