Theme switches
The main button API only allows re-writing one color of the image. Since we need to rewrite multiple colors for the switch, I introduced a `image_batch` for buttons which lets you do all kinds of manual fanciness, and pass the result into the button API.
@ -5,7 +5,7 @@ use aabb_quadtree::geom::{Point, Rect};
|
||||
use crate::{Distance, LonLat, Polygon, Pt2D, Ring};
|
||||
|
||||
/// Represents a rectangular boundary of `Pt2D` points.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Bounds {
|
||||
pub min_x: f64,
|
||||
pub min_y: f64,
|
||||
|
6
widgetry/icons/switch_off.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="30" height="16" viewBox="0 0 30 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="white" x="0" y="0" width="30" height="16" rx="8"></rect>
|
||||
<circle fill="black" cx="7" cy="8" r="4"></circle>
|
||||
<path fill="black" d="M13.4443 9.30957C13.4443 8.79199 13.5452 8.3265 13.7471 7.91309C13.9521 7.49967 14.2354 7.18066 14.5967 6.95605C14.9613 6.73145 15.3763 6.61914 15.8418 6.61914C16.5612 6.61914 17.1423 6.86816 17.585 7.36621C18.0309 7.86426 18.2539 8.52669 18.2539 9.35352V9.41699C18.2539 9.93132 18.1546 10.3936 17.9561 10.8037C17.7607 11.2106 17.4792 11.528 17.1113 11.7559C16.7467 11.9837 16.3268 12.0977 15.8516 12.0977C15.1354 12.0977 14.5544 11.8486 14.1084 11.3506C13.6657 10.8525 13.4443 10.1934 13.4443 9.37305V9.30957ZM14.3525 9.41699C14.3525 10.0029 14.4876 10.4733 14.7578 10.8281C15.0312 11.1829 15.3958 11.3604 15.8516 11.3604C16.3105 11.3604 16.6751 11.1813 16.9453 10.8232C17.2155 10.4619 17.3506 9.95736 17.3506 9.30957C17.3506 8.73014 17.2122 8.26139 16.9355 7.90332C16.6621 7.54199 16.2975 7.36133 15.8418 7.36133C15.3958 7.36133 15.0361 7.53874 14.7627 7.89355C14.4893 8.24837 14.3525 8.75618 14.3525 9.41699ZM19.8311 12V7.41504H18.9961V6.7168H19.8311V6.1748C19.8311 5.6084 19.9824 5.17057 20.2852 4.86133C20.5879 4.55208 21.016 4.39746 21.5693 4.39746C21.7777 4.39746 21.9844 4.42513 22.1895 4.48047L22.1406 5.21289C21.9876 5.18359 21.8249 5.16895 21.6523 5.16895C21.3594 5.16895 21.1331 5.25521 20.9736 5.42773C20.8141 5.59701 20.7344 5.84115 20.7344 6.16016V6.7168H21.8623V7.41504H20.7344V12H19.8311ZM23.3076 12V7.41504H22.4727V6.7168H23.3076V6.1748C23.3076 5.6084 23.459 5.17057 23.7617 4.86133C24.0645 4.55208 24.4925 4.39746 25.0459 4.39746C25.2542 4.39746 25.4609 4.42513 25.666 4.48047L25.6172 5.21289C25.4642 5.18359 25.3014 5.16895 25.1289 5.16895C24.8359 5.16895 24.6097 5.25521 24.4502 5.42773C24.2907 5.59701 24.2109 5.84115 24.2109 6.16016V6.7168H25.3389V7.41504H24.2109V12H23.3076Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
5
widgetry/icons/switch_on.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="30" height="16" viewBox="0 0 30 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="white" x="0" y="0" width="30" height="16" rx="8"></rect>
|
||||
<circle fill="black" cx="23" cy="8" r="4"></circle>
|
||||
<path fill="black" d="M5.44434 8.30957C5.44434 7.79199 5.54525 7.3265 5.74707 6.91309C5.95215 6.49967 6.23535 6.18066 6.59668 5.95605C6.96126 5.73145 7.3763 5.61914 7.8418 5.61914C8.5612 5.61914 9.14225 5.86816 9.58496 6.36621C10.0309 6.86426 10.2539 7.52669 10.2539 8.35352V8.41699C10.2539 8.93132 10.1546 9.39355 9.95605 9.80371C9.76074 10.2106 9.47917 10.528 9.11133 10.7559C8.74674 10.9837 8.32682 11.0977 7.85156 11.0977C7.13542 11.0977 6.55436 10.8486 6.1084 10.3506C5.66569 9.85254 5.44434 9.19336 5.44434 8.37305V8.30957ZM6.35254 8.41699C6.35254 9.00293 6.48763 9.47331 6.75781 9.82812C7.03125 10.1829 7.39583 10.3604 7.85156 10.3604C8.31055 10.3604 8.67513 10.1813 8.94531 9.82324C9.21549 9.46191 9.35059 8.95736 9.35059 8.30957C9.35059 7.73014 9.21224 7.26139 8.93555 6.90332C8.66211 6.54199 8.29753 6.36133 7.8418 6.36133C7.39583 6.36133 7.03613 6.53874 6.7627 6.89355C6.48926 7.24837 6.35254 7.75618 6.35254 8.41699ZM12.2412 5.7168L12.2705 6.38086C12.6742 5.87305 13.2015 5.61914 13.8525 5.61914C14.9691 5.61914 15.5322 6.24902 15.542 7.50879V11H14.6387V7.50391C14.6354 7.12305 14.5475 6.84147 14.375 6.65918C14.2057 6.47689 13.9404 6.38574 13.5791 6.38574C13.2861 6.38574 13.029 6.46387 12.8076 6.62012C12.5863 6.77637 12.4137 6.98145 12.29 7.23535V11H11.3867V5.7168H12.2412Z" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -1,3 +1,5 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M25.5 10.5H10.5C6.36 10.5 3 13.86 3 18C3 22.14 6.36 25.5 10.5 25.5H25.5C29.64 25.5 33 22.14 33 18C33 13.86 29.64 10.5 25.5 10.5ZM10.5 22.5C8.01 22.5 6 20.49 6 18C6 15.51 8.01 13.5 10.5 13.5C12.99 13.5 15 15.51 15 18C15 20.49 12.99 22.5 10.5 22.5Z" fill="#F2F2F2"/>
|
||||
<svg width="30" height="16" viewBox="0 0 30 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="white" x="0" y="0" width="30" height="16" rx="8"></rect>
|
||||
<circle fill="black" cx="7" cy="8" r="4"></circle>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 377 B After Width: | Height: | Size: 220 B |
@ -1,4 +0,0 @@
|
||||
<svg width="30" height="16" viewBox="0 0 30 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M22.5 0.5H7.5C3.36 0.5 0 3.86 0 8C0 12.14 3.36 15.5 7.5 15.5H22.5C26.64 15.5 30 12.14 30 8C30 3.86 26.64 0.5 22.5 0.5ZM7.5 12.5C5.01 12.5 3 10.49 3 8C3 5.51 5.01 3.5 7.5 3.5C9.99 3.5 12 5.51 12 8C12 10.49 9.99 12.5 7.5 12.5Z" fill="#F2F2F2"/>
|
||||
<path d="M13.4443 9.30957C13.4443 8.79199 13.5452 8.3265 13.7471 7.91309C13.9521 7.49967 14.2354 7.18066 14.5967 6.95605C14.9613 6.73145 15.3763 6.61914 15.8418 6.61914C16.5612 6.61914 17.1423 6.86816 17.585 7.36621C18.0309 7.86426 18.2539 8.52669 18.2539 9.35352V9.41699C18.2539 9.93132 18.1546 10.3936 17.9561 10.8037C17.7607 11.2106 17.4792 11.528 17.1113 11.7559C16.7467 11.9837 16.3268 12.0977 15.8516 12.0977C15.1354 12.0977 14.5544 11.8486 14.1084 11.3506C13.6657 10.8525 13.4443 10.1934 13.4443 9.37305V9.30957ZM14.3525 9.41699C14.3525 10.0029 14.4876 10.4733 14.7578 10.8281C15.0312 11.1829 15.3958 11.3604 15.8516 11.3604C16.3105 11.3604 16.6751 11.1813 16.9453 10.8232C17.2155 10.4619 17.3506 9.95736 17.3506 9.30957C17.3506 8.73014 17.2122 8.26139 16.9355 7.90332C16.6621 7.54199 16.2975 7.36133 15.8418 7.36133C15.3958 7.36133 15.0361 7.53874 14.7627 7.89355C14.4893 8.24837 14.3525 8.75618 14.3525 9.41699ZM19.8311 12V7.41504H18.9961V6.7168H19.8311V6.1748C19.8311 5.6084 19.9824 5.17057 20.2852 4.86133C20.5879 4.55208 21.016 4.39746 21.5693 4.39746C21.7777 4.39746 21.9844 4.42513 22.1895 4.48047L22.1406 5.21289C21.9876 5.18359 21.8249 5.16895 21.6523 5.16895C21.3594 5.16895 21.1331 5.25521 20.9736 5.42773C20.8141 5.59701 20.7344 5.84115 20.7344 6.16016V6.7168H21.8623V7.41504H20.7344V12H19.8311ZM23.3076 12V7.41504H22.4727V6.7168H23.3076V6.1748C23.3076 5.6084 23.459 5.17057 23.7617 4.86133C24.0645 4.55208 24.4925 4.39746 25.0459 4.39746C25.2542 4.39746 25.4609 4.42513 25.666 4.48047L25.6172 5.21289C25.4642 5.18359 25.3014 5.16895 25.1289 5.16895C24.8359 5.16895 24.6097 5.25521 24.4502 5.42773C24.2907 5.59701 24.2109 5.84115 24.2109 6.16016V6.7168H25.3389V7.41504H24.2109V12H23.3076Z" fill="#666666"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.0 KiB |
@ -1,4 +0,0 @@
|
||||
<svg width="30" height="16" viewBox="0 0 30 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M22.5 0.5H7.5C3.36 0.5 0 3.86 0 8C0 12.14 3.36 15.5 7.5 15.5H22.5C26.64 15.5 30 12.14 30 8C30 3.86 26.64 0.5 22.5 0.5ZM22.5 12.5C20.01 12.5 18 10.49 18 8C18 5.51 20.01 3.5 22.5 3.5C24.99 3.5 27 5.51 27 8C27 10.49 24.99 12.5 22.5 12.5Z" fill="#F2F2F2"/>
|
||||
<path d="M5.44434 8.30957C5.44434 7.79199 5.54525 7.3265 5.74707 6.91309C5.95215 6.49967 6.23535 6.18066 6.59668 5.95605C6.96126 5.73145 7.3763 5.61914 7.8418 5.61914C8.5612 5.61914 9.14225 5.86816 9.58496 6.36621C10.0309 6.86426 10.2539 7.52669 10.2539 8.35352V8.41699C10.2539 8.93132 10.1546 9.39355 9.95605 9.80371C9.76074 10.2106 9.47917 10.528 9.11133 10.7559C8.74674 10.9837 8.32682 11.0977 7.85156 11.0977C7.13542 11.0977 6.55436 10.8486 6.1084 10.3506C5.66569 9.85254 5.44434 9.19336 5.44434 8.37305V8.30957ZM6.35254 8.41699C6.35254 9.00293 6.48763 9.47331 6.75781 9.82812C7.03125 10.1829 7.39583 10.3604 7.85156 10.3604C8.31055 10.3604 8.67513 10.1813 8.94531 9.82324C9.21549 9.46191 9.35059 8.95736 9.35059 8.30957C9.35059 7.73014 9.21224 7.26139 8.93555 6.90332C8.66211 6.54199 8.29753 6.36133 7.8418 6.36133C7.39583 6.36133 7.03613 6.53874 6.7627 6.89355C6.48926 7.24837 6.35254 7.75618 6.35254 8.41699ZM12.2412 5.7168L12.2705 6.38086C12.6742 5.87305 13.2015 5.61914 13.8525 5.61914C14.9691 5.61914 15.5322 6.24902 15.542 7.50879V11H14.6387V7.50391C14.6354 7.12305 14.5475 6.84147 14.375 6.65918C14.2057 6.47689 13.9404 6.38574 13.5791 6.38574C13.2861 6.38574 13.029 6.46387 12.8076 6.62012C12.5863 6.77637 12.4137 6.98145 12.29 7.23535V11H11.3867V5.7168H12.2412Z" fill="#666666"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.6 KiB |
@ -1,3 +1,4 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M25.5 10.5H10.5C6.36 10.5 3 13.86 3 18C3 22.14 6.36 25.5 10.5 25.5H25.5C29.64 25.5 33 22.14 33 18C33 13.86 29.64 10.5 25.5 10.5ZM25.5 22.5C23.01 22.5 21 20.49 21 18C21 15.51 23.01 13.5 25.5 13.5C27.99 13.5 30 15.51 30 18C30 20.49 27.99 22.5 25.5 22.5Z" fill="#F2F2F2"/>
|
||||
<svg width="30" height="16" viewBox="0 0 30 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="white" x="0" y="0" width="30" height="16" rx="8"></rect>
|
||||
<circle fill="black" cx="23" cy="8" r="4"></circle>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 382 B After Width: | Height: | Size: 220 B |
@ -260,7 +260,7 @@ impl<'b, 'a: 'b> ButtonBuilder<'a> {
|
||||
|
||||
/// Set the image for the button. If not set, the button will have no image.
|
||||
///
|
||||
/// This will replace any image previously set by [`Self::image_bytes`]
|
||||
/// This will replace any image previously set.
|
||||
pub fn image_path(mut self, path: &'a str) -> Self {
|
||||
// Currently we don't support setting image for other states like "hover", we easily
|
||||
// could, but the API gets more verbose for a thing we don't currently need.
|
||||
@ -272,7 +272,8 @@ impl<'b, 'a: 'b> ButtonBuilder<'a> {
|
||||
|
||||
/// Set the image for the button. If not set, the button will have no image.
|
||||
///
|
||||
/// This will replace any image previously set by [`Self::image_path`].
|
||||
/// This will replace any image previously set.
|
||||
///
|
||||
/// * `labeled_bytes`: is a (`label`, `bytes`) tuple you can generate with
|
||||
/// [`include_labeled_bytes!`]
|
||||
/// * `label`: a label to describe the bytes for debugging purposes
|
||||
@ -290,6 +291,19 @@ impl<'b, 'a: 'b> ButtonBuilder<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the image for the button. If not set, the button will have no image.
|
||||
///
|
||||
/// This will replace any image previously set.
|
||||
///
|
||||
/// This method is useful when doing more complex transforms. For example, to re-write more than
|
||||
/// one color for your button image, do so externally and pass in the resultant GeomBatch here.
|
||||
pub fn image_batch(mut self, batch: GeomBatch, bounds: geom::Bounds) -> Self {
|
||||
let mut image = self.default_style.image.take().unwrap_or_default();
|
||||
image.source = Some(ImageSource::GeomBatch(batch, bounds));
|
||||
self.default_style.image = Some(image);
|
||||
self
|
||||
}
|
||||
|
||||
/// Rewrite the color of the button's image.
|
||||
///
|
||||
/// This has no effect if the button does not have an image.
|
||||
@ -727,6 +741,7 @@ impl<'b, 'a: 'b> ButtonBuilder<'a> {
|
||||
enum ImageSource<'a> {
|
||||
Path(&'a str),
|
||||
Bytes { bytes: &'a [u8], cache_key: &'a str },
|
||||
GeomBatch(GeomBatch, geom::Bounds),
|
||||
}
|
||||
|
||||
impl ImageSource<'_> {
|
||||
@ -739,6 +754,7 @@ impl ImageSource<'_> {
|
||||
cache_key
|
||||
))
|
||||
}
|
||||
ImageSource::GeomBatch(geom_batch, bounds) => (geom_batch.clone(), *bounds),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::svg::load_svg_bytes;
|
||||
use crate::{
|
||||
include_labeled_bytes, Button, Color, ControlState, EdgeInsets, EventCtx, GfxCtx, MultiKey,
|
||||
Outcome, RewriteColor, ScreenDims, ScreenPt, StyledButtons, Text, TextSpan, Widget, WidgetImpl,
|
||||
@ -36,20 +37,37 @@ impl Toggle {
|
||||
let mut buttons = ctx
|
||||
.style()
|
||||
.btn_plain_text(label)
|
||||
// we don't want the default coloring, because we do custom coloring below
|
||||
.image_color(RewriteColor::NoOp, ControlState::Default);
|
||||
|
||||
if let Some(hotkey) = hotkey.into() {
|
||||
buttons = buttons.hotkey(hotkey);
|
||||
}
|
||||
|
||||
let (off_batch, off_bounds) = {
|
||||
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_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_solid.bg))
|
||||
.color(RewriteColor::Change(Color::BLACK, ctx.style.btn_solid.fg));
|
||||
(batch, bounds)
|
||||
};
|
||||
|
||||
let off_button = buttons
|
||||
.clone()
|
||||
.image_bytes(include_labeled_bytes!("../../icons/toggle_off.svg"))
|
||||
.build(ctx, label);
|
||||
let on_button = buttons
|
||||
.image_bytes(include_labeled_bytes!("../../icons/toggle_on.svg"))
|
||||
.image_batch(off_batch, off_bounds)
|
||||
.build(ctx, label);
|
||||
|
||||
let on_button = buttons.image_batch(on_batch, on_bounds).build(ctx, label);
|
||||
|
||||
Toggle::new(enabled, off_button, on_button).named(label)
|
||||
}
|
||||
|
||||
@ -173,18 +191,40 @@ impl Toggle {
|
||||
) -> Widget {
|
||||
let mut toggle_left_button = ctx
|
||||
.style()
|
||||
.btn_plain_icon_bytes(include_labeled_bytes!("../../icons/toggle_left.svg"))
|
||||
.btn_plain()
|
||||
.image_dims(ScreenDims::new(40.0, 40.0))
|
||||
.padding(4)
|
||||
// we don't want the default coloring, because we do custom coloring below
|
||||
.image_color(RewriteColor::NoOp, ControlState::Default);
|
||||
|
||||
if let Some(hotkey) = hotkey.into() {
|
||||
toggle_left_button = toggle_left_button.hotkey(hotkey);
|
||||
}
|
||||
|
||||
let (left_batch, left_bounds) = {
|
||||
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_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_solid.bg))
|
||||
.color(RewriteColor::Change(Color::BLACK, ctx.style.btn_solid.fg));
|
||||
(batch, bounds)
|
||||
};
|
||||
|
||||
let toggle_right_button = toggle_left_button
|
||||
.clone()
|
||||
.image_bytes(include_labeled_bytes!("../../icons/toggle_right.svg"));
|
||||
.image_batch(right_batch, right_bounds);
|
||||
|
||||
let toggle_left_button = toggle_left_button
|
||||
.clone()
|
||||
.image_batch(left_batch, left_bounds);
|
||||
|
||||
let left_text_button = ctx
|
||||
.style()
|
||||
|