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.
// Variaveis locais
n_pbt_toaster lnv_toast
// Criar o notificador
lnv_toast = create n_pbt_toaster
// ... configuracao ...
// Destrui-lo no fim
destroy lnv_toast
Início rápido #
// Variaveis locais
n_pbt_toaster lnv_toast
// Criar o notificador
lnv_toast = create n_pbt_toaster
// Configurar e depois mostrar
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()
// Destrui-lo no fim
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. Os toasts fixados ao ecrã empilham-se por monitor: duas windows que mostram um cada uma já não se sobrepõem |
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. A chave pertence ao toaster: outro toaster que mostre a mesma chave abre o seu próprio toast. Uma atualização retoma também o novo canto, a fixação ao ecrã e a window de fixação. A chave regressa como as_key nos eventos ue_toast_* |
is_sound | string | SOUND_AUTO | Som de sistema do toast, reproduzido quando é pedido. SOUND_AUTO (a predefinição): um erro ou um aviso soa, uma informação ou um sucesso fica em silêncio; SOUND_ALWAYS: todos os tipos; SOUND_NEVER: silêncio |
il_max_visible | long | 0 | 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ã. Este limite é comum a todos os toasters da aplicação: prevalece o último valor definido; 0 (a predefinição) deixa-o como está — 5 enquanto ninguém o definir. Uma pilha é o mesmo canto da mesma window — ou, para um toast fixado ao ecrã ou sem ipo_owner, o mesmo canto do mesmo monitor, seja qual for a window que o mostrou |
ipo_owner | powerobject | — | O objeto visual ao qual o toast está fixado (o canto da respetiva window serve de referência). É a única ligação a fazer: os eventos do toast são desencadeados no próprio toaster. Enquanto essa window estiver minimizada, o toast espera: não é apresentado e a sua contagem decrescente não corre até a window regressar |
ipo_receiver | powerobject | — | Opcional, legado: se definido, a respetiva window recebe um pbm_custom02 em cada evento de toast (para código antigo que o tinha ligado). Deixe-o vazio — o toaster entrega os seus eventos sozinho, em si próprio |
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) |
SOUND_AUTO | "auto" | Som apenas para um erro ou um aviso (predefinição) |
SOUND_ALWAYS | "always" | Som para todos os tipos |
SOUND_NEVER | "never" | Nunca um som |
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) — um toast que espera o seu lugar (il_max_visible) também recebe o seu de imediato —, ou um valor negativo em caso de erro. Não bloqueia. -5 (e nada é apresentado) para uma definição fora dos seus limites: um is_kind, is_position ou is_sound que não é nenhuma das suas constantes, il_max_visible fora de 0 a 20, il_timeout abaixo de TIMEOUT_AUTO |
of_close ( long al_id ) → long | Fecha um toast ainda visível — ou que ainda espera o seu lugar —, designado pelo identificador devolvido por of_show. Um toast VISÍVEL fechado assim desencadeia ue_toast_dismissed, como a sua cruz; um que ainda espera nunca foi visto e não desencadeia nada. 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. O componente chama-a sozinho enquanto um toast está no ecrã: normalmente não tem de o fazer — 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). Um clique emite ue_toast_action(id, chave, ação); of_reset limpa os botões. Um rótulo pode conter qualquer carácter — uma vírgula, um sinal de igual — sem ser cortado. Devolve 0, ou -5 (nada é acrescentado) para uma chave vazia, uma chave já ocupada, uma chave que contém / ou uma barra vertical, ou um quarto botão |
of_count ( ) → long | Devolve o número de botões de ação que a notificação carrega |
of_keys_at ( long al_index ) → string | A chave do botão na posição al_index (a partir de 1), ou "" para além de qualquer das extremidades |
of_has ( string as_key ) → boolean | Foi adicionado um botão sob esta chave? of_add_button recusa (-5) uma chave já ocupada: perguntar antes diz porquê |
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.
// Variaveis locais
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 ...
// Fechar o toast no fim do trabalho
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.
Não tem de ligar nada: defina ipo_owner (a window à qual o toast está ancorado) e trate os eventos. O componente recolhe-os enquanto um toast está no ecrã e dispara-os no objeto — sem recetor, sem temporizador.
1. Definir ipo_owner na window à qual o toast está ancorado:
// Ancorar os toasts a esta janela
inv_toaster.ipo_owner = this // a window a qual o toast esta ancorado
2. Tratar os eventos desencadeados no toaster:
| Evento | Acionado quando |
|---|---|
ue_toast_clicked (long al_id, string as_key) | O corpo do toast é clicado (não um botão). al_id é o identificador devolvido por of_show, as_key o is_key do toast (vazio sem chave) |
ue_toast_action (long al_id, string as_key, string as_action) | Um botão de ação é clicado; as_action contém a chave passada a of_add_button. al_id é o identificador devolvido por of_show, as_key o is_key do toast (vazio sem chave) |
ue_toast_dismissed (long al_id, string as_key) | O toast fecha-se: prazo esgotado, cruz de fecho, ou of_close enquanto está visível (um toast que ainda espera não desencadeia nada). Um clique no corpo desencadeia ue_toast_clicked, um botão ue_toast_action. al_id é o identificador devolvido por of_show, as_key o is_key do toast (vazio sem chave) |
Se não espera qualquer retorno — nem botão de ação, nem clique no corpo — não tem nenhum destes eventos para tratar: a notificação aparece e desaparece sozinha. É o modo mais simples, perfeito para uma simples confirmação.
Exemplos #
Os quatro níveis #
// Info : uma mensagem neutra
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_INFO
inv_toaster.is_text = "Operação concluída."
inv_toaster.of_show()
// Sucesso : esta feito
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()
// Aviso : merece atencao
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()
// Erro : falhou
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 #
// Partir das definicoes por omissao
inv_toaster.of_reset()
// Um titulo, um texto e uma imagem
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 : ancorar o toaster de uma vez por todas ; os retornos chegam sozinhos
inv_toaster.ipo_owner = this
// Propor duas acoes ; timeout 0 = o toast aguarda a decisao do utilizador
inv_toaster.of_reset()
// Titulo, texto e dois botoes, depois mostrar
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(/*key*/ "installer", /*label*/ "Instalar")
inv_toaster.of_add_button(/*key*/ "later", /*label*/ "Mais tarde")
inv_toaster.of_show()
// event ue_toast_action de inv_toaster : (long al_id, string as_key, string as_action)
choose case as_action
case "installer" ; of_start_update()
case "later" ; of_reporter(1)
end choose
Reagir ao clique na mensagem #
// event ue_toast_clicked de inv_toaster : (long al_id, string as_key)
// 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()
// O tipo e o texto seguem o resultado
if ll_errors = 0 then
inv_toaster.is_kind = inv_toaster.KIND_SUCCESS
inv_toaster.is_text = "Importação concluída: [b]" + String(ll_rows) + " 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_errors) + " erros."
end if
// Mostrar o toast
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 ancoragem
ipo_ownermantém-se e os retornos chegam. Um toaster destruído já não recebe nada: os seus toasts ficam no ecrã, mudos. - 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.