PBToolboxAI v1 ← Site

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 #

Objeton_pbt_toasternão visual: nada a colocar na window
Serve paraConfirmar uma ação bem-sucedida, assinalar um aviso ou um erro, sem parar o trabalho em curso
RetornoNã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.

PropriedadeTipoPredefiniçãoFunção
is_textstring""Corpo da mensagem. Aceita o texto formatado com etiquetas
is_kindstringKIND_INFONível: comanda o ícone e a cor do friso. Constantes KIND_*
is_positionstringPOSITION_BOTTOM_RIGHTCanto de fixação. Constantes POSITION_*
ib_screenbooleanfalsefalse = fixado ao canto da window; true = fixado ao canto do ecrã, flutuando por cima de tudo
il_timeoutlongTIMEOUT_AUTOTempo 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_titlestring""Linha de título a negrito por cima da mensagem (toast enriquecido)
is_imagestring""Imagem de ilustração à esquerda, em vez do ícone de nível (formas aceites: caminho, mono:, recurso de DLL)
is_keystring""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_visiblelong5Nú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_ownerpowerobjectO objeto visual ao qual o toast está fixado (o canto da respetiva window serve de referência)
ipo_receiverpowerobjectO objeto visual que recebe os eventos do toast. Deve deixar-se vazio para uma notificação sem retorno

Constantes #

ConstanteValorUtilizaçã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/RIGHT aqui e START/END noutros 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étodoFunção
of_show ( ) → longApresenta 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 ) → longFecha 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 }) → longAcrescenta 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_receiver tem 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:

EventoAcionado 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 #


← Referência dos componentes · Índice do guia