PBToolboxAI v4 ← Site

tab — u_pbt_tab #

← Referência dos componentes · Índice do guia

Separadores modernos que alojam controlos reais do PowerBuilder: faixa reposicionável, ícones por separador, separadores que se podem fechar, reordenação com o rato.

▶ Ver ao vivo — Aplicação de demonstração, mosaico Tab: a pré-visualização, o código que o produz e esta página, lado a lado.


Em resumo #

Userobjectu_pbt_tab
Classe de itemsn_pbt_tab_page (uma página = um separador)
Serve paraSubstituir um tab do PowerBuilder por uma faixa com tema, mantendo os ecrãs existentes como páginas
Opções opt-inib_reorderable

O argumento decisivo: uma página não é uma maqueta HTML, é um dragobject do PowerBuilder — um userobject, uma DataWindow, um conjunto de controlos ou até outro componente PBToolboxAI. O componente encarrega-se do posicionamento, do redimensionamento e da apresentação/ocultação na mudança de separador. Ver Alojar controlos reais do PowerBuilder.


Início rápido #

// event open da janela : cada pagina e um controlo PB ja colocado na janela
uo_tabs.of_add_page(/*key*/ "customers",  /*title*/ "Clientes",  /*page*/ uo_page_customers)
uo_tabs.of_add_page(/*key*/ "invoices", /*title*/ "Faturas", /*page*/ uo_page_invoices, /*closable*/ true)

// Um icone por separador, colocado no handle da pagina
uo_tabs.of_page(/*key*/ "customers").is_icon  = "mono:img\customers.svg"
uo_tabs.of_page(/*key*/ "invoices").is_icon = "mono:img\invoice.svg"

// Mostra o primeiro separador
uo_tabs.of_select_page(/*key*/ "customers")
// event ue_selection_changed de uo_tabs : (string as_from_key, string as_key)
of_load_page(as_key)

Propriedades #

PropriedadeTipoPredefiniçãoFunção
is_positionstring"top"Colocação da faixa: top, bottom (banda horizontal), start, end (banda vertical). Constantes POSITION_TOP, POSITION_BOTTOM, POSITION_START, POSITION_END. START/END são lógicas e acompanham o sentido de escrita
is_overflow_modestring"menu"O que faz uma banda demasiado pequena para os seus separadores. menu (predefinição) mantém cada separador legível: os que já não cabem saem da banda e o botão ··· lista-os todos, ficando o separador ativo sempre visível. compact mantém-nos todos na banda e deixa-os reduzir-se, até ao espaço que um texto truncado exige. Constantes OVERFLOW_MENU, OVERFLOW_COMPACT
ib_reorderablebooleanfalseOpt-in: o utilizador pode reordenar os separadores arrastando o respetivo cabeçalho com o rato (aciona ue_tab_reordered)
ib_veto_selectionbooleanfalsePerguntar antes de o separador ativo mudar — um gesto do utilizador (clique, teclado, atalho, lista de separadores) e of_select_page: aciona ue_selection_changing, que pode recusar; um of_select_page recusado devolve -4. Desativado por predefinição, como qualquer evento cancelável: coloque-o a true para poder recusar (trabalho não guardado). Cada pergunta de um gesto custa uma ida e volta ao PowerBuilder (~35 ms)
ib_veto_closebooleanfalsePerguntar antes de o utilizador fechar um separador (cruz, clique do meio, menu de contexto, Delete): aciona ue_tab_closing, que pode recusar. Desativado por predefinição: coloque-o a true para manter uma página com trabalho não guardado
ib_context_menubooleantrueMenu contextual integrado no cabeçalho de um separador: Fechar, Fechar os outros, Fechar à direita, Fechar todos, esbatidos quando não têm alvo. Ativo por predefinição. O clique direito seleciona primeiro o separador: se a aplicação recusar a mudança, não abre nenhum menu. Com ib_veto_close, cada fecho passa por ue_tab_closing, uma pergunta por página: a que detém trabalho não guardado recusa sozinha e permanece aberta enquanto as vizinhas partem. A false, o clique direito num separador seleciona-o e depois lança ue_tab_rclicked: abra aí o seu próprio menu
is_theme_stylestring""Estilo visual do componente (constantes THEME_STYLE_*); vazio = o da aplicação, seguido a cada mudança
is_theme_modestring""Variante clara ou escura (constantes THEME_MODE_*); vazio = a da aplicação, seguida a cada mudança
il_theme_accentlong-1Cor de destaque deste componente (-1 = destaque da aplicação, ou o do tema)
is_tooltipstring""Tooltip simples apresentado ao passar sobre o componente
is_super_tooltip_titlestring""Título do tooltip enriquecido (prevalece sobre is_tooltip)
is_super_tooltip_textstring""Texto do tooltip enriquecido (aceita marcação enriquecida)
is_super_tooltip_imagestring""Imagem do tooltip enriquecido

