Slide 34 de 37
O módulo de UI
Uma página, servida diretamente
proc main(): void {
view := hive.ui.column([hive.ui.pad(24), hive.ui.gap(12)], [
hive.ui.text([hive.ui.size(hive.ui.TextSize.Title()), hive.ui.heading(1)], "Tour do Hive"),
hive.ui.row([hive.ui.gap(8)], [
hive.ui.input([hive.ui.placeholder("seu nome")], ""),
hive.ui.button([hive.ui.tone(hive.ui.Tone.Good())], "Dizer oi"),
]),
hive.ui.link([hive.ui.background(hive.ui.Tone.Good())], "/1", "Começar →"),
])
body := hive.ui.page("Hive", view) // um documento inteiro, servido diretamente
echo len(body)
}
Uma cena 3D, em uma window
type Msg { Tick }
func view(model: Int): hive.ui.View {
shapes := [
hive.ui.ground([hive.ui.paint(hive.ui.Tone.HEX("#2d5c34"))], 20.0, 20.0),
hive.ui.box(
[hive.ui.at(0.0, 0.5, -3.0), hive.ui.paint(hive.ui.Tone.HEX("#b5651d"))],
1.0, 1.0, 1.0,
),
hive.ui.sphere([hive.ui.at(2.0, 1.0, -4.0), hive.ui.paint(hive.ui.Tone.HEX("#e0c341"))], 1.0),
]
return hive.ui.scene(
[hive.ui.grow(1), hive.ui.eye(0.0, 1.6, 4.0), hive.ui.aim(0.0, 0.0), hive.ui.lens(70), hive.ui.fog(60)],
shapes,
)
}
proc update(model: Int, msg: Msg, envelope: hive.syslink.Envelope): Int {
return model
}
proc main(): void {
hive.ui.window("Uma cena 3D", view, update, 0)
}
Animando, e reagindo a um frame
type Msg {
Tick { ms: Int }
}
func view(angle: Float): hive.ui.View {
return hive.ui.scene(
[
hive.ui.grow(1),
hive.ui.eye(0.0, 1.5, 5.0),
hive.ui.aim(0.0, 0.0),
hive.ui.onFrame(Msg.Tick(_)),
],
[
hive.ui.ground([hive.ui.paint(hive.ui.Tone.Muted())], 10.0, 10.0),
hive.ui.box(
[hive.ui.at(0.0, 1.0, 0.0), hive.ui.turn(0.0, angle, 0.0), hive.ui.paint(hive.ui.Tone.Good())],
1.0, 1.0, 1.0,
),
],
)
}
// O onFrame de uma scene reporta quantos milissegundos o último frame levou,
// então o giro que esta caixa faz é em segundos reais, não em frames — a
// mesma caixa gira na mesma velocidade a trinta quadros por segundo ou a sessenta.
proc spin(angle: Float, msg: Msg, envelope: hive.syslink.Envelope): Float {
if msg is Msg.Tick(ms) {
return angle + hive.conv.itf(ms) * 0.002
}
return angle
}
proc main(): void {
hive.ui.window("Uma caixa girando", view, spin, 0.0)
}
hive.ui constrói uma interface como um valor: uma View é uma árvore de widgets, e cada um deles recebe as mesmas duas coisas, seus atributos e depois sua própria carga. row e column organizam filhos; text, image, icon e link mostram algo; button, input, textarea, checkbox e select pedem algo; table mostra uma Table, e spacer, spinner, none e overlay completam o conjunto. Os atributos são um conjunto igualmente fechado: gap, pad, width, height, grow, align, justify e scroll organizam; size, heading, tone e background estilizam; disabled, busy, placeholder, hint e kind descrevem estado; e on, onDismiss, onInput, onSubmit, onChoose, onToggle, onPick e onSort carregam um evento, para uma window e não para este tipo de página. Align, Justify, TextSize, Tone, Axis, InputKind e Icon são as enumerações por trás deles, acessadas como qualquer outro tipo da biblioteca.html(view) renderiza uma árvore como um fragmento HTML, e page(title, view) como um documento inteiro com uma stylesheet já embutida, claro e escuro igualmente — que é exatamente o que um handler de httpServe pode usar para responder a uma requisição diretamente, e o que toda tela deste tour, exceto suas amostras de código, é. A mesma árvore, mostrada em vez disso por window(title, view, update, state), se torna uma página viva: update é um fold sobre seus eventos, a mesma forma que um handler de hive.syslink faz fold sobre uma caixa de mensagens, então uma window tem um endereço e não precisa de mutex próprio.Uma scene é o único widget que somente uma window consegue desenhar. box, sphere, cylinder, ground, label e line são suas formas, posicionadas com at e turn e coloridas com paint; eye, aim, lens e fog posicionam e ajustam a câmera; grab e crosshair capturam o mouse, e onFrame, onKeyDown, onKeyUp, onLook e onGrab são os eventos que somente uma scene reporta. Uma página servida renderiza a caixa de uma scene vazia — não há um socket para os frames viajarem — então os dois exemplos abaixo são mostrados apenas como código: abra qualquer um deles em uma window para realmente ver.