The Material page's caps were grey and twelve of them were one picture. The face: most stock sheets give a button a second fill stop (macos-dark's is #353537) and the page set the first stop only, so each cap was a blend of the ground and that grey. The cap clears the second stop, as the slider's handle already did. The states: a state applied as a widget's default (`hover: {default: @down}`) is handed to the shader's slots as written, and a slot skipped a `snap(..)`, which the button's hover.on and hover.down are both written with; disabled is a plain number, which is why it alone showed. `write_value_to_f32_slots` writes the value a snap carries. Any event that reached a posed cap also played its hover off, so the four posed caps of a row stand in a StillView, which moves from the foundations page to the shell for any page to use; the first cap of each row stays live. Focus: the page set border_size 0, which took the ring away. The cap keeps a stroke that is clear in every state but focus, in the glow ink. Size: the bench's numbers are tuned on a face of 156 by 72 and were read on one of 51 by 28, where a shadow 12 long is more shadow than face. The caps are one width, a face 104 by 52, the largest five to a row leaves room for, and a row too narrow for five breaks. The lit label takes the material's glow ink rather than the theme's, and on the illuminating row is pushed far enough to clip near white.
173 lines
7.1 KiB
Rust
173 lines
7.1 KiB
Rust
//! The two script namespaces every story file relies on and the page
|
|
//! templates stories are built from.
|
|
//!
|
|
//! `mod.stories` holds one template per story, looked up by name at runtime
|
|
//! by the canvas. `mod.storybook` holds the shared building blocks so a story
|
|
//! file can say `use mod.storybook.*` and write `StoryPage{ StoryRow{ ... } }`.
|
|
//! This module registers first; the story files come after it and the app
|
|
//! shell last, because a block's `use` only sees what exists when it runs.
|
|
use crate::makepad_widgets::*;
|
|
|
|
script_mod! {
|
|
use mod.prelude.widgets.*
|
|
use mod.widgets.*
|
|
|
|
mod.storybook = {}
|
|
mod.stories = {}
|
|
|
|
/** A story's page: a scrolling column the story fills top to bottom. */
|
|
mod.storybook.StoryPage = View{
|
|
width: Fill
|
|
height: Fill
|
|
flow: Down
|
|
spacing: theme.space_2
|
|
padding: theme.mspace_3
|
|
scroll_bars: ScrollBars{
|
|
show_scroll_x: false
|
|
show_scroll_y: true
|
|
scroll_bar_y.drag_scrolling: true
|
|
}
|
|
}
|
|
|
|
/** A row of instances, laid out left to right and centred vertically. */
|
|
mod.storybook.StoryRow = View{
|
|
width: Fill
|
|
height: Fit
|
|
flow: Right
|
|
spacing: theme.space_2
|
|
align: Align{x: 0. y: 0.5}
|
|
}
|
|
|
|
mod.storybook.StillViewBase = #(StillView::register_widget(vm))
|
|
/** A view that passes no event to anything inside it, so whatever state its children were built in is the state they keep. */
|
|
mod.storybook.StillView = set_type_default() do mod.storybook.StillViewBase{
|
|
width: Fill
|
|
height: Fit
|
|
flow: Down
|
|
}
|
|
|
|
/** A section heading inside a story page. */
|
|
mod.storybook.StoryHeading = H4{}
|
|
|
|
/** A line of explanation under a heading. */
|
|
mod.storybook.StoryNote = P{}
|
|
|
|
/** Coloured ground for the glass family to bend.
|
|
*
|
|
* Two kinds of content on purpose. The wash gives the lens something to
|
|
* shift; the rings and the bars give it something to shift AT the scale
|
|
* the refraction works on. A wash alone has no detail that fine, so the
|
|
* bend has nothing to show and the colour split has nothing to split,
|
|
* and the surface reads as a grey rectangle however well it is tuned. */
|
|
mod.storybook.GlassGround = View{
|
|
width: Fill
|
|
height: Fill
|
|
show_bg: true
|
|
draw_bg +: {
|
|
pixel: fn() {
|
|
let p = self.pos
|
|
let h = max(self.rect_size.y, 1.0)
|
|
let aspect = self.rect_size.x / h
|
|
// Square-ish space, so the rings stay round on a wide band.
|
|
let q = vec2(p.x * aspect, p.y)
|
|
|
|
let a = vec3(0.05, 0.12, 0.38)
|
|
let b = vec3(0.62, 0.16, 0.42)
|
|
let c = vec3(0.05, 0.42, 0.45)
|
|
let m = mix(a, b, p.x)
|
|
let n = mix(c, b, p.y)
|
|
var col = mix(m, n, 0.45 + 0.35 * sin(p.x * 6.0 + p.y * 3.0))
|
|
|
|
let ring_a = abs(length(q - vec2(aspect * 0.26, 0.34)) - 0.21)
|
|
col = mix(vec3(0.98, 0.86, 0.42), col, smoothstep(0.0, 0.014, ring_a))
|
|
let ring_b = abs(length(q - vec2(aspect * 0.72, 0.70)) - 0.28)
|
|
col = mix(vec3(0.42, 0.92, 0.86), col, smoothstep(0.0, 0.014, ring_b))
|
|
let bars = abs(fract((q.x + q.y) * 7.0) - 0.5)
|
|
col = mix(col * 1.35, col, smoothstep(0.0, 0.05, bars - 0.30))
|
|
return vec4(col, 1.0)
|
|
}
|
|
}
|
|
}
|
|
|
|
/** A band of ground with a scrim over it and a slot for the demo.
|
|
*
|
|
* Every glass page needs one: these widgets draw what is BEHIND them, so
|
|
* over a plain page there is nothing behind them to draw and the whole
|
|
* family collapses to an outline. The scrim is not decoration either -
|
|
* the ground at full chroma out-shouts the lens, and the refraction is
|
|
* read from the difference between neighbouring pixels, which a scrim
|
|
* keeps legible without flattening the ground into one colour.
|
|
*
|
|
* Every layer is NAMED. A variant of this stage has to override its
|
|
* layers by name: a derived object copies the prototype's children and
|
|
* then appends its own, so an anonymous child in a derived block adds a
|
|
* layer rather than replacing one, and the last thing added in an
|
|
* Overlay flow is painted over everything else. Nothing warns about it.
|
|
*
|
|
* The height is FIXED, never Fit. The ground is `height: Fill`, and a
|
|
* Fill child of a Fit parent is handed nothing at all - which drew no
|
|
* gradient and quietly made this page's whole comparison a lie the first
|
|
* time it was written. Callers set the height; they must not set Fit,
|
|
* and they must leave room for the clearance the body spends. */
|
|
mod.storybook.GlassStage = View{
|
|
width: Fill
|
|
height: 220.
|
|
flow: Overlay
|
|
|
|
ground := mod.storybook.GlassGround{}
|
|
// SolidView, not a View with show_bg: a bare View's draw_bg has no
|
|
// `color`, so the wash was declared here for as long as the page
|
|
// existed and never painted a pixel.
|
|
scrim := SolidView{
|
|
width: Fill
|
|
height: Fill
|
|
draw_bg +: {color: #x02040a26}
|
|
}
|
|
body := View{
|
|
width: Fill
|
|
height: Fill
|
|
flow: Down
|
|
spacing: 12.
|
|
// The clearance is arithmetic, not taste. The rim samples along
|
|
// the outward normal by up to `lensing_strength` points, and the
|
|
// panel family ships 28 of them - so ground that stops at the
|
|
// glass hands the bend the page background instead of the
|
|
// ground, and the edge everyone looks at is the part that goes
|
|
// wrong. 30 is that reach, rounded up to the nearest ten, on
|
|
// all four sides: the top and the bottom rims bend exactly as
|
|
// far as the sides do.
|
|
padding: Inset{left: 30., right: 30., top: 30., bottom: 30.}
|
|
align: Align{x: 0. y: 0.5}
|
|
}
|
|
}
|
|
|
|
/** The same band with nothing on it at all, for the comparison every
|
|
* glass page should make once: the demo stands over the page itself,
|
|
* which is what a reader who drops one of these on a plain window gets.
|
|
*
|
|
* Both layers are switched off BY NAME. Writing replacements as
|
|
* anonymous children would add a fourth and a fifth layer instead, and
|
|
* whatever was painted last would land over the demo. */
|
|
mod.storybook.FlatStage = mod.storybook.GlassStage{
|
|
ground +: {visible: false}
|
|
scrim +: {visible: false}
|
|
}
|
|
}
|
|
|
|
/// A view that hands no event to its children. A page that shows a control
|
|
/// in each of its states builds each one in the state it shows, and any
|
|
/// event that reaches one (a pointer passing over it, the hover being
|
|
/// cleared) would play its hover off and leave it showing rest.
|
|
#[derive(Script, ScriptHook, Widget)]
|
|
pub struct StillView {
|
|
#[deref]
|
|
view: View,
|
|
}
|
|
|
|
impl Widget for StillView {
|
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
|
self.view.draw_walk(cx, scope, walk)
|
|
}
|
|
|
|
fn handle_event(&mut self, _cx: &mut Cx, _event: &Event, _scope: &mut Scope) {}
|
|
}
|