toaster — n_pbt_toaster #
← Referência dos componentes · Índice do guia
Notificações «toast» no canto do ecrã: uma mensagem que aparece, informa e desaparece sem bloquear o utilizador nem interromper a sua introdução de dados.
▶ Ver ao vivo — Aplicação de demonstração, mosaico Toaster: a pré-visualização, o código que o produz e esta página, lado a lado.
Em resumo #
| Objeto | n_pbt_toaster — não visual: nada a colocar na window |
| Serve para | Confirmar uma ação bem-sucedida, assinalar um aviso ou um erro, sem parar o trabalho em curso |
| Retorno | Não bloqueante: of_show() devolve o controlo imediatamente; as reações do utilizador regressam por eventos |
O toast é uma window destacada: flutua por cima da aplicação (ou de todo o ecrã) e fecha-se sozinho.
n_pbt_toaster lnv_toast
lnv_toast = create n_pbt_toaster
// ... configuracao ...
destroy lnv_toast
Início rápido #
n_pbt_toaster lnv_toast
lnv_toast = create n_pbt_toaster
lnv_toast.ipo_owner = this // window a qual o toast se fixa
lnv_toast.is_kind = lnv_toast.KIND_SUCCESS // icone verde + friso de sucesso
lnv_toast.is_text = "As suas alterações foram [b]guardadas[/b]."
lnv_toast.of_show()
destroy lnv_toast
Tudo se configura por propriedades e, em seguida, of_show() — que não recebe qualquer argumento — faz aparecer a notificação.
Propriedades #
A definir antes de of_show.
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
is_text | string | "" | Corpo da mensagem. Aceita o texto formatado com etiquetas |
is_kind | string | KIND_INFO | Nível: comanda o ícone e a cor do friso. Constantes KIND_* |
is_position | string | POSITION_BOTTOM_RIGHT | Canto de fixação. Constantes POSITION_* |
ib_screen | boolean | false | false = fixado ao canto da window; true = fixado ao canto do ecrã, flutuando por cima de tudo |
il_timeout | long | TIMEOUT_AUTO | Tempo de apresentação em milissegundos antes do fecho automático. TIMEOUT_AUTO (-1, a predefinição) vale 4 s para uma informação mas até ao clique para um erro — um erro que se apaga em quatro segundos é um erro perdido. TIMEOUT_UNTIL_CLICKED (0) torna persistente qualquer toast; uma duração explícita é respeitada tal como está. Enquanto o ponteiro estiver sobre um toast a sua contagem decrescente fica suspensa, e uma barra mostra o tempo restante |
is_title | string | "" | Linha de título a negrito por cima da mensagem (toast enriquecido) |
is_image | string | "" | Imagem de ilustração à esquerda, em vez do ícone de nível (formas aceites: caminho, mono:, recurso de DLL) |
is_key | string | "" | Chave do toast: mostrar de novo a mesma chave atualiza o toast já no ecrã em vez de abrir um segundo. É disso que precisa uma notificação de progresso («Exportação 3/10» e depois «4/10»): fechar e reabrir reiniciaria a animação e baralharia a pilha. Deixe vazia para um toast comum |
il_max_visible | long | 5 | Número máximo de toasts no ecrã no mesmo canto (1 a 20). Para além disso, os seguintes esperam e aparecem à medida que se liberta espaço: um ciclo de processamento que emite um toast por linha empilhava de outro modo as janelas para fora do ecrã |
ipo_owner | powerobject | — | O objeto visual ao qual o toast está fixado (o canto da respetiva window serve de referência) |
ipo_receiver | powerobject | — | O objeto visual que recebe os eventos do toast. Deve deixar-se vazio para uma notificação sem retorno |
Constantes #
| Constante | Valor | Utilização |
|---|---|---|
KIND_INFO | "info" | Informação neutra |
KIND_SUCCESS | "success" | Operação bem-sucedida |
KIND_WARNING | "warning" | Aviso |
KIND_ERROR | "error" | Falha |
POSITION_TOP_LEFT | "top-left" | Canto superior esquerdo |
POSITION_TOP_CENTER | "top-center" | Superior, centrado |
POSITION_TOP_RIGHT | "top-right" | Canto superior direito |
POSITION_BOTTOM_LEFT | "bottom-left" | Canto inferior esquerdo |
POSITION_BOTTOM_CENTER | "bottom-center" | Inferior, centrado |
POSITION_BOTTOM_RIGHT | "bottom-right" | Canto inferior direito (predefinição) |
Porquê
LEFT/RIGHTaqui eSTART/ENDnoutros locais? O toast é uma window de sistema posicionada em pixels do ecrã, não um conteúdo que siga um sentido de leitura: um canto do ecrã não tem «início». Estas constantes permanecem, portanto, deliberadamente físicas, e não mudam de lado quando a aplicação passa a escrita da direita para a esquerda. Ver Idioma e RTL.
Métodos #
| Método | Função |
|---|---|
of_show ( ) → long | Apresenta a notificação construída a partir das propriedades. Devolve o identificador do toast (> 0), ou um valor negativo em caso de erro. Não bloqueia |
of_close ( long al_id ) → long | Fecha um toast ainda visível, designado pelo identificador devolvido por of_show. Devolve 0, ou -5 se o identificador estiver vazio ou designar um toast que já desapareceu |
of_reset ( ) | Repõe todas as propriedades de conteúdo na predefinição e apaga os botões (ipo_owner e ipo_receiver são preservados: são ligações, não conteúdo) |
of_process_events ( ) | Esvazia a fila de retornos do toast e desencadeia os eventos ue_toast_* correspondentes — ver abaixo |
of_add_button (string as_key, string as_label {, string as_image }) → long | Acrescenta um botão de ação (no máximo 3) e devolve quantos existem. Um clique emite ue_toast_action(id, chave); of_reset limpa os botões. Um rótulo pode conter qualquer carácter — uma vírgula, um sinal de igual — sem ser cortado |
Vários toasts apresentados no mesmo canto empilham-se automaticamente. Cada um tem uma cruz de fecho; o identificador devolvido por of_show permite distingui-los nos eventos e fechá-los a partir do código.
A contagem decrescente é suspensa enquanto o ponteiro estiver sobre o toast: uma notificação não deve desvanecer-se sob os olhos de quem a lê. Uma barra fina em baixo mostra o tempo restante — e explica assim o seu desaparecimento. Um clique no corpo responde e fecha, em ambos os modos de alojamento.
Uma notificação criada com il_timeout = 0 permanece no ecrã enquanto ninguém a fechar: convém guardar o respetivo identificador para a poder retirar quando a tarefa que anuncia estiver concluída.
long ll_toast
// Notificacao persistente : ficara visivel ate of_close.
inv_toaster.is_text = "Exportação em curso..."
inv_toaster.il_timeout = /*ms, 0 = sem fecho automatico*/ 0
ll_toast = inv_toaster.of_show()
// ... processamento demorado ...
inv_toaster.of_close(/*id*/ ll_toast)
Eventos — o toast responde #
Uma notificação não é um simples «apresentar e esquecer»: pode indicar que foi clicada, que um botão de ação foi escolhido, ou que se fechou.
Como o toast vive numa window destacada, a ligação faz-se em três etapas.
1. Designar o objeto visual destinatário:
inv_toaster.ipo_owner = this
inv_toaster.ipo_receiver = this // este userobject / esta window recebera os retornos
ipo_receivertem de ser um objeto visual (window ou userobject). Um objeto não visual não pode receber uma notificação de sistema.
2. Declarar nesse objeto visual um event mapeado em pbm_custom02, que esvazia a fila:
// event ue_toast_notified, mapeado em pbm_custom02
if IsValid(inv_toaster) then inv_toaster.of_process_events()
3. Tratar os eventos desencadeados no toaster:
| Evento | Acionado quando |
|---|---|
ue_toast_clicked (string as_id) | O corpo do toast é clicado (não um botão) |
ue_toast_action (string as_id, string as_action) | Um botão de ação é clicado; as_action contém a chave passada a of_add_button |
ue_toast_dismissed (string as_id) | O toast fecha-se: prazo esgotado, cruz de fecho, ou após uma ação |
Sem ipo_receiver, a notificação aparece e desaparece sem nunca devolver nada — é o modo mais simples, perfeito para uma simples confirmação.
Exemplos #
Os quatro níveis #
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_INFO
inv_toaster.is_text = "Operação concluída."
inv_toaster.of_show()
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_SUCCESS
inv_toaster.is_text = "As suas alterações foram [b]guardadas[/b]."
inv_toaster.of_show()
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_WARNING
inv_toaster.il_timeout = 5000 // um pouco mais longo
inv_toaster.is_text = "Espaço em disco reduzido na unidade C:."
inv_toaster.of_show()
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_ERROR
inv_toaster.il_timeout = 6000
inv_toaster.is_text = "Não foi possível contactar o servidor."
inv_toaster.of_show()
Escolher o canto, na window ou no ecrã #
// Fixado ao canto superior direito da WINDOW (predefinicao : acompanha a aplicacao)
inv_toaster.is_position = inv_toaster.POSITION_TOP_RIGHT
inv_toaster.ib_screen = false
inv_toaster.is_text = "Fixado ao canto da window."
inv_toaster.of_show()
// Destacado : fixado ao canto do ECRA, visivel mesmo se a window estiver minimizada
inv_toaster.is_position = inv_toaster.POSITION_TOP_RIGHT
inv_toaster.ib_screen = true
inv_toaster.is_text = "Processamento noturno concluído."
inv_toaster.of_show()
Toast enriquecido: título, imagem e duração #
inv_toaster.of_reset()
inv_toaster.is_title = "Cópia de segurança concluída"
inv_toaster.is_text = "1 240 ficheiros copiados para [b]\\servidor\backup[/b]."
inv_toaster.is_image = "mono:img\backup.svg"
inv_toaster.il_timeout = 8000 // permanece 8 segundos
inv_toaster.of_show()
Notificação com botões de ação #
// event open : ligar o retorno de uma vez por todas
inv_toaster.ipo_owner = this
inv_toaster.ipo_receiver = this
// Propor duas acoes ; timeout 0 = o toast aguarda a decisao do utilizador
inv_toaster.of_reset()
inv_toaster.is_title = "Atualização disponível"
inv_toaster.is_text = "A versão 2.0 está pronta a ser instalada."
inv_toaster.il_timeout = 0
inv_toaster.of_add_button(/*chave*/ "installer", /*rotulo*/ "Instalar")
inv_toaster.of_add_button(/*chave*/ "plus_tard", /*rotulo*/ "Mais tarde")
inv_toaster.of_show()
// event ue_toast_notified da window, mapeado em pbm_custom02
if IsValid(inv_toaster) then inv_toaster.of_process_events()
// event ue_toast_action de inv_toaster : (string as_id, string as_action)
choose case as_action
case "installer" ; of_lancer_mise_a_jour()
case "plus_tard" ; of_reporter(1)
end choose
Reagir ao clique na mensagem #
// event ue_toast_clicked de inv_toaster : (string as_id)
// O utilizador clicou no corpo do toast : abrir o ecra correspondente
Open(w_journal_import)
Notificar a partir de um processamento demorado #
// Fim de uma importacao : informar sem bloquear o ecra de introducao de dados
inv_toaster.of_reset()
if ll_erreurs = 0 then
inv_toaster.is_kind = inv_toaster.KIND_SUCCESS
inv_toaster.is_text = "Importação concluída: [b]" + String(ll_lignes) + " linhas[/b] integradas."
else
inv_toaster.is_kind = inv_toaster.KIND_ERROR
inv_toaster.il_timeout = 0 // um erro tem de ser lido
inv_toaster.is_text = "Importação interrompida: " + String(ll_erreurs) + " erros."
end if
inv_toaster.of_show()
Boas práticas #
- Uma instância persistente por window (variável de instância criada na abertura) em vez de uma criação/destruição a cada mensagem: a ligação
ipo_receivermantém-se e os retornos chegam. - Convém chamar
of_reset()antes de cada notificação: sem isso, o título, a imagem ou os botões da anterior permanecem definidos. il_timeout = 0deve reservar-se às mensagens que exigem uma decisão (erro bloqueante, ação proposta): um toast que não desaparece sozinho acaba por incomodar.ib_screen = truedeve utilizar-se apenas para o que tem de permanecer visível quando a aplicação está em segundo plano (fim de processamento demorado, tarefa noturna).- Um toast é uma mensagem transitória: se for absolutamente necessária uma resposta antes de continuar, deve utilizar-se a messagebox, que bloqueia e devolve a escolha.
- Para um estado permanente em vez de uma notificação, é preferível a statusbar.