Propriedades de uma página — n_pbt_tab_page #

Obtidas através de of_page(id), podem ser alteradas a quente, sem reconstruir a faixa.

PropriedadeTipoPredefiniçãoFunção
is_titlestring""Etiqueta do separador. Aceita a formatação com etiquetas
is_iconstring""Ícone do separador (formas aceites: caminho, mono:, tint:, recurso de DLL). Vazio = nenhum ícone
ib_enabledbooleantruefalse desativa o separador: nenhum clique, tecla, atalho nem of_select_page o ativa, e não tem cruz de fecho. Desativar o separador ativo deixa-o ativo e a sua página utilizável: desative a própria página se for preciso (o seu código sabe se deve continuar editável)
ib_visiblebooleantruefalse oculta o separador sem eliminar a página; ocultar o separador ativo ativa o seu vizinho (o da direita, senão o da esquerda); ocultar o último separador visível oculta a página e lança ue_selection_changed com uma chave vazia
ib_closablebooleanfalseCruz de fecho neste separador. Raramente conhecido no momento em que a página é adicionada: passa a true assim que o documento que contém é guardado, e a false enquanto lá corre um processamento. Um clique do meio num separador que se pode fechar também o fecha, tal como a sua cruz
is_shortcutstring""Atalho de teclado que ativa este separador: "Ctrl+2", "Alt+F", "F6"… Responde onde quer que o utilizador esteja na janela, incluindo a página alojada — o atalho é detido pela DLL, não pela barra de separadores. Selecionar assim é um clique: ue_selection_changing é perguntado se ib_veto_selection estiver ativo, ue_selection_changed segue; um separador desativado ou oculto ignora-o. "" remove-o
is_tooltipstring""Tooltip simples apresentado ao passar sobre o item
is_super_tooltip_titlestring""Título do tooltip enriquecido do item (prevalece sobre is_tooltip)
is_super_tooltip_textstring""Texto do tooltip enriquecido do item (aceita marcação enriquecida)
is_super_tooltip_imagestring""Imagem do tooltip enriquecido do item

Métodos #

