Pular para o conteúdo

Telas, menus e atalhos

Navegar entre telas com parâmetros, a barra de menus, atalhos que viram Cmd no macOS, status, notificação e a tabela com seleção.

Telas e navegação#

Cada tela é uma ação que recebe t. A primeira registrada é a que abre. t.ir(nome, parametros) troca de tela e empilha; t.voltar() desempilha. Os dois acabam a tela ali — o que vem depois deles não roda.

dataforge
adopt Arcane.Bigorna as B
adopt Arcane.OS as OS

clientes := [{"id": 1, "nome": "Ana"}, {"id": 2, "nome": "Bruno"}]
app := B.app("CRM", pasta_de_config := $"{OS.temp_dir()}/df-doc-{randint(100000, 999999)}")

action lista(t):
    t.titulo("Clientes")
    cycle c in clientes:
        given t.botao(c["nome"]):
            t.ir("cliente", {"id": c["id"]})

action cliente(t):
    id := t.parametro("id")
    t.titulo($"Cliente {id}")
    given t.botao("Voltar"):
        t.voltar()

app.tela("lista", lista)
app.tela("cliente", cliente)

s := B.testar(app)
s.clicar("Bruno")
assert s.tela_atual() is "cliente"
assert s.tem("Cliente 2")
s.clicar("Voltar")
assert s.tela_atual() is "lista"

B.item(rótulo, comando, atalho) cria um item; t.comando("novo") é yes na execução em que ele foi escolhido — pelo menu ou pelo atalho, que são o mesmo evento.

dataforge
adopt Arcane.Bigorna as B
adopt Arcane.OS as OS

app := B.app("Editor", pasta_de_config := $"{OS.temp_dir()}/df-doc-{randint(100000, 999999)}")
app.menu("Arquivo", [
    B.item("Novo", "novo", atalho := "Ctrl+N"),
    B.item("Salvar", "salvar", atalho := "Ctrl+S"),
    B.separador(),
    B.item("Exportar PDF", "pdf", atalho := "Ctrl+Shift+E"),
])
app.menu("Ajuda", [B.item("Sobre", "sobre")])

eventos := []

action tela(t):
    t.titulo("Documento")
    cycle c in ["novo", "salvar", "pdf", "sobre"]:
        given t.comando(c):
            eventos.append(c)

app.tela("doc", tela)

s := B.testar(app)
s.atalho("Cmd+S")                   // Cmd e Ctrl são o mesmo atalho
s.atalho("ctrl+shift+e")            // a grafia é normalizada
s.menu("Ajuda", "Sobre")
assert eventos is ["salvar", "pdf", "sobre"]
out s.menus()
EscritoNo macOSNo Windows e no Linux
Ctrl+N⌘NCtrl+N
Ctrl+Shift+S⌘⇧SCtrl+Shift+S
Alt+F4⌥F4Alt+F4

O programa escreve Ctrl uma vez, e no macOS ele vira Cmd sozinho: um atalho que existisse num sistema só obrigaria a ramificar o código. Dois itens com o mesmo atalho são recusados — só um deles rodaria, e qual dependeria da ordem.

Status, notificação e atualizar#

dataforge
adopt Arcane.Bigorna as B
adopt Arcane.OS as OS

tarefas := ["ler", "escrever", "revisar"]
app := B.app("Tarefas", pasta_de_config := $"{OS.temp_dir()}/df-doc-{randint(100000, 999999)}")

action tela(t):
    t.lista(tarefas)
    t.status($"{len(tarefas)} tarefa(s)")
    given t.botao("Concluir a primeira"):
        tarefas.remove(tarefas[0])
        t.notificar("concluída")
        t.atualizar()               // o status acima já tinha sido calculado

app.tela("t", tela)

s := B.testar(app)
s.clicar("Concluir a primeira")
assert s.status() is "2 tarefa(s)"
assert s.notificacoes() is ["concluída"]

Na janela, a notificação aparece no topo e some sozinha em três segundos; o status fica na barra de baixo.

Tabela com seleção#

dataforge
adopt Arcane.Bigorna as B
adopt Arcane.OS as OS

pedidos := [{"n": 101, "total": 30}, {"n": 102, "total": 45}]
app := B.app("Pedidos", pasta_de_config := $"{OS.temp_dir()}/df-doc-{randint(100000, 999999)}")

action tela(t):
    escolhido := t.tabela(["n", "total"], pedidos, selecionar := yes)
    given escolhido is void:
        t.texto("escolha um pedido")
    otherwise:
        t.texto($"pedido {escolhido["n"]}: R$ {escolhido["total"]}")

app.tela("t", tela)

s := B.testar(app)
assert s.tem("escolha um pedido")
s.selecionar(1)
assert s.tem("pedido 102: R$ 45")

Ela devolve o que foi passado — o vault inteiro, e não o texto da célula —, ou void enquanto nada foi escolhido. Uma seleção que aponta para além da lista (ela encolheu) volta a void, em vez de devolver outra linha.