MétodoFunção
of_add_page (string as_key, string as_title, dragobject ado_page)Acrescenta um separador que não se pode fechar, sem ícone, e aloja o controlo. Devolve 0 depois de aplicado, -5 se a chave estiver vazia, contiver uma / ou uma `, já estiver ocupada, ou se a página faltar ou já estiver alojada (por este separador com outra chave, ou por outro componente): nada é acrescentado então, -2` se o componente não estiver criado
of_add_page (string as_key, string as_title, dragobject ado_page, boolean ab_closable)Idem, com cruz de fecho se ab_closable. Devolve 0 depois de aplicado, -5 se a chave estiver vazia, contiver uma / ou uma `, já estiver ocupada, ou se a página faltar ou já estiver alojada (por este separador com outra chave, ou por outro componente): nada é acrescentado então, -2` se o componente não estiver criado
of_add_page (string as_key, string as_title, dragobject ado_page, boolean ab_closable, string as_icon)Idem, com o ícone colocado de imediato (o separador surge logo completo). Devolve 0 depois de aplicado, -5 se a chave estiver vazia, contiver uma / ou uma `, já estiver ocupada, ou se a página faltar ou já estiver alojada (por este separador com outra chave, ou por outro componente): nada é acrescentado então, -2` se o componente não estiver criado
of_insert_page (string as_key, string as_title, dragobject ado_page, integer ai_index)Acrescenta a página e desloca-a depois para a posição ai_index (1 = a primeira). Devolve 0 depois de aplicado, -5 pelas mesmas recusas que of_add_page, -2 se o componente não estiver criado
of_insert_page (string as_key, string as_title, dragobject ado_page, boolean ab_closable, string as_icon, integer ai_index)Idem, dizendo o que of_add_page diz : se o separador fecha, e o seu ícone. Devolve 0 depois de aplicado, -5 pelas mesmas recusas que of_add_page, -2 se o componente não estiver criado
of_move_page (string as_key, integer ai_index)Desloca um separador existente para a posição ai_index (1 = a primeira); a página alojada e a seleção são preservadas. Devolve 0 depois de aplicado, -5 se a chave não designar nenhuma página, -2 se o componente não estiver criado
of_select_page (string as_key)Ativa um separador, como um clique nele: com ib_veto_selection ativo, ue_selection_changing é perguntado primeiro; depois segue ue_selection_changed, como num clique (logo após o seu script, a partir da fila de eventos), e of_selected_key() relido logo a seguir já devolve a nova chave. Separador já ativo: nada é perguntado nem lançado. Devolve 0 depois de aplicado (ou se já ativo), -4 se o seu ue_selection_changing recusou (nada se move), -5 se a chave não designar nenhuma página ou se a página não puder ser mostrada (oculta, desativada, além do limite da demonstração) — incluindo quando depois nenhuma página fica ativa, -2 se o componente não estiver criado
of_remove_page (string as_key)Retira o separador e devolve o controlo à sua janela de origem, oculto. O controlo continua utilizável e pode ser alojado noutro local. Não lança ue_tab_closed: foi o seu código que o fez. Se era a página ativa, a sua vizinha passa a ativa. Devolve 0 depois de aplicado, -5 se a chave não designar nenhuma página, -2 se o componente não estiver criado
of_selected_key ( )Identificador do separador ativo, "" se não existir nenhum
of_get_layout ( )Relê a disposição atual em JSON: a ordem dos separadores e a visibilidade de cada um. Guarde-a (ficheiro, base de dados, registo) e devolva-a com of_set_layout no arranque seguinte. O mesmo par tem os mesmos nomes em todos os componentes reorganizáveis
of_set_layout (string as_layout_json)Repõe uma disposição lida com of_get_layout ou recebida com ue_layout_changed. O que a disposição não nomeia mantém o seu lugar no fim: uma disposição de ontem não deve fazer desaparecer o que foi acrescentado desde então. Aplicá-la não gera qualquer event de disposição — foi você que a forneceu; se ocultar o separador ativo, o seu vizinho passa a ativo e ue_selection_changed di-lo. Devolve 0 depois de aplicado, -5 se o texto estiver vazio ou não for JSON válido, -2 se o componente não estiver criado
of_page (string as_key)Handle n_pbt_tab_page da página (criado no primeiro acesso)
of_refresh_page (string as_key)Atualiza a representação de uma página construída fora do ecrã, sem cintilação. Devolve 0, -5 se a chave não designar nenhuma página, -2 se o componente não estiver criado
of_relayout ( )Volta a publicar a zona de página para que o controlo alojado seja reposicionado (útil após uma apresentação diferida). Devolve 0 depois de aplicado, -2 se o componente não estiver criado
of_preload_icons (string as_icons[])Pré-aquece um lote de ícones no arranque: um separador aberto mais tarde apresenta o seu ícone de imediato. Devolve 0 depois de aplicado, -2 se o componente não estiver criado
of_reset ( )Esvazia a faixa: cada página alojada é devolvida à sua janela de origem e o componente regressa ao estado inicial. Devolve 0 depois de aplicado, -2 se o componente não estiver criado
of_set_redraw (boolean)Agrupa uma rajada de alterações numa única representação. Devolve 0 depois de aplicado, -2 se o componente não estiver criado
of_save_as_png (string) · of_save_as_jpg (string)Exporta a representação como imagem. Devolve 0 depois de a imagem ser escrita, -4 se a escrita falhar, -2 se o componente não estiver criado

of_add_page devolve um código negativo se o identificador estiver vazio, já estiver a ser utilizado ou se o controlo indicado não for válido ou já estiver alojado.

Quando há demasiados separadores — reduzem-se para caber na banda, mas nunca abaixo de uma largura legível: o ícone e a cruz de fecho ocupam o seu espaço para além do título, nunca no lugar dele. Os que já não cabem saem da banda, e na sua extremidade aparece um botão ···: abre a lista de todos os separadores visíveis, com o ativo assinalado, e a escolha passa para ele. O separador ativo permanece sempre visível. A banda não desliza — esse botão é o caminho para os separadores fora do enquadramento. Nada a programar, o comportamento é automático.

Teclado e rato — Ctrl+Tab e Ctrl+Page Down passam ao separador seguinte, Ctrl+Shift+Tab e Ctrl+Page Up ao anterior: só contam os separadores que podem ficar ativos (os ocultos e os desativados são saltados), e o percurso recomeça do início. Estas teclas respondem quando o teclado está na banda de separadores ou numa página que ela aloja — um controlo PowerBuilder da página tal como outro componente colocado nela; a partir de um controlo fora do tab, ficam para a janela. É um gesto do utilizador: ue_selection_changing é colocado se ib_veto_selection estiver ativo, e depois segue-se ue_selection_changed. Um clique do meio num separador que se pode fechar fecha-o, exatamente como a sua cruz: a mesma pergunta ue_tab_closing se ib_veto_close estiver ativo, e depois ue_tab_closed; num separador desativado ou que não se pode fechar, não faz nada. Nada a programar.


Eventos #

EventoAcionado quando
ue_selection_changed (string as_from_key, string as_key)O separador ativo mudou, por um gesto (um clique, o teclado, incluindo Ctrl+Tab, um atalho, a lista de separadores), por of_select_page (uma ordem do seu código também o lança, como SelectTab lança SelectionChanged) ou porque um separador sai (fechado, retirado, oculto). Mesmos argumentos que ue_selection_changing: a pergunta e o seu resultado leem-se da mesma forma, e as_from_key é a página abandonada — mesmo quando já não existe. Um as_key vazio significa que nenhum separador pode ser mostrado: todas as páginas estão ocultas
ue_tab_closed (string as_key)O utilizador fechou um separador: a sua cruz, um clique do meio sobre ele, o menu de contexto ou a tecla Delete. O separador já foi retirado e a página devolvida à sua janela. of_remove_page nunca o lança: foi o seu código que o fez
ue_tab_reordered (string as_key, integer ai_index)O utilizador terminou de arrastar um cabeçalho. ai_index é a nova posição, a partir de 1, como of_move_page
ue_layout_changed (string as_layout_json)A disposição a guardar mudou: o utilizador arrastou um cabeçalho, ou o seu código deslocou um separador (of_move_page, of_insert_page) ou ocultou / voltou a mostrar um (ib_visible). of_set_layout não o lança (essa disposição foi você que a forneceu), nem acrescentar, fechar ou retirar um separador — a ordem dos outros não muda. Transporta a disposição inteira, não apenas o que se moveu: guardá-la é uma única atribuição
ue_selection_changing (string as_from_key, string as_key) → booleanCancelável, colocado antes de o separador ativo mudar — um gesto do utilizador ou of_select_page —, quando ib_veto_selection está a true (desativado por predefinição). Devolva false para ficar na página: nada se move, e of_select_page devolve -4
ue_tab_closing (string as_key) → booleanCancelável, colocado antes de o utilizador fechar um separador, quando ib_veto_close está a true (desativado por predefinição). Nomeado para fazer par com ue_tab_closed: closing / closed. Devolva false para manter o separador (e a página que aloja) aberto
ue_tab_rclicked (string as_key)Clique direito no cabeçalho de um separador quando ib_context_menu está a false: o separador é primeiro selecionado (através de ue_selection_changing se estiver armado — uma seleção recusada não lança nada), e depois este event dá a sua chave. Abra aqui o seu próprio menu: PopMenu(PointerX(), PointerY()) da sua janela. Um separador desativado não lança nada; um único event por clique direito
ue_ready ( )O componente terminou o carregamento; tudo o que foi enviado antes foi reproduzido
ue_runtime_missing ( )O runtime WebView2 está ausente: o componente permanece vazio
ue_bg_color (long al_color)O componente calculou a cor de fundo do respetivo tema; o userobject já a adotou (backcolor)

Exemplos #

Um dossiê de páginas de negócio #

// event open : os userobjects de pagina ja estao colocados na janela
uo_tabs.of_set_redraw(/*on*/ false)

// Um separador por userobject de pagina
uo_tabs.of_add_page(/*key*/ "identity", /*title*/ "Identidade",  /*page*/ uo_identity)
uo_tabs.of_add_page(/*key*/ "addresses", /*title*/ "Moradas",  /*page*/ uo_addresses)
uo_tabs.of_add_page(/*key*/ "accounting",   /*title*/ "Contabilidade", /*page*/ uo_accounting)

// Um icone por separador, colocado no handle da pagina
uo_tabs.of_page(/*key*/ "identity").is_icon = "mono:img\user.svg"
uo_tabs.of_page(/*key*/ "addresses").is_icon = "mono:img\map.svg"
uo_tabs.of_page(/*key*/ "accounting").is_icon   = "mono:img\euro.svg"

// Uma so renderizacao para tudo e depois mostra-se o primeiro separador
uo_tabs.of_set_redraw(/*on*/ true)
uo_tabs.of_select_page(/*key*/ "identity")

Documentos que se podem fechar, abertos a pedido #

// Abrir um documento num novo separador que se pode fechar
uo_tabs.of_add_page(/*key*/ ls_key, /*title*/ ls_label, /*page*/ uo_editor, /*closable*/ true, /*icon*/ "mono:img\doc.svg")
uo_tabs.of_select_page(/*key*/ ls_key)
// event ue_tab_closed de uo_tabs : (string as_key)
// O separador ja foi retirado ; falta libertar os dados de negocio.
of_free_document(as_key)

Reordenação com o rato #

// The user may drag a tab to a new place
uo_tabs.ib_reorderable = true
// event ue_tab_reordered de uo_tabs : (string as_key, integer ai_index)
// ai_index = nova posicao, a partir de 1 (como of_move_page) : memoriza-se a ordem escolhida.
of_save_order(as_key, ai_index)

Faixa vertical #

// Banda de separadores do lado esquerdo, util quando as etiquetas sao longas
uo_tabs.is_position = uo_tabs.POSITION_START

Inativar ou ocultar um separador consoante os direitos #

// O caminho passa sempre pelo handle da pagina
uo_tabs.of_page(/*key*/ "accounting").ib_enabled = of_is_allowed("accounting")
uo_tabs.of_page(/*key*/ "audit").ib_visible  = gb_expert_mode

Reagir à seleção #

// event ue_selection_changed de uo_tabs : (string as_from_key, string as_key)
choose case as_key
    case "identity" ; uo_identity.of_refresh()
    case "addresses" ; uo_addresses.of_refresh()
    case "accounting"   ; uo_accounting.of_refresh()
end choose

Recusar uma mudança de separador ou um fecho #

// As duas perguntas tem de ser ATIVADAS: sem estas linhas o componente nao
// pergunta nada e muda de pagina ou fecha de imediato.
uo_tabs.ib_veto_selection = true
uo_tabs.ib_veto_close     = true
// event ue_selection_changing de uo_tabs : (string as_from_key, string as_key)
// Devolver FALSE mantem o utilizador na pagina que abandona.
if of_page_modified(as_from_key) then
    if MessageBox("Modificações", "Sair sem guardar?", Question!, YesNo!) = 2 then
        return false
    end if
end if
return true
// event ue_tab_closing de uo_tabs : (string as_key)
// Devolver FALSE mantem o separador e a pagina que aloja abertos.
return not of_page_modified(as_key)

Recomeçar com uma faixa vazia #

// of_reset devolve CADA pagina alojada a sua janela de origem antes de esvaziar
uo_tabs.of_reset()
uo_tabs.of_add_page(/*key*/ "home", /*title*/ "Início", /*page*/ uo_home)

Boas práticas #

Herdado da base comum #

Estes membros existem em todos os componentes visuais — não são próprios deste. São detalhados uma só vez, nos capítulos transversais; esta tabela apenas diz onde os ler.

MembrosFunçãoDetalhado em
of_count · of_keys_at · of_hasPercorrer o que o componente contém3.2 Os items
of_resetRepor o componente a zero3.6 Repor um componente a zero: of_reset()
of_register_shortcut · of_clear_shortcutsAtalhos de teclado do componente3.5 Os atalhos de teclado
of_is_created · of_is_ready · of_get_last_errorSe nasceu, se está pronto, o que falhou3.7 Diagnóstico
of_save_as_png · of_save_as_jpgExportar a renderização como imagem3.8 Exportar a representação como imagem
of_set_redrawAgrupar as alterações num único repinte3.10 Boas práticas
of_preload_iconsÍcones mostrados sem atrasoApresentação instantânea: of_icon
of_set_translationTraduzir uma legenda do componente5.2 Adaptar uma etiqueta: of_set_translation
of_focus_webviewDar o foco ao componente6.4 Teclado e focus
of_print · of_print_to_pdfImprimir, ou escrever um PDF6.9 Imprimir
of_set_property · of_get_property · of_component_nameControlar uma propriedade pelo nome3.1 O motor de propriedades

Duas ajudas não são herdadas: of_icon e of_escape_markup vivem em n_pbt_utils. Declare um — n_pbt_utils lnv_utils, nada a criar — e chame-as nele.


← Referência dos componentes · Índice do guia