PBToolboxAI v5 ← Site

treeview — u_pbt_treeview #

← Referência dos componentes · Índice do guia

treeview mostra dados em árvore: nós que contêm outros, abertos e fechados pelo seu chevron, com uma imagem, um emblema, uma caixa de três estados e uma seleção simples ou múltipla. Assim que lhe é acrescentada uma coluna, torna-se uma lista em árvore (TreeList): a primeira coluna tem a árvore, as outras mostram os campos de cada nó, ordenáveis com um clique no seu cabeçalho. Um ramo pode prometer filhos que só lê ao abrir; o utilizador renomeia um nó (F2) e arrasta-o para outro lado, podendo a sua aplicação recusar antes; uma pesquisa só deixa o que corresponde. A árvore preenche-se à mão ou a partir de um DataStore hierárquico (uma linha nomeia o seu pai), e pode reescrever nele o que o utilizador muda.

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


Em resumo #

Userobjectu_pbt_treeview
Classes de itensn_pbt_treeview_node (of_node(keys)), n_pbt_treeview_column (of_column(key))
Serve paraUma árvore de pastas, um organigrama, categorias de produtos, direitos a marcar, uma lista de materiais com as suas quantidades
PrincípioUm nó tem uma chave única sob o seu pai; o seu endereço junta as chaves dos seus níveis com / ("europe/france")
Opções opt-inib_checkboxes, ib_editable, ib_drag_drop, ib_veto_changes, ib_veto_selection, ib_veto_toggle, ib_single_expand, ib_parents_first, ib_toolbar, ib_show_lines, ib_write_back, ib_allow_drop
Limite no modo de demonstraçãoOs 8 primeiros nós de cada nível desenhados, sob cada pai, pela ordem do modelo, e 200 nós em toda a árvore, os primeiros acrescentados (um nó escondido conta, lotes e grupos incluídos; um total nunca conta o que o limite esconde) — ver o modo de demonstração

Início rápido #

// Two levels : a continent, then its countries (the parent is added first)
uo_tree.of_add_node(/*keys*/ "europe", /*text*/ "Europe")
uo_tree.of_add_node(/*keys*/ "europe/france", /*text*/ "France")
uo_tree.of_add_node(/*keys*/ "europe/italy", /*text*/ "Italy")

// Open the continent : its countries show
uo_tree.of_node(/*keys*/ "europe").ib_expanded = true
// event ue_node_opened of uo_tree : (string as_keys)
// A double click or Enter on a node : your own window shows it
OpenWithParm(w_country, as_keys)

Um endereço por nó #

Um nó é designado pelo seu endereço: as chaves dos seus níveis juntas por /. "europe" está no topo, "europe/france" dentro de "europe" — o pai é acrescentado primeiro. Uma chave é única sob o seu pai: "europe/paris" e "usa/paris" são dois nós. Um endereço já ocupado, um pai desconhecido, um nível vazio, uma chave que contém | ou começa por __: o acréscimo devolve -5 e of_get_last_error diz porquê. of_insert_node coloca um nó entre os seus irmãos (posição contada a partir de 1), of_move_node desloca-o com a sua subárvore para outro pai ("" = o topo): o seu endereço muda, e os handles obtidos no endereço antigo são libertados de imediato (um handle obtido depois no novo continua válido). Para percorrer a árvore: of_count() e of_keys_at(n) para o primeiro nível, of_count(endereço) e of_keys_at(endereço, n) para os filhos de um nó — que devolve o endereço completo, reutilizável tal como está.

// Local variables
long ll_i

// Paris first among the cities of France, then Italy moved under a new region
uo_tree.of_add_node(/*keys*/ "europe/france/lyon", /*text*/ "Lyon")
uo_tree.of_insert_node(/*keys*/ "europe/france/paris", /*text*/ "Paris", /*image*/ "", /*position*/ 1)
uo_tree.of_add_node(/*keys*/ "south", /*text*/ "Southern Europe")
uo_tree.of_move_node(/*keys*/ "europe/italy", /*to_parent_keys*/ "south", /*position*/ 1)

// The children of France, by their whole address
for ll_i = 1 to uo_tree.of_count(/*keys*/ "europe/france")
    lb_cities.AddItem(uo_tree.of_keys_at(/*keys*/ "europe/france", /*index*/ ll_i))
next

Abrir, selecionar, marcar #

Um nó abre-se pelo seu chevron, um duplo clique, o teclado ou o seu código (ib_expanded do seu handle, of_expand_all, of_collapse_all, of_expand_to_level, of_scroll_to_node, o que of_select_node abre; of_clear_children fecha): cada um levanta ue_node_toggled, depois ue_layout_changed. A seleção segue is_selection_mode: um nó (SELECT_SINGLE, o predefinido), vários com Ctrl e Shift como no Explorador (SELECT_MULTIPLE), ou nenhum (SELECT_NONE: o teclado só move um foco). of_select_node seleciona um nó sozinho, abre o que o contém e trá-lo para o ecrã — uma árvore abre para selecionar, como o TreeView do Windows, mas julga primeiro: um nó escondido ou contido num escondido, além do limite de demonstração ou afastado pela pesquisa é recusado (-5, of_get_last_error diz porquê) e nada se abre. ue_selection_changed recebe os endereços selecionados num array JSON — quer a tenha mudado um clique, o teclado ou o seu código, quer um nó selecionado tenha saído do ecrã (ramo fechado, nó retirado ou escondido, nó ocultado pela pesquisa). Fechar um ramo traz o foco de volta para ele. Com ib_checkboxes, cada nó tem uma caixa; com ib_check_cascade (o predefinido), uma marca do utilizador num pai marca a sua subárvore exceto um nó desativado e a sua subárvore, que ficam como estão (o pai fica então misto); uma marca do seu código marca tudo. Durante uma pesquisa, a cascata abrange toda a subárvore, nós ocultados incluídos. Sob a cascata, um pai é o estado dos filhos que a árvore pode desenhar (nem escondidos nem, em modo de demonstração, além do limite): marcado quando todos o estão, misto quando uma parte o está. Uma marca posta pelo utilizador levanta ue_node_checked; uma marca posta pelo seu código (ib_checked, of_check_all) é um valor, mudo como SetItem. Os filhos recebidos sob uma folha marcada recebem a sua marca — todos, toda a resposta a ue_children_needed — até que uma marca (gesto ou código) ou um nó deslocado para dentro lhe ponha fim. Uma marca do utilizador nunca toca num nó além do limite de demonstração, nem, com ib_write_back, num nó escondido. of_select_nodes(as_keys_json) seleciona vários nós de uma vez em SELECT_MULTIPLE — o par de of_selected_keys — com uma só pergunta aos vetos e um só ue_selection_changed; o foco vai para o último endereço nomeado.

// Local variables
n_pbt_json lnv_json
string ls_keys[]
long ll_i

// A box before each node : checking a parent checks its subtree
uo_tree.ib_checkboxes = true
uo_tree.of_node(/*keys*/ "europe/france").ib_checked = true

// Every checked node, in the order of the tree
lnv_json.of_load(/*json*/ uo_tree.of_checked_keys())
for ll_i = 1 to lnv_json.of_get_array(/*path*/ "", /*values*/ ls_keys)
    lb_chosen.AddItem(ls_keys[ll_i])
next

Perguntar primeiro: seleção e abertura #

Um ecrã mestre-detalhe não deve sair de uma ficha por gravar. Com ib_veto_selection, ue_selection_changing recebe a seleção atual e a pedida (arrays JSON de endereços) antes de qualquer escolha: um clique, Ctrl ou Shift + clique, o teclado, F3, of_select_node, of_clear_selection, of_search_next ou of_search_prev. Devolva FALSE para recusar: nada se move, nem sequer o foco do teclado, e o método devolve -4; ue_node_clicked é levantado na mesma, o clique aconteceu. O que sai da seleção por consequência — um ramo fechado, um nó retirado, escondido ou ocultado pela pesquisa — não é perguntado. Da mesma forma, ib_veto_toggle pergunta ue_node_toggling antes de cada abertura ou fecho, por um gesto ou pelo código: um ib_expanded recusado não envia nada (of_get_last_error di-lo), of_expand_all, of_collapse_all e of_expand_to_level aplicam os outros nós e devolvem -4, of_select_node e of_scroll_to_node devolvem -4 sem abrir nada. of_select_node pergunta primeiro as aberturas (ue_node_toggling), depois a seleção: uma aplicação nunca age sobre uma seleção aceite para uma abertura depois recusada. O que sai da seleção por consequência não se recusa: para que um ramo fechado não saia de uma ficha por gravar, junte ib_veto_selection a ib_veto_toggle e recuse o fecho do ramo que a contém. ib_single_expand deixa um só ramo aberto sob cada pai: abrir um nó fecha os seus irmãos abertos, sem perguntar; defini-lo não fecha nada no momento.

// A record shown beside the tree : ask before the selection leaves it, and before
// a branch closes (closing the branch that holds it would leave it)
uo_tree.ib_veto_selection = true
uo_tree.ib_veto_toggle = true
// event ue_selection_changing of uo_tree : (string as_from_keys_json, string as_keys_json)
// Unsaved changes in the detail : the user decides
if dw_detail.ModifiedCount() > 0 then
    if MessageBox("Unsaved changes", "Leave this record without saving?", Question!, YesNo!) = 2 then return false
end if
return true
// event ue_node_toggling of uo_tree : (string as_keys, boolean ab_expanding)
// Closing the branch that holds an unsaved record would leave it : refused
if not ab_expanding and dw_detail.ModifiedCount() > 0 then
    if Pos(uo_tree.of_selected_key() + "/", as_keys + "/") = 1 then return false
end if
return true

Ramos carregados a pedido #

Uma árvore grande — um disco, um catálogo, uma tabela de milhares de linhas — não tem de ser lida de uma vez. ib_has_children = true num nó é uma promessa: o seu chevron aparece embora não contenha nada. Quando se abre — um clique, o teclado, o seu código, ou of_select_node a abrir o que contém um nó —, ue_children_needed é levantado: os seus of_add_node feitos durante o evento estão lá quando o ramo se abre, depois do retorno da linha que o abriu (ib_expanded = true não espera por eles). A promessa vale até essa resposta, mesmo que entretanto um nó tenha sido acrescentado ou largado lá dentro; não acrescente nada, e ela é retirada (o chevron desaparece). Voltar a pôr ib_has_children = true faz a próxima abertura voltar a perguntar. Uma abertura feita durante o evento levanta um só ue_node_toggled. of_expand_all só abre os ramos que já têm filhos: um ramo cuja promessa não teve resposta fica fechado, nenhuma pergunta é feita em massa. Para uma tabela, não é preciso chamar of_add_node linha a linha: of_from_datastore(ads, as_parent_keys) faz das linhas de um DataStore os filhos do nó, numa só mensagem — o padrão ItemPopulate → Retrieve do TreeView do PowerBuilder. ROLE_PARENT nomeia aí uma linha do mesmo lote (vazio ou desconhecido: diretamente sob o nó); o mesmo DataStore dado de novo sob o mesmo nó substitui o seu lote, outro DataStore acrescenta o seu. of_row de um nó de um lote devolve a sua linha no seu DataStore, e ib_write_back escreve lá. of_clear_children retira os filhos de um nó e fá-lo prometer de novo: a sua próxima abertura volta a perguntar (o «atualizar» de uma pasta). Dê a cada lote o seu próprio DataStore (criado quando o seu ramo abre, guardado enquanto os seus nós são mostrados): um DataStore recarregado para outro nó — Reset, Retrieve, depois of_from_datastore sob outro nó — leva as suas linhas para o novo lote, e o PowerBuilder volta a dar os mesmos RowID depois de um Reset. Os nós do lote anterior guardam então o que mostram mas já não têm linha: of_row devolve 0, uma deslocação pelo código devolve -5 ("loaded again"), um texto renomeado ou uma marca é recusado e ue_write_back_failed diz porquê, e o carregamento que o causou conta-os (stale=N) em of_get_last_error. O mesmo DataStore dado de novo sob o mesmo nó substitui o seu lote; para refrescar um lote a partir de outro objeto DataStore, chame primeiro of_clear_children, senão acrescenta-se ao lado do primeiro. Uma coluna chamada has_children (ROLE_HAS_CHILDREN) faz uma linha prometer os seus próprios filhos, sem ciclo. as_parent_keys vazio é recusado (-5): o topo da árvore é of_from_datastore(ads).

// A folder that promises children : nothing is read before it opens
uo_tree.of_add_node(/*keys*/ "docs", /*text*/ "Documents", /*image*/ "img\packimages.dll:png/folder")
uo_tree.of_node(/*keys*/ "docs").is_expanded_image = "mono:img\packimages.dll:svg/samples/folder-open"
uo_tree.of_node(/*keys*/ "docs").ib_has_children = true
// event ue_children_needed of uo_tree : (string as_keys)
// Local variables
datastore lds_folders
n_pbt_utils lnv_utils

// The folder opens : ITS sub-folders are retrieved into a DataStore of their own and
// added in ONE call - code is their key and name their text (of_map, once), the
// column has_children says whether each one promises its own
lds_folders = create datastore
lds_folders.DataObject = "d_folders"
lds_folders.SetTransObject(SQLCA)

// as_keys is the whole ADDRESS (docs/reports) : the code of the folder is its LAST key
lds_folders.Retrieve(lnv_utils.of_leaf(/*keys*/ as_keys))
uo_tree.of_from_datastore(/*ads*/ lds_folders, /*parent_keys*/ as_keys)

// One DataStore per lot, kept while its nodes are shown : of_row and ib_write_back
// read it ; the window destroys them when it closes
ids_lots[UpperBound(ids_lots) + 1] = lds_folders

Renomear e deslocar #

Com ib_editable, o utilizador renomeia um nó: F2, ou um clique no nó já selecionado (após um breve atraso, como o Explorador). Enter (ou sair do campo) guarda o texto, Esc devolve-o, um texto esvaziado é recusado (a edição é cancelada); ue_node_edited recebe o texto escrito e o antigo — um texto escrito é texto, nunca etiquetas. Uma ordem do seu código durante a edição mantém o campo e o que nele está escrito; se a linha editada sair do ecrã sem um gesto do utilizador (código, deslocamento), a edição é cancelada. Com ib_drag_drop, arrasta um nó: sobre o quarto superior de uma linha vai antes dela, sobre o quarto inferior depois — como primeiro filho se for um ramo aberto —, ao meio dentro; um ramo fechado sob o ponteiro abre-se ao fim de um momento, a árvore desloca-se perto dos seus bordos, Esc cancela, um nó nunca vai para a sua própria subárvore nem para onde a sua chave está ocupada, e nada se larga sobre a linha de um nó desativado. Um arrastar cujo botão solto a árvore não vê — a janela perde o foco (Alt+Tab, uma caixa de mensagem) — é cancelado: nada se move. Sob uma ordenação, ou com ib_parents_first, uma largada só vai dentro. ue_node_moved recebe o novo endereço, o antigo e o lugar sob o novo pai; um nó largado onde já está não pergunta, não escreve nem levanta nada. Com ib_veto_changes, ue_node_editing e ue_node_moving são perguntados antes — ue_node_moving com o lugar final, o que ue_node_moved dirá: devolva FALSE para recusar — nada muda, e of_move_node devolve -4. Arrasta-se um nó de cada vez, mesmo em seleção múltipla.

// Renaming and moving by the user, with a question before each change
uo_tree.ib_editable = true
uo_tree.ib_drag_drop = true
uo_tree.ib_veto_changes = true
// event ue_node_moving of uo_tree : (string as_keys, string as_to_parent_keys, long al_position)
// Nothing goes to the top level : FALSE keeps the node where it is
if as_to_parent_keys = "" then return false
return true

O seu código também abre um nome em edição: of_edit_node(as_keys) — o EditLabel de um TreeView PowerBuilder, para uma «Nova pasta» que se abre pronta a ser nomeada. O nó é primeiro selecionado (o que o contém abre-se), depois o campo abre-se; o fim pertence ao utilizador, como acima. Um bloqueio para o utilizador, nunca o seu código: funciona com ib_editable = false, num nó só de leitura ou desativado. of_cancel_edit() fecha o campo e devolve o texto, como Esc.

// A new folder, opened at once in edit mode : the user types its name, then Enter
uo_tree.of_add_node(/*keys*/ "docs/new", /*text*/ "New folder")
uo_tree.of_edit_node(/*keys*/ "docs/new")

Bloqueios, Delete e cópia #

Três bloqueios por nó travam o utilizador, nunca o seu código: ib_read_only (nem renomeado nem arrastado, continua a ser um destino), ib_drop_target = false (nada é largado dentro dele, nem um nó nem um ficheiro — antes ou depois dele continua permitido) e ib_show_checkbox = false (sem caixa: o nó não conta para o pai, não está em of_checked_keys, e a cascata atravessa-o para os seus filhos). Delete levanta ue_delete_requested com os nós selecionados (em SELECT_NONE, o do foco; sem seleção, caso contrário, nada é levantado), exceto os desativados e só de leitura: a árvore não retira nada, a sua aplicação chama of_remove_node para o que apaga. Ctrl+C (ou Ctrl+Insert) levanta ue_copy com os nós selecionados (em SELECT_NONE, o do foco) em texto separado por tabulações, um número bruto (um ponto, sem agrupamento nem símbolo): o texto depois de tantas tabulações quanto a sua profundidade, depois as colunas de uma lista em árvore alinhadas, primeiro uma linha de cabeçalho; a árvore tenta também a área de transferência do navegador, que pode ser recusada à página — ClipBoard(as_tsv) para ter a certeza.

// The system folder : neither renamed nor dragged, nothing dropped into it, no check box
uo_tree.of_node(/*keys*/ "system").ib_read_only = true
uo_tree.of_node(/*keys*/ "system").ib_drop_target = false
uo_tree.of_node(/*keys*/ "system").ib_show_checkbox = false
// event ue_delete_requested of uo_tree : (string as_keys_json)
// Local variables
n_pbt_json lnv_json
string ls_keys[]
long ll_i

// Delete pressed : the tree removes nothing, your application decides
lnv_json.of_load(/*json*/ as_keys_json)
for ll_i = 1 to lnv_json.of_get_array(/*path*/ "", /*values*/ ls_keys)
    uo_tree.of_remove_node(/*keys*/ ls_keys[ll_i])
next
// event ue_copy of uo_tree : (string as_tsv)
// Ctrl+C : the nodes copied, ready for a spreadsheet
ClipBoard(as_tsv)

Ficheiros largados a partir do Explorador #

Com ib_allow_drop, a árvore aceita ficheiros arrastados a partir do Explorador do Windows sobre um nó: o nó sob o cursor acende-se durante o arrastar, ue_drop_files recebe o seu endereço e os caminhos completos. as_keys fica vazio para uma largada ao lado dos nós, sobre um nó desativado ou sobre um nó cujo ib_drop_target vale false. ue_drag_enter e ue_drag_leave dizem que um arrastar de ficheiros entrou e depois saiu sem largar nada.

// Files of the Explorer dropped on a folder of the tree
uo_tree.ib_allow_drop = true
// event ue_drop_files of uo_tree : (string as_keys, string as_files[])
// The folder under the cursor : your application copies the files there
if as_keys <> "" then wf_copy_files(as_files, uo_tree.of_get_field(/*keys*/ as_keys, /*field*/ "path"))

Colunas, ordenação e disposição #

of_add_column faz da árvore uma lista em árvore: a primeira coluna tem a árvore (o seu título é is_tree_title), cada coluna acrescentada mostra o campo com a mesma chave de cada nó — definido por of_set_field, ou uma coluna do DataStore. O handle de uma coluna (of_column) regula o seu título, a sua largura (0 = automática), o seu alinhamento, o seu formato (uma máscara numérica como "#,##0.00" com os separadores da língua de apresentação, ou tokens de data para um valor "yyyy-mm-dd", os do datagrid), a sua visibilidade e o seu lugar. Um clique num cabeçalho ordena os irmãos de cada nível — crescente, decrescente, depois a ordem de acréscimo — e levanta ue_sort_changed; of_sort faz o mesmo a partir do código. A ordenação só muda a ordem mostrada: of_keys_at e as posições mantêm a ordem de acréscimo. O utilizador alarga uma coluna pelo bordo do seu cabeçalho e desloca-a arrastando o cabeçalho. O que dispôs — larguras, ordem, visibilidade, ordenação, nós abertos — lê-se por of_get_layout e devolve-se por of_set_layout; ue_layout_changed leva a disposição inteira depois de cada gesto que a muda, e quando o seu código escreve a largura, o lugar ou a visibilidade de uma coluna (ii_width, ii_index, ib_visible) e a disposição muda. Valores iguais mantêm a ordem do modelo, e a ordenação é refeita quando a língua de apresentação muda. Retirar a coluna ordenada (of_remove_column, of_clear_columns) levanta ue_sort_changed com a chave seguinte da ordenação — SORT_NONE quando era a única —, depois ue_layout_changed. As cinco cores do handle de uma coluna (il_accent, il_back_color, il_text_color, il_back_color_hover, il_text_color_hover) colorem o seu cabeçalho. Assim que há colunas, a coluna da árvore fica fixa no deslocamento horizontal. A ordenação pode ter várias chaves: of_sort(as_sort) lê a sintaxe do SetSort de um DataWindow («type A, text D», sendo «text» o texto dos nós), of_sort(as_column, as_dir) aceita também um campo que nenhuma coluna mostra, e ue_sort_changed recebe a ordenação inteira como terceiro argumento. ib_parents_first põe em cada nível os nós que têm (ou prometem) filhos antes das folhas — as pastas antes dos ficheiros — seja qual for a ordenação. Uma coluna não pode ter a chave text, que designa o texto dos nós (-5): of_sort("text", as_dir) ordena por ele, e of_sort aceita vários espaços entre uma coluna e o seu sentido, como SetSort.

// A tree list : the population of each country beside the tree
uo_tree.is_tree_title = "Country"
uo_tree.of_add_column(/*key*/ "population", /*title*/ "Population", /*width*/ 120)
uo_tree.of_column(/*key*/ "population").is_format = "#,##0"
uo_tree.of_column(/*key*/ "population").is_align = u_pbt_treeview.ALIGN_END
uo_tree.of_set_field(/*keys*/ "europe/france", /*field*/ "population", /*value*/ "68000000")

// The largest countries first, inside each continent
uo_tree.of_sort(/*column*/ "population", /*dir*/ u_pbt_treeview.SORT_DESC)
// The folders first, then by type and by name
uo_tree.ib_parents_first = true
uo_tree.of_sort(/*sort*/ "type A, text A")

Exportar a árvore com a sua hierarquia: of_export_csv(as_path) escreve um CSV (UTF-8, ponto e vírgula) em que o texto de um nó fica na célula do seu nível — uma célula mais à direita por nível —, as colunas de uma lista em árvore depois do nível mais profundo, primeiro uma linha de cabeçalho; of_export_xlsx(as_path) escreve um livro Excel em que o texto fica recuado pelo seu nível e cada ramo agrupado sob o seu pai, dobrável no Excel, e os números continuam números. is_export_scope diz quais nós: EXPORT_ALL (o predefinido) todos os nós, ramos fechados incluídos, EXPORT_SHOWN as linhas no ecrã. A árvore constrói o ficheiro, a DLL escreve-o, ue_csv_saved / ue_xlsx_saved confirmam; recusado no modo de demonstração.

// The tree written to Excel - every node, the closed branches too ; ue_xlsx_saved confirms
uo_tree.is_export_scope = u_pbt_treeview.EXPORT_ALL
uo_tree.of_export_xlsx(/*path*/ "C:\exports\countries.xlsx")

Totais por ramo #

Uma coluna de uma lista em árvore pode mostrar, em cada ramo, o total do que contém: is_summary no seu handle vale SUMMARY_SUM, SUMMARY_AVG, SUMMARY_MIN, SUMMARY_MAX ou SUMMARY_COUNT (os valores não vazios). O cálculo desce até às folhas — uma média é a das folhas, nunca uma média de médias — e o total escreve-se a negrito, por is_format — uma contagem sempre como número simples. Um ramo que tem um valor próprio guarda-o e fá-lo subir, exceto com ib_summary_over_value na coluna. Só contam os nós que a árvore pode desenhar (nunca um escondido); com ib_summary_filtered, no componente, só o que a pesquisa mostra. of_get_field devolve o total bruto (um número com ponto), uma ordenação por esta coluna usa os totais, e os totais seguem cada adição, remoção ou arrastar. SUMMARY_MIN e SUMMARY_MAX comparam também datas (yyyy-mm-dd, yyyy-mm-dd hh:mm:ss, hh:mm:ss), e uma soma de inteiros continua exata além de 2^53.

// Each continent shows the sum of its countries, in bold
uo_tree.of_column(/*key*/ "population").is_summary = u_pbt_treeview.SUMMARY_SUM

// The total of Europe, read like a field
st_total.text = uo_tree.of_get_field(/*keys*/ "europe", /*field*/ "population")

Pesquisar #

is_filter só mostra os nós cujo texto contém a pesquisa (maiúsculas ignoradas), com os nós que os contêm, abertos, e o texto encontrado realçado. "" mostra tudo. O que contém uma correspondência aparece aberto sem mudar ib_expanded, e os chevrons ficam inertes enquanto dura a pesquisa. Com ib_toolbar, uma barra por cima da árvore tem um campo de pesquisa (que escreve is_filter: uma leitura devolve-o de imediato), e os botões Expandir tudo e Recolher tudo. Esc no campo esvazia a pesquisa, Seta para baixo passa para a árvore, Enter e F3 vão para a correspondência seguinte (Shift: para a anterior) e o campo mantém o teclado. Um nó selecionado que a pesquisa oculta sai da seleção, e ue_selection_changed di-lo; o nó que o contém não é selecionado no seu lugar. of_select_node e of_scroll_to_node recusam um nó que a pesquisa afasta (-5). Para ir de correspondência em correspondência, of_search_next e of_search_prev selecionam a seguinte ou a anterior depois do nó do foco, em ciclo (F3 e Shift+F3 no teclado), e of_match_count diz quantas a pesquisa encontrou. of_find_node(as_field, as_value, as_after_keys) encontra sem filtrar: o endereço do primeiro nó cujo campo ("" = o seu texto) vale exatamente o valor, pela ordem que a árvore mostra, ramos fechados incluídos; volte a dar o endereço encontrado para o seguinte. Em SELECT_NONE, of_search_next e of_search_prev movem para lá o foco, como F3. of_find_node parte depois do lugar de as_after_keys na ordem mostrada — também um nó escondido; um desconhecido devolve "" e of_get_last_error di-lo. of_find_nodes(as_field, as_value) devolve todas as correspondências de uma vez, como array JSON na ordem mostrada.

A pesquisa ignora os acentos por predefinição, como a ordenação: «montreal» encontra «Montréal», e o I com ponto do turco conta como um I («izmir» encontra «İzmir»); ib_filter_accents = true fá-los contar. Em seleção múltipla, Ctrl+A seleciona todos os nós apresentados (uma única pergunta com ib_veto_selection).

// A search field above the tree, and a first search from the code
uo_tree.ib_toolbar = true
uo_tree.is_filter = "par"
// Local variables
string ls_keys

// The first node whose code is FR, selected if there is one
ls_keys = uo_tree.of_find_node(/*field*/ "code", /*value*/ "FR", /*after_keys*/ "")
if ls_keys <> "" then uo_tree.of_select_node(/*keys*/ ls_keys)
// Every node whose status is late, selected at once (a multiple selection)
uo_tree.is_selection_mode = u_pbt_treeview.SELECT_MULTIPLE
uo_tree.of_select_nodes(/*keys_json*/ uo_tree.of_find_nodes(/*field*/ "status", /*value*/ "late"))

A partir de um DataStore #

of_from_datastore faz um nó de cada linha de uma tabela hierárquica: a coluna ROLE_KEY dá a sua chave (sem ela, o RowID da linha), a coluna ROLE_PARENT nomeia a chave do nó que o contém (vazia, desconhecida, ou um ciclo: no topo) — com uma coluna ROLE_KEY, um valor de pai nomeia uma chave, nunca um RowID. Os outros papéis: o texto (ROLE_TEXT, mostrado como texto, nunca como etiquetas), a imagem, a marca, o emblema e a abertura ao carregar. Uma coluna desempenha um papel quando se chama como ele (key, parent, text…) ou quando of_map o diz. Cada coluna é um campo (of_get_field) — as colunas da lista não são criadas automaticamente: of_add_column com o nome da coluna. Datas e números são lidos sejam quais forem as definições regionais, numa só forma: uma data yyyy-mm-dd, uma data-hora yyyy-mm-dd hh:mm:ss, um número com ponto e sem zeros inúteis (1234,50 passa a 1234.5) — uma coluna decimal é formatada e ordenada como um número. Duas linhas com a mesma chave: a segunda recebe "chave~RowID". O que o carregamento teve de corrigir (linhas cujo pai não está lá, ciclos quebrados, chaves duplicadas, chaves impossíveis) é dito por of_get_last_error, o retorno continuando 0. of_reload_row relê uma linha mudada pelo seu código e atualiza o seu nó no lugar; uma linha cuja chave ou pai mudou desloca o seu nó. O nó de uma linha retirado por of_remove_node fica fora até ao próximo of_from_datastore; of_reload_row da sua linha trá-lo de volta. Com ib_write_back, um texto renomeado é escrito na coluna ROLE_TEXT e um nó que muda de pai escreve-o na coluna ROLE_PARENT (NULL no topo, seja qual for o seu tipo; uma deslocação entre os mesmos irmãos não escreve nada), antes do evento; um nó de linha não vai então nem para debaixo de um nó acrescentado à mão nem para debaixo de uma linha sem valor de chave — a sua coluna pai não o saberia dizer. Um valor que o DataStore recusa, ou um DataStore destruído desde o carregamento (no DataStore is bound), volta a pôr o nó no lugar e levanta ue_write_back_failed. Sem ib_write_back, um arrastar só desloca o nó: a sua linha guarda o que o DataStore diz, e a releitura seguinte das linhas (of_map, is_group_by, of_reload_row, um novo carregamento) devolve o nó para onde a sua linha diz — o seu antigo handle é libertado. O Update continua a ser seu. O handle de um nó lê o número da sua linha (of_row). of_from_datastore lê também as linhas de um DataWindow ou de um DataWindowChild — o que o utilizador vê ao lado: a árvore escreve então nesse. Com ib_write_back, uma marca do utilizador escreve-se também na coluna ROLE_CHECKED de cada linha que mudou — cascata incluída, e os ramos acima cujo estado passa a marcado ou desmarcado (um ramo que fica misto guarda o seu valor) —, escrita como a coluna já a escreve (1/0, Y/N, T/F, O/N, -1/0…; uma coluna que só mostra o seu não escreve o sim habitual: Y para N, 1 para 0 — O e -1 só se a coluna já contiver um); uma coluna cujos valores não são nem um sim nem um não é recusada, com o seu motivo. Cada valor é julgado primeiro e a escrita é tudo ou nada: uma recusa devolve as marcas do gesto e levanta ue_write_back_failed. of_row_keys devolve o endereço do nó de uma linha do DataStore principal: retire o nó antes de um DeleteRow. Toda a escrita de volta é tudo ou nada — cada valor julgado antes de um ser escrito; uma data-hora guarda a sua hora, uma coluna time escreve-se, lê-se e agrupa-se em hh:mm:ss. Uma deslocação escrita por of_move_node é julgada de novo depois de ue_node_moving, e o que foi escrito é reposto se o nó não se mover. Com ib_write_back, um nó de linha cujo DataStore não tem coluna ROLE_TEXT não se renomeia. Um novo carregamento só liberta os handles do que substitui: o handle de um nó acrescentado à mão, um handle inerte ou um obtido num endereço ainda não criado continuam válidos; of_from_datastore a partir de uma DataWindow verifica que os seus dados se podem partilhar (-5 com o motivo). O que uma releitura das linhas teve de corrigir conta-se em of_get_last_error — incluindo os nós acrescentados à mão subidos ao topo porque o seu grupo já não existe (lifted=N) e os lotes que partiram com o seu nó (lots=N); of_map e is_group_by dizem-no para todas as fontes.

// The departments : each row names its parent by its id
ids_depts.Retrieve()
uo_tree.of_map(/*role*/ u_pbt_treeview.ROLE_KEY, /*column*/ "dept_id")
uo_tree.of_map(/*role*/ u_pbt_treeview.ROLE_PARENT, /*column*/ "parent_id")
uo_tree.of_map(/*role*/ u_pbt_treeview.ROLE_TEXT, /*column*/ "dept_name")
uo_tree.of_from_datastore(/*ads*/ ids_depts)

// Two columns of the DataStore shown beside the tree
uo_tree.of_add_column(/*key*/ "head_count", /*title*/ "Staff")
uo_tree.of_add_column(/*key*/ "budget", /*title*/ "Budget")
uo_tree.of_column(/*key*/ "budget").is_format = "#,##0"

// A renamed or moved department is written into its row before the event
uo_tree.ib_write_back = true
uo_tree.ib_editable = true
uo_tree.ib_drag_drop = true
// event ue_node_moved of uo_tree : (string as_keys, string as_old_keys, long al_position)
// parent_id is already written in the row : save it
if ids_depts.Update() = 1 then commit using sqlca;

Um papel resolve-se por DataStore: a coluna que of_map(ads, as_role, as_column) deu a este DataStore, senão a de of_map(as_role, as_column) quando este DataStore a tem, senão a coluna com o nome do papel. Um lote de empregados sob uma árvore de departamentos não precisa assim de nenhuma coluna dos departamentos. Uma tabela cujas raízes têm 0 na coluna pai (uma coluna NOT NULL) di-lo com is_root_parent_value = "0" ("0|-1" para dois valores): essas linhas ficam no topo sem contar como órfãs, e um nó deslocado para o topo com ib_write_back escreve 0 em vez de NULL. As colunas ROLE_STATE_IMAGE e ROLE_OVERLAY_IMAGE dão a imagem de estado e a imagem sobreposta de um nó, lidas como ROLE_IMAGE.

// event ue_children_needed of uo_tree : (string as_keys)
// Local variables
datastore lds_staff
n_pbt_utils lnv_utils

// The employees of the department that opens, in a DataStore of their own
lds_staff = create datastore
lds_staff.DataObject = "d_staff"
lds_staff.SetTransObject(SQLCA)
lds_staff.Retrieve(lnv_utils.of_leaf(/*keys*/ as_keys))

// THEIR key and THEIR text : the departments keep dept_id and dept_name
uo_tree.of_map(/*ads*/ lds_staff, /*role*/ u_pbt_treeview.ROLE_KEY, /*column*/ "emp_id")
uo_tree.of_map(/*ads*/ lds_staff, /*role*/ u_pbt_treeview.ROLE_TEXT, /*column*/ "emp_name")
uo_tree.of_from_datastore(/*ads*/ lds_staff, /*parent_keys*/ as_keys)

// Kept while its nodes are shown ; the window destroys them when it closes
ids_lots[UpperBound(ids_lots) + 1] = lds_staff
// The roots of the table carry 0 in parent_id (a NOT NULL column) : 0 names the top
uo_tree.is_root_parent_value = "0"
uo_tree.of_from_datastore(/*ads*/ ids_depts)

Uma árvore agrupada por colunas #

O estilo TreeView de um DataWindow, sem DataWindow: is_group_by = "region|country|city" faz das linhas de of_from_datastore as folhas de grupos construídos sobre os valores dessas colunas, um nível por coluna (ROLE_PARENT não tem papel, ROLE_KEY nomeia as folhas). A chave de um grupo é o seu valor (/, | e % escritos %2F, %7C, %25), o seu texto o valor escrito com o formato da coluna com a mesma chave, «(vazio)» para um valor vazio; o handle de um nó de grupo lê of_group_column() e of_group_value(). Definido depois de um carregamento, reagrupa; of_reload_row coloca uma linha cujo valor mudou no seu novo grupo. of_set_level_image dá uma imagem a todos os nós de um nível, of_expand_to_level abre a árvore até um nível, e is_summary dá os totais de cada grupo. Com ib_write_back, uma folha largada sob um grupo do último nível escreve todas as suas colunas de grupo antes do evento; noutro lado, e para um nó de grupo, a deslocação é recusada. O texto de um grupo segue um formato posto depois do carregamento, a chegada da sua coluna e a língua de apresentação; um valor que começa por __ escreve-se %5F_ na chave; of_group_value de uma data-hora vale yyyy-mm-dd hh:mm:ss, de uma hora hh:mm:ss. Sem ib_write_back, uma folha arrastada para outro grupo volta ao seu no agrupamento seguinte, pois a sua linha não mudou; um nó acrescentado à mão sob um grupo que desaparece sobe ao topo.

// The sales, one row per sale, grouped by region, country and city : the customer is
// the text of each sale
uo_tree.is_group_by = "region|country|city"
uo_tree.of_map(/*role*/ u_pbt_treeview.ROLE_TEXT, /*column*/ "customer")
uo_tree.of_from_datastore(/*ads*/ ids_sales)

// The amount of each sale, and the total of each group
uo_tree.of_add_column(/*key*/ "amount", /*title*/ "Amount")
uo_tree.of_column(/*key*/ "amount").is_format = "#,##0.00"
uo_tree.of_column(/*key*/ "amount").is_summary = u_pbt_treeview.SUMMARY_SUM

// A globe before every region ; only the regions show at first
uo_tree.of_set_level_image(/*level*/ 1, /*image*/ "mono:img\packimages.dll:svg/ribbon/globe", /*expanded_image*/ "")
uo_tree.of_expand_to_level(/*level*/ 1)

Propriedades #

PropriedadeTipoPredefiniçãoFunção
is_selection_modestringSELECT_SINGLEComo o utilizador seleciona: SELECT_SINGLE (um nó), SELECT_MULTIPLE (Ctrl e Shift, como o Explorador) ou SELECT_NONE (o teclado só move um foco, nada é selecionado). Outro valor é recusado: o antigo fica, of_get_last_error diz porquê
ib_checkboxesbooleanfalseUma caixa de verificação antes de cada nó
ib_check_cascadebooleantrueUma marca do utilizador num nó marca a sua subárvore, exceto um nó desativado e a sua subárvore; uma marca do código marca tudo. Um pai é o estado dos filhos que a árvore pode desenhar: marcado quando todos o estão, misto (CHECK_MIXED) quando uma parte o está. false: cada nó mantém a sua própria marca; uma marca do utilizador nunca toca num nó além do limite de demonstração, nem, com ib_write_back, num nó escondido
ib_editablebooleanfalseO utilizador renomeia um nó: F2, ou um clique no nó já selecionado. Enter guarda, Esc devolve (ue_node_edited); um texto esvaziado é recusado
ib_drag_dropbooleanfalseO utilizador arrasta um nó antes, depois ou para dentro de outro (ue_node_moved); nunca para a sua própria subárvore; uma largada no quarto inferior de um ramo aberto torna-o o seu primeiro filho; a janela que perde o foco durante um arrastar cancela-o
ib_veto_changesbooleanfalsePerguntar ue_node_editing e ue_node_moving antes de um texto escrito ser guardado ou de um nó se deslocar — por gesto como por of_move_node (desativado por omissão, como todo o evento cancelável)
is_filterstring""A pesquisa: só aparecem os nós cujo texto a contém, com os que os contêm, abertos, o texto encontrado realçado. "" mostra tudo. O campo da barra de ferramentas também a escreve: uma leitura devolve-a de imediato; um nó selecionado que ela oculta sai da seleção (ue_selection_changed)
ib_toolbarbooleanfalseUma barra por cima da árvore: o campo de pesquisa, Expandir tudo, Recolher tudo
ib_show_linesbooleanfalseLinhas finas ligam cada nó ao seu pai
ii_indentinteger18O recuo de um nível, em píxeis, de 8 a 64. Outro valor é recusado: o antigo fica, of_get_last_error diz porquê
is_tree_titlestring""O título da coluna da árvore de uma lista em árvore. Aceita o texto formatado com etiquetas
ib_write_backbooleanfalseCom uma árvore alimentada por of_from_datastore: um texto renomeado é escrito na coluna ROLE_TEXT, um nó que muda de pai escreve-o na coluna ROLE_PARENT (NULL no topo; uma deslocação entre os mesmos irmãos não escreve nada), antes do evento. Um nó de linha não vai então nem para debaixo de um nó acrescentado à mão nem para debaixo de uma linha sem valor de chave. Um valor recusado, ou um DataStore destruído, volta a pôr o nó no lugar e levanta ue_write_back_failed. Sem ela, um arrastar só desloca o nó. O Update continua a ser seu. Uma marca do utilizador escreve-se também na coluna ROLE_CHECKED de cada linha que muda. Uma marca escreve também os ramos acima cujo estado passa a marcado ou desmarcado; cada valor é julgado primeiro, tudo ou nada; sem coluna ROLE_TEXT, um nó de linha não se renomeia
ib_enabledbooleantruefalse desativa a árvore: os nós continuam visíveis, nada mais responde ao utilizador e a árvore sai da ordem da tecla Tab. O seu código continua a mudar tudo; deixa de receber o foco
ib_veto_selectionbooleanfalsePerguntar ue_selection_changing antes de a seleção mudar: uma escolha do utilizador, of_select_node, of_clear_selection (desativado por omissão, como todo o evento cancelável)
ib_veto_togglebooleanfalsePerguntar ue_node_toggling antes de um nó se abrir ou fechar, por um gesto ou pelo código
ib_single_expandbooleanfalseUm só ramo aberto sob cada pai: abrir um nó fecha os seus irmãos abertos (ue_node_toggled para cada um, sem pergunta); defini-lo não fecha nada no momento; of_expand_all e of_expand_to_level ignoram-no
ib_parents_firstbooleanfalseEm cada nível, os nós que têm (ou prometem) filhos antes das folhas — as pastas antes dos ficheiros —, seja qual for a ordenação; uma largada só vai então dentro
ib_summary_filteredbooleanfalseOs totais dos ramos (is_summary de uma coluna) só contam o que a pesquisa mostra; false: todo o nó que a árvore pode desenhar
is_group_bystring""Uma árvore agrupada por colunas, como o estilo TreeView de um DataWindow: `"regioncountry" faz um nível de grupos por coluna, sendo as linhas de of_from_datastore as folhas sob o último. Definido depois de um carregamento, reagrupa; uma coluna que o DataStore não tem é ignorada. O que um agrupamento teve de corrigir, para todas as fontes, lê-se em of_get_last_error`
is_root_parent_valuestring""Os valores de pai que nomeiam o topo da árvore, unidos por ` ("0", "0-1"): uma linha assim fica no topo sem contar como órfã, e um nó deslocado para o topo com ib_write_back escreve o primeiro em vez de NULL. ""`: só um pai vazio (NULL) nomeia o topo
ib_filter_accentsbooleanfalsefalse: a pesquisa (is_filter) ignora os acentos, como a ordenação; true: contam
ib_auto_tooltipbooleantrueUm rótulo cortado pela largura mostra o seu texto inteiro num tooltip — nunca por cima de um tooltip que a sua aplicação deu ao nó
is_export_scopestringEXPORT_ALLO que of_export_csv e of_export_xlsx escrevem: EXPORT_ALL todos os nós, ramos fechados incluídos, EXPORT_SHOWN as linhas no ecrã. Um nó escondido nunca é escrito; outro valor é recusado
ib_allow_dropbooleanfalseAceitar os ficheiros largados a partir do Explorador sobre um nó: o nó sob o cursor acende-se, ue_drop_files nomeia-o com os caminhos completos
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 um nó — n_pbt_treeview_node #

O seu handle, através de of_node(endereço). Uma leitura pergunta à árvore o que o nó é agora. O seu of_count() conta os seus filhos, o seu of_keys_at(n) devolve o endereço do seu n-ésimo filho (a partir de 1), o seu of_has(chave) diz se tem esse filho, o seu of_key() devolve a sua chave.

PropriedadeTipoPredefiniçãoFunção
is_textstring""O texto do nó. Aceita o texto formatado com etiquetas. Vazio, o nó mostra a sua chave
is_imagestring""A imagem antes do texto: um ficheiro do posto, um recurso "ficheiro.dll:nome", um glifo "mono:…" / "tint:…" desenhado no tema, um endereço https://. http:// é recusado (ue_image_failed, REASON_INSECURE)
is_expanded_imagestring""A imagem quando o nó está aberto (uma pasta aberta); "" mantém is_image
is_state_imagestring""A imagem de estado do nó, antes da sua imagem: uma bandeira, um estado — a StatePicture de um TreeView PowerBuilder. Um clique nela levanta ue_state_clicked e não seleciona o nó; mesmas fontes e recusas que is_image
is_overlay_imagestring""Uma pequena imagem desenhada por cima do canto inferior da imagem do nó (uma seta de atalho, um cadeado) — a OverlayPicture de um TreeView PowerBuilder
is_selected_imagestring""A imagem do nó enquanto está selecionado — a SelectedPicture de um TreeView PowerBuilder. "" mantém is_image
ib_expandedbooleanfalsetrue abre o nó (os seus filhos aparecem), false fecha-o; segue-se ue_node_toggled, como num clique no seu chevron. Um nó sem filhos lê-se false; abrir um nó que só promete filhos pede-os (ue_children_needed); chegam com a resposta, depois do retorno desta linha; com ib_veto_toggle, ue_node_toggling é perguntado primeiro; recusado, nada é enviado e of_get_last_error di-lo
ib_has_childrenbooleanfalseUma promessa de filhos: o chevron aparece embora ainda nada esteja acrescentado. Abrir o nó levanta ue_children_needed, onde a sua aplicação os acrescenta. A promessa vale até à resposta, mesmo que lá tenha sido acrescentado ou largado um nó; voltar a pô-la a true faz perguntar de novo na próxima abertura
ib_checkedbooleanfalseA marca do nó (ib_checkboxes da árvore). Com ib_check_cascade, escrevê-la marca toda a subárvore (nós desativados incluídos), e lê-se true quando os seus filhos que a árvore pode desenhar estão todos marcados (of_check_state diz misto); os filhos recebidos sob uma folha marcada recebem a sua marca. Uma marca escrita pelo seu código não levanta nada
ib_enabledbooleantruefalse desativa o nó: o utilizador não o pode selecionar, marcar, renomear nem arrastar, nada se larga sobre a sua linha, o teclado salta-o, e uma marca do utilizador num pai deixa-o como está, com a sua subárvore. O seu código continua a selecioná-lo e a marcá-lo
ib_visiblebooleantruefalse retira do ecrã o nó e a sua subárvore; mantém o seu endereço
is_badgestring""Um pequeno emblema depois do texto (etiquetas aceites): um número de elementos não lidos; "" nenhum
ib_read_onlybooleanfalsetrue: o utilizador não o pode renomear nem arrastar (continua a ser um destino), e Delete exclui-o; o seu código continua a poder
ib_drop_targetbooleantruefalse: nada é largado dentro dele, nem um nó arrastado nem um ficheiro do Explorador; antes ou depois dele continua permitido
ib_show_checkboxbooleantruefalse: sem caixa neste nó (ib_checkboxes) — não conta para o pai, não está em of_checked_keys, e a cascata atravessa-o para os seus filhos
of_keys ( ) → string——Devolve o endereço do nó: as suas chaves juntas por /
of_level ( ) → long——Devolve a sua profundidade: 1 para um nó do topo, 2 para um nó dentro dele… 0 quando a árvore não o contém
of_position ( ) → long——Devolve o seu lugar entre os filhos do seu pai, a partir de 1, pela ordem de acréscimo (uma ordenação só muda a ordem mostrada); 0 quando a árvore não o contém
of_parent_keys ( ) → string——Devolve o endereço do seu pai; "" para um nó do topo
of_check_state ( ) → string——Devolve o estado da sua caixa: CHECK_ON, CHECK_OFF ou CHECK_MIXED (parte dos seus filhos marcada, com ib_check_cascade); "" quando a árvore não o contém
of_row ( ) → long——Devolve o número de linha de hoje, no DataStore de of_from_datastore, da linha de onde vem o nó — seja qual for a chave que teve de tomar, e após uma ordenação ou um filtro do DataStore. 0 para um nó acrescentado à mão ou cuja linha desapareceu; um nó de um lote devolve a sua linha no seu DataStore, um nó de grupo 0; 0 também quando o DataStore do seu lote foi recarregado para outro nó
of_group_column ( ) → string——Para um nó de grupo de is_group_by: a coluna pela qual o seu nível agrupa ("region"); "" para qualquer outro nó
of_group_value ( ) → string——Para um nó de grupo: o valor da sua coluna que representa, tal como as linhas o contêm (uma data yyyy-mm-dd, um número com ponto, "" para o grupo dos valores vazios); "" para qualquer outro nó; uma data-hora yyyy-mm-dd hh:mm:ss, uma hora hh:mm:ss
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
il_accentlong-1Destaque do nó: a sua seleção (enquanto a árvore tem o foco) e a sua caixa marcada usam-no; o emblema mantém a cor do tema (-1 = o do componente)
il_back_colorlong-1Fundo da linha do nó, em RGB(r,g,b) (-1 = o que o tema dá). Uma linha selecionada usa as cores da seleção
il_text_colorlong-1Cor do texto da linha do nó (-1 = o que o tema dá)
il_back_color_hoverlong-1Fundo da linha do nó sob o ponteiro (-1 = o que o tema dá)
il_text_color_hoverlong-1Cor do texto da linha do nó sob o ponteiro (-1 = o que o tema dá)

Propriedades de uma coluna — n_pbt_treeview_column #

O seu handle, através de of_column(chave). Um valor escrito pelo seu código é mudo, como SetItem — exceto a sua disposição: ii_width, ii_index e ib_visible escritos pelo seu código levantam ue_layout_changed quando a disposição muda, como um gesto. Uma leitura devolve o que o utilizador possa ter mudado (largura, lugar).

PropriedadeTipoPredefiniçãoFunção
is_titlestring""O título no cabeçalho (etiquetas aceites); "" mostra a chave
ii_widthinteger0A largura em píxeis: 0 é automática (tão larga como o título e os valores desenhados), senão de 40 a 2000. O utilizador arrasta o bordo do cabeçalho: uma leitura devolve-a de imediato
is_alignstringALIGN_STARTOnde ficam os valores nas suas células: ALIGN_START, ALIGN_CENTER, ALIGN_END — o início e o fim da leitura, que seguem uma aplicação da direita para a esquerda. Outro valor é recusado
is_formatstring""Como um valor é escrito: uma máscara numérica para um número ("#,##0.00", separadores da língua de apresentação), os tokens de data de um formato de apresentação PowerBuilder para uma data ou uma data-hora ("dd/mm/yyyy", "d mmm yyyy hh:mm" — mm depois de uma hora são os minutos —, AM/PM, s, f, literais "…", [shortdate], [longdate], [time]), os mesmos do datagrid; "" escreve o valor tal como está
ib_visiblebooleantruefalse retira a coluna do ecrã; mantém o seu lugar e a sua chave
ii_indexinteger—O seu lugar entre todas as colunas, a partir de 1: escrevê-lo desloca a coluna. O utilizador também arrasta um cabeçalho: uma leitura devolve-o de imediato
ib_sortablebooleantrueUm clique no seu cabeçalho ordena a árvore por esta coluna. O cabeçalho da coluna da árvore (is_tree_title) ordena sempre, pelo texto dos nós
is_summarystring""O total que cada ramo mostra nesta coluna: SUMMARY_SUM, SUMMARY_AVG, SUMMARY_MIN, SUMMARY_MAX, SUMMARY_COUNT (os valores não vazios), do que os filhos trazem até às folhas, a negrito; SUMMARY_NONE (""): nenhum. of_get_field lê o total, uma ordenação usa-o; SUMMARY_COUNT escreve-se como número simples, nunca por is_format; SUMMARY_MIN e SUMMARY_MAX comparam também datas
ib_summary_over_valuebooleanfalsefalse: um ramo que tem um valor próprio na coluna guarda-o (e fá-lo subir); true: o total ocupa o seu lugar
il_accentlong-1Destaque do cabeçalho: a sua seta de ordenação e o anel do teclado usam-no (-1 = o do componente)
il_back_colorlong-1Fundo do cabeçalho, em RGB(r,g,b) (-1 = o que o tema dá)
il_text_colorlong-1Cor do texto do cabeçalho (-1 = o que o tema dá)
il_back_color_hoverlong-1Fundo do cabeçalho sob o ponteiro (-1 = o que o tema dá)
il_text_color_hoverlong-1Cor do texto do cabeçalho sob o ponteiro (-1 = o que o tema dá)
is_tooltipstring""Tooltip simples apresentado ao passar sobre o cabeçalho da coluna
is_super_tooltip_titlestring""Título do tooltip enriquecido do cabeçalho (prevalece sobre is_tooltip)
is_super_tooltip_textstring""Texto do tooltip enriquecido do cabeçalho (aceita marcação enriquecida)
is_super_tooltip_imagestring""Imagem do tooltip enriquecido do cabeçalho

Constantes #

Estão em u_pbt_treeview: u_pbt_treeview.CHECK_MIXED.

ConstanteValorSignificado
SUMMARY_NONE""Sem total — o predefinido
SUMMARY_SUM"sum"A soma
SUMMARY_AVG"avg"A média das folhas
SUMMARY_MIN"min"O valor mais pequeno
SUMMARY_MAX"max"O valor maior
SUMMARY_COUNT"count"O número de valores não vazios
SELECT_SINGLE"single"Um nó selecionado de cada vez — o predefinido
SELECT_MULTIPLE"multiple"Vários, com Ctrl e Shift
SELECT_NONE"none"Nenhum: só um foco se move
SORT_ASC"asc"Crescente
SORT_DESC"desc"Decrescente
SORT_NONE"none"Sem ordenação: a ordem de acréscimo
CHECK_ON"on"Marcado (com a cascata: toda a subárvore)
CHECK_OFF"off"Não marcado
CHECK_MIXED"mixed"Parte dos filhos marcada
ALIGN_START"start"No início da leitura — o predefinido
ALIGN_CENTER"center"Ao centro
ALIGN_END"end"No fim da leitura (os números)
ROLE_KEY"key"A chave do nó (um identificador); sem ela, o RowID
ROLE_PARENT"parent"A chave do nó que o contém; com uma coluna ROLE_KEY, nunca um RowID
ROLE_TEXT"text"O seu texto (mostrado como texto)
ROLE_IMAGE"image"A sua imagem
ROLE_CHECKED"checked"Marcado quando o valor diz sim (1, -1, true, y, yes, on, t, o; não: 0, false, n, no, off, f, maiúsculas ignoradas); reescrito como a coluna já o escreve; sob a cascata, só é lido para uma folha: um pai é aí o estado dos seus filhos
ROLE_BADGE"badge"O seu emblema
ROLE_EXPANDED"expanded"Aberto ao carregar quando o valor diz sim
ROLE_HAS_CHILDREN"has_children"A linha promete filhos quando o valor diz sim: um chevron, e ue_children_needed quando o nó abre; lido uma vez, quando o nó é criado
ROLE_STATE_IMAGE"state_image"A sua imagem de estado
ROLE_OVERLAY_IMAGE"overlay_image"A sua imagem sobreposta
EXPORT_ALL"all"Exportação: todos os nós, ramos fechados incluídos — o predefinido
EXPORT_SHOWN"shown"Exportação: as linhas no ecrã
REASON_INSECURE"insecure"Um endereço http://
REASON_NOT_FOUND"notfound"Um ficheiro não encontrado
REASON_UNC"unc"Um caminho de rede vindo de uma coluna de DataStore, recusado antes de qualquer pedido

Métodos #

MétodoFunção
of_add_node (string as_keys, string as_text)Acrescenta um nó no seu endereço, no fim do seu pai: "europe" no topo, "europe/france" dentro de "europe" (acrescentado primeiro). as_text aceita etiquetas ("" mostra a chave). Devolve 0 depois de acrescentado, -5 para um endereço com um nível vazio, uma chave com ` ou que começa por __, um endereço já ocupado, um pai desconhecido (of_get_last_error diz qual), -2` quando o componente não está criado
of_add_node (string as_keys, string as_text, string as_image)O mesmo com a sua imagem (is_image do handle). Devolve 0 depois de acrescentado, -5 como acima, -2 quando o componente não está criado
of_insert_node (string as_keys, string as_text, string as_image, long al_position)Acrescenta um nó num lugar entre os filhos do seu pai, a partir de 1 (para além do último: no fim). Devolve 0 depois de acrescentado, -5 como of_add_node, -2 quando o componente não está criado
of_remove_node (string as_keys)Retira um nó e tudo o que contém (os seus handles são libertados). Retirar o nó selecionado passa a seleção para o que o continha (ue_selection_changed). O nó de uma linha de DataStore fica fora até ao próximo of_from_datastore: nem of_map nem a releitura de outra linha o trazem de volta, of_reload_row da sua linha sim. Devolve 0 depois de retirado, -5 para um endereço que a árvore não contém, -2 quando o componente não está criado
of_move_node (string as_keys, string as_to_parent_keys, long al_position)Desloca um nó com a sua subárvore para outro pai ("" = o topo), para um lugar a partir de 1 (para além do último: no fim) — ou para outro lugar entre os seus irmãos. O seu endereço muda: os handles obtidos no endereço antigo são libertados por esta chamada, de imediato; um handle obtido depois no novo continua válido (uma deslocação entre os mesmos irmãos não liberta nada). Com ib_veto_changes, ue_node_moving é perguntado primeiro, com o lugar final; com ib_write_back, um nó de linha que muda de pai escreve-o antes de se mover (uma deslocação entre os mesmos irmãos não escreve nada). Segue-se ue_node_moved, como num arrastar. O que escreve é julgado de novo depois de ue_node_moving; se o nó não se mover, o que foi escrito é reposto. Devolve 0 (também quando já lá está: nada é perguntado, escrito nem levantado), -4 se a aplicação recusar ou se o DataStore recusar o valor (ue_write_back_failed), -5 para um nó ou um pai desconhecido, uma deslocação para a sua própria subárvore, uma chave já ocupada sob o novo pai, com ib_write_back um nó de linha sob um nó acrescentado à mão ou sob uma linha sem valor de chave, um nó de um lote fora do seu lote ou cujo DataStore foi recarregado para outro nó, uma folha de uma árvore agrupada noutro lado que não sob um grupo do último nível, um nó de grupo, um nó que se moveu ou saiu durante ue_node_moving, -2 quando o componente não está criado
of_clear ( )Esvazia a árvore: nós, handles e linhas lidas (o DataStore continua ligado para um novo of_from_datastore); as colunas e as opções ficam. Segue-se ue_selection_changed se havia nós selecionados. As colunas mantêm as suas cores e tooltips. As imagens dos níveis (of_set_level_image) também ficam. Devolve 0 depois de aplicado, -2 quando o componente não está criado
of_node (string as_keys)O handle n_pbt_treeview_node de um nó, pelo seu endereço (criado no primeiro acesso): o seu texto, imagem, marca, estados, cores e tooltip; um endereço impossível (nível vazio, `, __`) devolve um handle inerte, que não lê nem escreve nada
of_edit_node (string as_keys)Abre o texto de um nó em edição a partir do seu código — o EditLabel de um TreeView PowerBuilder. O nó é primeiro selecionado (em SELECT_NONE, só trazido à vista), depois o campo abre-se; o fim é do utilizador (Enter: ue_node_editing, depois ue_node_edited; Esc ou of_cancel_edit devolve o texto). Funciona com ib_editable = false, num nó só de leitura ou desativado. Devolve 0 depois de aberto o campo, -5 para um nó que a árvore não tem ou não pode desenhar, uma árvore desativada, um nó de grupo de is_group_by ou uma linha cujo DataStore não tem coluna ROLE_TEXT com ib_write_back (of_get_last_error diz qual), -4 quando ue_selection_changing (ou ue_node_toggling) recusou, -2 quando o componente não está criado
of_cancel_edit ( )Fecha o campo de uma edição em curso (aberta pelo utilizador ou por of_edit_node) e devolve o texto, como Esc: nada é levantado. Devolve 0 depois de aplicado (nenhuma edição em curso: 0, nada muda), -2 quando o componente não está criado
of_expand_all ( )Abre todos os nós que têm filhos (um ramo só prometido fica fechado: nada é pedido). Segue-se ue_node_toggled para cada um, depois ue_layout_changed uma vez. Devolve 0 depois de aplicado, -4 quando ue_node_toggling recusou algum, -2 quando o componente não está criado
of_collapse_all ( )Fecha todos os nós. Segue-se ue_node_toggled para cada um dos que estavam abertos, depois ue_layout_changed uma vez. Devolve 0 depois de aplicado, -4 quando ue_node_toggling recusou algum, -2 quando o componente não está criado
of_expand_all (string as_keys)Abre um nó e todo o nó sob ele que tem filhos (o ExpandAll(handle) do PowerBuilder); "" = toda a árvore. Devolve 0 depois de aplicado, -4 quando ue_node_toggling recusou algum, -5 para um nó que a árvore não contém, -2 quando o componente não está criado
of_collapse_all (string as_keys)Fecha um nó e todo o nó sob ele; "" = toda a árvore. Devolve 0 depois de aplicado, -4 quando ue_node_toggling recusou algum, -5 para um nó que a árvore não contém, -2 quando o componente não está criado
of_expand_to_level (long al_level)Mostra a árvore até um nível: os níveis acima de al_level abrem-se, este nível e os seguintes fecham-se (1: só se vê o topo). Um ramo cuja promessa não teve resposta fica fechado. ue_node_toggled para cada nó mudado, depois ue_layout_changed. Devolve 0 depois de aplicado, -4 quando ue_node_toggling recusou algum, -5 para um nível abaixo de 1, -2 quando o componente não está criado
of_set_level_image (integer ai_level, string as_image, string as_expanded_image)A imagem de todo o nó de um nível (1 = o topo) que não tem uma própria — o SetLevelPictures do PowerBuilder, prático para uma árvore agrupada: as_image, e as_expanded_image enquanto o nó está aberto ("" mantém as_image). Dois "" retiram as imagens do nível. Devolve 0 depois de definido, -5 para um nível abaixo de 1, -2 quando o componente não está criado
of_clear_children (string as_keys)Retira os filhos de um nó (os seus handles são libertados; um nó de linha fica fora até ao próximo of_from_datastore) e mantém o nó, que promete de novo: a sua próxima abertura levanta ue_children_needed — o «atualizar» de uma pasta. Aberto, fecha-se (ue_node_toggled). Fecha sem perguntar ue_node_toggling, e segue-se ue_layout_changed. Devolve 0 depois de aplicado, -5 para um nó que a árvore não contém, -2 quando o componente não está criado
of_scroll_to_node (string as_keys)Mostra um nó: o que o contém abre-se (ue_node_toggled para cada um, do mais exterior para o mais interior), depois a árvore desloca-se até ele estar à vista. A seleção não muda. Um nó que a árvore não poderia desenhar é recusado antes de algo se abrir. Devolve 0 depois de aplicado, -5 para um nó que a árvore não contém ou não desenha (escondido ou contido num escondido, além do limite de demonstração, afastado pela pesquisa; of_get_last_error diz qual), -4 se ue_node_toggling recusar abrir um nó que o contém (ib_veto_toggle), -2 quando o componente não está criado
of_select_node (string as_keys)Seleciona um nó sozinho, como um clique: o que o contém abre-se (um ramo prometido faz a sua pergunta), o foco vai para ele e ele fica à vista; segue-se ue_selection_changed (já selecionado sozinho: nada é levantado). Um nó desativado também é selecionado: o desativado trava o utilizador, não o seu código. O nó é julgado primeiro: uma árvore abre para selecionar, como o TreeView do Windows, mas nada se abre para um nó recusado. Com os dois vetos, perguntam-se primeiro as aberturas (ue_node_toggling), depois a seleção (ue_selection_changing). Devolve 0 depois de selecionado, -5 para um nó que a árvore não contém ou não desenha (escondido ou contido num escondido, além do limite de demonstração, afastado pela pesquisa; of_get_last_error diz qual), ou quando is_selection_mode vale SELECT_NONE, -4 se ue_selection_changing recusar a seleção (ib_veto_selection) ou ue_node_toggling um nó a abrir (ib_veto_toggle), -2 quando o componente não está criado
of_select_nodes (string as_keys_json)Seleciona vários nós de uma vez — o par de of_selected_keys: as_keys_json é um array JSON de endereços, em qualquer ordem (["europe/france","asia"], o mesmo endereço duas vezes conta uma). Cada nó é julgado primeiro (presente, e desenhável depois de aberto o que o contém); depois abre-se o que os contém, o foco e a âncora vão para o último endereço nomeado, e ue_selection_changed segue-se uma vez. Com ib_veto_toggle, ue_node_toggling é perguntado para cada nó que abre, depois com ib_veto_selection ue_selection_changing uma vez para toda a seleção. "[]" não deixa nada selecionado; em SELECT_SINGLE, um endereço no máximo. Devolve 0 depois de selecionados (também quando essa seleção já lá está: nada é levantado), -4 recusado, -5 para um texto que não é um array JSON de endereços, um endereço que a árvore não contém ou não desenha (of_get_last_error diz qual), mais de um endereço em SELECT_SINGLE, ou SELECT_NONE, -2 quando o componente não está criado
of_clear_selection ( )Não deixa nenhum nó selecionado: segue-se ue_selection_changed("[]") (já nada selecionado: nada é levantado). Devolve 0 depois de aplicado, -4 se ue_selection_changing recusar, -2 quando o componente não está criado
of_selected_key ( )O endereço do nó selecionado (o que tem o foco quando há vários); senão "". Lido em direto
of_selected_keys ( )Os endereços de todos os nós selecionados, num array JSON pela ordem da árvore: ["europe/france","asia"]; "[]" se nenhum. Lido em direto; lê-se com n_pbt_json
of_checked_keys ( )Os endereços de todos os nós marcados, num array JSON pela ordem da árvore. Com ib_check_cascade, um nó cuja subárvore está toda marcada faz parte, um nó misto não. Lido em direto
of_check_all (boolean ab_checked)Marca (ou desmarca) todos os nós de uma vez. Uma marca escrita pelo código é um valor: nada é levantado. Devolve 0 depois de aplicado, -2 quando o componente não está criado
of_sort (string as_column, string as_dir)Ordena os nós mostrados, em cada nível: por uma coluna (a sua chave) ou pelo texto dos nós (as_column = ""). as_dir: SORT_ASC, SORT_DESC ou SORT_NONE (a ordem de acréscimo). A ordem do modelo (of_keys_at, of_position) não muda. Seguem-se ue_sort_changed e depois ue_layout_changed, como num clique num cabeçalho. as_column pode também nomear um campo que nenhuma coluna mostra; uma coluna resumida ordena pelos seus totais, e com ib_parents_first os ramos ficam antes das folhas. as_column "text" é o texto dos nós, como "". Devolve 0 depois de aplicado (também quando a ordenação já é essa: nada é levantado), -5 para um nome que não o é (letras, algarismos e _) ou um sentido desconhecido, -2 quando o componente não está criado
of_sort (string as_sort)Ordena por várias chaves, pela sua ordem: a primeira decide, as seguintes desempatam. as_sort escreve-se como o SetSort de um DataWindow o lê — "type A, text D" (também asc e desc, sem direção = crescente, text = o texto dos nós, qualquer outro nome uma coluna ou um campo); "" retira a ordenação. Seguem-se ue_sort_changed e depois ue_layout_changed. São aceites vários espaços entre uma coluna e o seu sentido, como por SetSort. Devolve 0 depois de ordenado (também quando já é essa ordenação: nada é levantado), -5 para um nome que não o é, outra direção ou uma chave nomeada duas vezes, -2 quando o componente não está criado
of_find_node (string as_field, string as_value, string as_after_keys)O endereço do primeiro nó cujo campo vale exatamente as_value (as maiúsculas contam): as_field "" = o texto do nó, qualquer outro nome um campo (seu, uma coluna do DataStore, o total de uma coluna resumida). Pela ordem que a árvore mostra, ramos fechados e nós afastados pela pesquisa incluídos, nunca um nó escondido; as_after_keys "" começa no primeiro, senão depois desse nó: volte a dar o endereço encontrado para o seguinte. "" quando não há nenhum (of_get_last_error diz porquê quando os argumentos foram recusados). Parte depois do lugar de as_after_keys na ordem mostrada — também um nó escondido; um as_after_keys desconhecido, ou uma chamada durante uma espera, devolve "" e of_get_last_error diz porquê (esta leitura esvazia-o primeiro). of_find_nodes devolve-os todos de uma vez
of_find_nodes (string as_field, string as_value)Todos os nós cujo campo vale exatamente as_value (as maiúsculas contam), numa passagem: os seus endereços como array JSON, na ordem que a árvore mostra (["europe/france","asia"]); "[]" se não houver nenhum. as_field "" é o texto do nó, qualquer outro nome um campo. Os ramos fechados e os nós que a pesquisa afasta são percorridos, nunca um nó escondido (nem, em modo de demonstração, um nó além do limite). "[]" com of_get_last_error quando o nome de campo não o é ou durante uma espera. Leia-o com n_pbt_json
of_search_next ( )Seleciona o nó seguinte que a pesquisa encontrou (is_filter), depois do nó do foco, em ciclo; F3 faz o mesmo. Como of_select_node: segue-se ue_selection_changed, e com ib_veto_selection ue_selection_changing é perguntado primeiro. Em SELECT_NONE, move para lá o foco e devolve 0; durante uma espera, devolve -5 e of_get_last_error diz porquê. Devolve 0 depois de selecionado, -4 recusado, -5 sem pesquisa ou sem correspondências, -2 quando o componente não está criado
of_search_prev ( )Seleciona o nó anterior que a pesquisa encontrou, antes do nó do foco, em ciclo; Shift+F3 faz o mesmo. Em SELECT_NONE, move para lá o foco e devolve 0; durante uma espera, devolve -5 e of_get_last_error diz porquê. Devolve 0 depois de selecionado, -4 recusado, -5 sem pesquisa ou sem correspondências, -2 quando o componente não está criado
of_match_count ( )Devolve quantos nós a pesquisa (is_filter) encontrou, lido de imediato; 0 sem pesquisa
of_add_column (string as_key, string as_title)Acrescenta uma coluna no fim: a árvore torna-se uma lista em árvore, a primeira coluna tem a árvore, esta mostra o campo com a mesma chave de cada nó (of_set_field, ou a coluna do DataStore). A sua largura é automática. A chave text é recusada (-5): designa o texto dos nós. Devolve 0 depois de acrescentada, -5 para uma chave que não pode sê-lo (vazia, com / ou `, que começa por __) ou uma coluna já presente, -2` quando o componente não está criado
of_add_column (string as_key, string as_title, integer ai_width)O mesmo com uma largura em píxeis (0 = automática; 40 a 2000). Devolve 0 depois de acrescentada, -5 como acima, -2 quando o componente não está criado
of_remove_column (string as_key)Retira uma coluna (o seu handle é libertado); saída a última, a lista volta a ser uma árvore. Retirar a coluna ordenada levanta ue_sort_changed com a chave seguinte da ordenação — SORT_NONE quando era a única —, depois ue_layout_changed. Devolve 0 depois de retirada, -5 para uma coluna que a lista não contém, -2 quando o componente não está criado
of_clear_columns ( )Retira todas as colunas (os seus handles são libertados): a lista volta a ser uma árvore. Retirar a coluna ordenada levanta ue_sort_changed com a chave seguinte da ordenação — SORT_NONE quando era a única —, depois ue_layout_changed. Devolve 0 depois de aplicado, -2 quando o componente não está criado
of_column (string as_key)O handle n_pbt_treeview_column de uma coluna (criado no primeiro acesso): o seu título, largura, alinhamento, formato, visibilidade, lugar e se um clique no seu cabeçalho ordena
of_set_field (string as_keys, string as_field, string as_value)Dá a um nó um campo seu: of_set_field("europe/france", "population", "68000000"); a coluna de chave population mostra-o. Um nó de um DataStore já tem cada coluna como campo; um campo seu com o mesmo nome prevalece. Um nome de campo: letras, algarismos e _, sem algarismo inicial. Devolve 0 depois de definido, -5 para um nó desconhecido ou um nome inválido, -2 quando o componente não está criado
of_get_field (string as_keys, string as_field)Lê um campo de um nó, em direto: um dos seus (of_set_field), uma coluna do DataStore de onde vem, ou um campo integrado (key, keys, text, badge, level, position, count, image). "" quando não o tem; para uma coluna resumida (is_summary), o total bruto do ramo, um número com ponto; o campo integrado count conta os filhos que a árvore pode desenhar
of_from_datastore (datastore ads)Alimenta a árvore a partir de um DataStore: uma linha = um nó (ver acima). Os nós de um carregamento anterior saem (os seus handles são libertados); os nós acrescentados à mão no topo ficam, os seus handles também. Duas linhas com a mesma chave: a segunda recebe "chave~RowID"; uma chave impossível (com / ou `, ou que começa por __): o RowID — os seus filhos continuam a encontrá-la pelo seu valor. Com uma coluna ROLE_KEY, um valor de pai nomeia uma chave, nunca um RowID. Datas e números são lidos sejam quais forem as definições regionais (data yyyy-mm-dd, hh:mm:ss, número com ponto). O que o carregamento teve de corrigir (pais em falta, ciclos, chaves duplicadas ou impossíveis) é dito por of_get_last_error, o retorno continuando 0. Com is_group_by, as linhas são as folhas de grupos (ROLE_PARENT não tem papel). Um novo carregamento leva os lotes pendurados sob as suas linhas e mantém os pendurados sob um nó acrescentado à mão. Um novo carregamento só liberta os handles do que substitui (um nó acrescentado à mão, um handle inerte, um endereço ainda não criado guardam o seu); um nó de linha deslocado sem ib_write_back volta ao lugar que a sua linha diz. O relatório de of_get_last_error conta também os nós acrescentados à mão subidos ao topo (lifted=N) e os lotes que partiram com o seu nó (lots=N). Devolve 0 depois de carregado, -5 quando o DataStore não é válido, não tem nenhuma coluna ou lhe falta uma coluna nomeada por of_map (of_get_last_error nomeia-a), -2` quando o componente não está criado
of_from_datastore (datawindow adw)O mesmo a partir das linhas de um DataWindow: a árvore escreve nesse DataWindow (ib_write_back), o que o utilizador vê ao lado. Os seus dados são partilhados com um DataStore de passagem: uma DataWindow que não os pode partilhar é recusada (-5, com o motivo). Devolve 0 depois de carregado, -5 como acima, -2 quando o componente não está criado
of_from_datastore (datawindowchild adwc)O mesmo a partir das linhas de um DataWindowChild (um DataWindow pendente, um relatório aninhado): a árvore escreve nele. Devolve 0 depois de carregado, -5 como acima, -2 quando o componente não está criado
of_from_datastore (datastore ads, string as_parent_keys)Um lote: as linhas de um DataStore tornam-se os filhos do nó as_parent_keys, o resto da árvore não se move — o que ue_children_needed faz numa só chamada. Um papel resolve-se para cada DataStore: a coluna de of_map(ads, …) para este, senão a de of_map quando a tem, senão a coluna com o nome do papel; ROLE_PARENT nomeia uma linha do mesmo lote (vazio ou desconhecido: o próprio nó). O mesmo DataStore dado de novo sob o mesmo nó substitui o seu lote (os seus handles são libertados), outro acrescenta o seu; of_row de um nó do lote é a sua linha nesse DataStore, e ib_write_back escreve lá. Uma chave já ocupada sob o nó recebe "chave~RowID". Um DataStore por lote: recarregado para outro nó (Reset, Retrieve — o PowerBuilder volta a dar os mesmos RowID), leva as suas linhas para o novo lote, e os nós do lote anterior guardam o que mostram sem linha (of_row 0, uma deslocação pelo código -5, uma escrita recusada com ue_write_back_failed; o carregamento conta stale=N). Para refrescar um lote a partir de outro objeto DataStore, primeiro of_clear_children. Devolve 0 depois de carregado, -5 quando o DataStore não é válido, não tem nenhuma coluna, lhe falta uma coluna nomeada para ele por of_map(ads, …), ou as_parent_keys está vazio (o topo da árvore é of_from_datastore(ads)) ou não é um nó da árvore, -2 quando o componente não está criado
of_from_datastore (datawindow adw, string as_parent_keys)Um lote a partir das linhas de um DataWindow (ver acima). Devolve 0 depois de carregado, -5 como acima, -2 quando o componente não está criado
of_from_datastore (datawindowchild adwc, string as_parent_keys)Um lote a partir das linhas de um DataWindowChild. Devolve 0 depois de carregado, -5 como acima, -2 quando o componente não está criado
of_row_keys (long al_row)O endereço do nó de uma linha do DataStore de of_from_datastore (o principal, não um lote), pelo seu número de linha de hoje: retire o nó (of_remove_node) antes do DeleteRow. "" quando a linha não tem nó (retirado, nunca carregado, não existe tal linha). "" também depois de o DataStore principal ter sido dado de novo como lote, até ao próximo carregamento principal
of_map (string as_role, string as_column)Dá um papel (ROLE_KEY, ROLE_PARENT, ROLE_TEXT…) a uma coluna do DataStore quando o seu nome não o diz: of_map(ROLE_PARENT, "manager_id"). O papel vale para cada DataStore que tem essa coluna: um lote lido de um DataStore que não a tem usa a coluna com o nome do papel, e of_map(ads, …) dá a um DataStore os seus próprios papéis. Antes ou depois de of_from_datastore: depois, as linhas são relidas, e o que foi posto nos nós fica. "" como coluna devolve o papel à coluna que tem o seu nome. Um novo ROLE_KEY ou ROLE_PARENT dá novos endereços: só os handles dos nós cujo endereço mudou são libertados, os outros continuam válidos. Os papéis dados ficam para os of_from_datastore seguintes, mesmo depois de of_clear; só of_reset os esquece. A sua releitura das linhas diz o que teve de corrigir, para todas as fontes, em of_get_last_error. Devolve 0 depois de definido, -5 quando o papel não é uma constante ROLE_ ou a coluna não é do DataStore do último of_from_datastore, -2 quando o componente não está criado
of_map (datastore ads, string as_role, string as_column)Dá um papel a uma coluna só para este DataStore: o lote dos departamentos e o dos empregados de uma mesma árvore nomeiam cada um a sua chave e o seu texto. Vem antes de of_map(as_role, as_column) para este DataStore; "" devolve o papel. Antes ou depois de of_from_datastore: depois, as linhas são relidas, o que foi posto nos nós fica. Devolve 0 depois de definido, -5 quando o DataStore não é válido, o papel não é uma constante ROLE_ ou o DataStore não tem essa coluna, -2 quando o componente não está criado
of_map (datawindow adw, string as_role, string as_column)O mesmo para as linhas de uma DataWindow dada a of_from_datastore. Devolve 0 depois de definido, -5 para um argumento recusado, -2 quando o componente não está criado
of_map (datawindowchild adwc, string as_role, string as_column)O mesmo para as linhas de uma DataWindowChild dada a of_from_datastore. Devolve 0 depois de definido, -5 para um argumento recusado, -2 quando o componente não está criado
of_reload_row (long al_row)Volta a enviar à árvore uma linha do DataStore de of_from_datastore, lida agora: depois de o seu código a ter mudado (SetItem, uma janela de edição). al_row é o número de linha de hoje; o nó segue a linha no lugar: o que lhe foi posto (aberto, desativado, visível, campos, cores) fica, nada é levantado. Uma linha cuja chave ou pai mudou desloca o seu nó (os handles do que se moveu são libertados, os outros continuam válidos); uma linha que a árvore ainda não tem (InsertRow) chega também, no seu lugar entre os irmãos; a linha de um nó retirado por of_remove_node volta. Cada valor é escrito como o carregamento o escreve. Só o DataStore principal é relido, não um lote (volte a dá-lo); numa árvore agrupada, uma linha cujo valor de grupo mudou vai para o seu novo grupo. Depois de o DataStore principal ter sido dado de novo como lote, devolve -5 até ao próximo carregamento principal; uma linha cujo pai ou grupo muda desloca o seu nó no lugar. Devolve 0 depois de enviada, -5 quando nenhum DataStore está ligado, a árvore foi esvaziada por of_clear desde o carregamento, ou a linha não existe, -2 quando o componente não está criado
of_export_csv (string as_path)Escreve a árvore num ficheiro CSV (UTF-8, ponto e vírgula) com a sua hierarquia: o texto de um nó na célula do seu nível, as colunas depois do nível mais profundo, primeiro uma linha de cabeçalho; um número em bruto, com a marca decimal da língua de apresentação. is_export_scope diz quais nós; ue_csv_saved confirma; um caminho relativo é escrito na pasta de arranque da aplicação. Recusado no modo de demonstração. Devolve 0 depois de pedido, -5 quando o caminho está vazio, -2 quando o componente não está criado
of_export_xlsx (string as_path)Escreve a árvore num livro Excel (.xlsx): o texto de um nó na primeira coluna, recuado pelo seu nível e agrupado sob o seu pai (os níveis de destaque do Excel: cada ramo dobra-se com o + / - da margem, até 7 níveis, tudo escrito aberto), as colunas depois, os números continuam números (com o formato da sua coluna quando é uma máscara numérica). is_export_scope diz quais nós; ue_xlsx_saved confirma. Recusado no modo de demonstração. Devolve 0 depois de pedido, -5 quando o caminho está vazio, -2 quando o componente não está criado
of_get_layout ( )O que o utilizador dispôs, em JSON: {"columns":[{"key":"","width":260,"visible":true},…],"sort":{"column":"","dir":"none"},"expanded":["europe"]} — primeiro a coluna da árvore (chave ""), depois cada coluna pela sua ordem com a sua largura (0 = automática) e visibilidade, a ordenação, os nós abertos. A guardar (ficheiro, registo, base de dados) e depois devolver a of_set_layout. Lido em direto. Leva também "sorts" (todas as chaves da ordenação), "selected" (os nós selecionados) e "top" (o nó no topo da vista, nunca píxeis)
of_set_layout (string as_layout_json)Repõe uma disposição lida por of_get_layout ou recebida por ue_layout_changed: larguras, ordem e visibilidade das colunas, ordenação, e que nós estão abertos (os que não nomeia fecham-se). Uma coluna ou um nó que nomeia e que a árvore não contém é ignorado. ue_layout_changed é levantado uma vez quando algo mudou (nem ue_node_toggled nem ue_sort_changed: repõe um estado). Devolve também a seleção (ue_selection_changed se mudou, nada é perguntado) e desloca até ao nó do topo. Um endereço que pede aberto num ramo ainda sem resposta é lembrado: abre-se sozinho quando a resposta do seu ramo o traz (ue_node_toggled, depois ue_layout_changed); ue_selection_changed é levantado uma só vez. As perguntas de ib_veto_selection e ib_veto_toggle não são feitas: repõe um estado, tipicamente no arranque. Um ramo prometido que já contém um nó não é aberto sobre metade do seu conteúdo: pede primeiro ue_children_needed. Devolve 0 depois de aplicado, -5 quando o texto está vazio ou não é um objeto JSON, -2 quando o componente não está criado

Eventos #

EventoAcionado quando
ue_node_clicked (string as_keys)Um nó foi clicado (e selecionado, exceto em SELECT_NONE). Um clique no chevron ou na caixa não o levanta; um nó desativado não levanta nada
ue_node_opened (string as_keys)Um duplo clique num nó, ou Enter: abra o seu editor para ele. Um duplo clique num ramo também o abre ou fecha (ue_node_toggled)
ue_node_rclicked (string as_keys, long al_x, long al_y)Um clique direito num nó (selecionado primeiro, salvo se ue_selection_changing o recusar ou em SELECT_NONE: aja sobre as_keys, nunca sobre of_selected_key), ou a tecla de menu (ou Shift + F10) no nó que tem o foco. al_x, al_y são píxeis de ecrã — o ponto do clique, ou o canto inferior esquerdo do nó para a tecla de menu —, os que um contextmenu recebe: uo_menu.of_show(al_x, al_y); para um menu PowerBuilder, PopMenu(PointerX(), PointerY()) da sua janela
ue_node_toggled (string as_keys, boolean ab_expanded)Um nó abriu-se (ab_expanded = true) ou fechou-se: o seu chevron, um duplo clique, o teclado, ou o seu código (ib_expanded, of_expand_all, of_collapse_all, e o que of_select_node ou of_scroll_to_node abrem); uma abertura feita durante ue_children_needed levanta-o uma só vez; of_expand_to_level, of_clear_children (que fecha) e um ramo que of_set_layout lembrou também o levantam
ue_selection_changed (string as_keys_json)A seleção mudou: um clique, o teclado, o seu código (of_select_node, of_clear_selection), ou nós selecionados que saíram do ecrã (ramo fechado, nó retirado ou escondido, nó ocultado pela pesquisa — o que o contém não é selecionado no seu lugar). as_keys_json é o array JSON dos endereços selecionados, pela ordem da árvore: ["europe/france", "asia"]
ue_node_checked (string as_keys, boolean ab_checked)O utilizador marcou (ab_checked = true) ou desmarcou um nó: a sua caixa, ou Espaço. Com ib_check_cascade, toda a sua subárvore segue, já no lugar quando o evento chega. Uma marca escrita pelo seu código não levanta nada. Uma marca do utilizador salta um nó desativado e a sua subárvore
ue_children_needed (string as_keys)Um ramo prometido por ib_has_children abre-se e ainda não contém os seus filhos: acrescente-os agora (of_add_node); o ramo abre-se com eles no retorno do evento, depois do retorno da linha que o abriu. A promessa vale até esta resposta, mesmo que lá tenha sido acrescentado ou largado um nó; sob uma folha marcada, cada filho acrescentado recebe a sua marca. Não acrescente nada, e a promessa é retirada (o chevron desaparece)
ue_node_editing (string as_keys, string as_text) → booleanCancelável, perguntado antes de um texto escrito pelo utilizador ser guardado, só quando ib_veto_changes = true. Devolver FALSE recusa: o nó mantém o seu texto. Por omissão: TRUE
ue_node_edited (string as_keys, string as_text, string as_old_text)O utilizador renomeou um nó (F2, ou um segundo clique lento com ib_editable). O nó já mostra as_text; as_old_text é o que tinha. Com ib_write_back, o DataStore já está escrito
ue_node_moving (string as_keys, string as_to_parent_keys, long al_position) → booleanCancelável, perguntado antes de um nó se mover (um arrastar ou of_move_node), só quando ib_veto_changes = true. as_to_parent_keys vale "" para o topo, al_position o seu lugar final lá, a partir de 1, limitado aos irmãos — o que ue_node_moved dirá. Um nó que já está no seu lugar não pergunta nada. Devolver FALSE recusa: nada se move, e of_move_node devolve -4. Um of_move_node do mesmo nó feito dentro do evento não volta a ser perguntado: aplica-se, e o of_move_node que fazia a pergunta devolve então -5; outro nó é perguntado normalmente. Por omissão: TRUE
ue_node_moved (string as_keys, string as_old_keys, long al_position)Um nó deslocou-se com a sua subárvore: um arrastar do utilizador ou of_move_node. as_keys é o seu novo endereço, as_old_keys o que tinha, al_position o seu lugar sob o novo pai (a partir de 1). Os handles obtidos no endereço antigo já estão libertados (of_move_node liberta-os de imediato, um arrastar antes deste evento); um handle obtido no novo continua válido
ue_sort_changed (string as_column, string as_dir, string as_sort)A ordenação mudou: um clique num cabeçalho ou of_sort. as_column é a sua primeira chave ("" para o texto dos nós), as_dir a sua direção (uma das constantes SORT_), as_sort a ordenação inteira escrita como o SetSort de um DataWindow a lê ("type A, text D", "" sem ordenação). Retirar a coluna ordenada levanta-o com a chave seguinte da ordenação, SORT_NONE quando era a única
ue_layout_changed (string as_layout_json)A disposição mudou: largura ou ordem de uma coluna, ordenação, um nó aberto ou fechado, ou of_set_layout. as_layout_json é a disposição inteira, como of_get_layout a devolve. Uma largura, um lugar ou uma visibilidade de coluna escritos pelo seu código também o levantam, quando a disposição muda; título, formato, alinhamento, ordenação permitida e total ficam mudos
ue_write_back_failed (string as_keys, string as_col, string as_value, string as_reason)ib_write_back: o DataStore recusou um valor (um tipo que não consegue guardar, uma linha apagada desde o carregamento), ou já não há DataStore (as_reason = no DataStore is bound). O nó voltou (as_keys é o endereço que tem de novo); o evento do gesto não é levantado. as_reason diz também quando o lote do nó foi recarregado para outro nó, ou quando a coluna da marca tem valores que não são nem um sim nem um não
ue_image_failed (string as_keys, string as_reason)A imagem de um nó não pôde ser mostrada: as_reason vale REASON_INSECURE (um endereço http://), REASON_UNC (um caminho de rede vindo de uma coluna de DataStore) ou REASON_NOT_FOUND (ficheiro não encontrado). Dito uma vez por nó e por imagem
ue_selection_changing (string as_from_keys_json, string as_keys_json) → booleanCancelável, perguntado antes de o utilizador escolher outra seleção (um clique, o teclado, F3) e antes de of_select_node, of_clear_selection, of_search_next / of_search_prev, só quando ib_veto_selection = true. as_from_keys_json é a seleção atual, as_keys_json a pedida (arrays JSON de endereços). Devolver FALSE recusa: nada se move, nem sequer o foco do teclado, e o método devolve -4. O que sai da seleção por consequência (ramo fechado, remoção, nó escondido, pesquisa) não é perguntado. of_select_nodes pergunta uma vez para toda a seleção. Para levar o utilizador para outro lado, selecione durante o evento e depois devolva FALSE: uma seleção feita durante o evento não volta a ser perguntada. Por omissão: TRUE
ue_node_toggling (string as_keys, boolean ab_expanding) → booleanCancelável, perguntado antes de um nó se abrir (ab_expanding = true) ou fechar, só quando ib_veto_toggle = true: um gesto (chevron, duplo clique, teclado, *, a barra de ferramentas, um ramo sob um arrastar) e o seu código (ib_expanded, of_expand_all, of_collapse_all, of_expand_to_level — uma pergunta por nó —, of_select_node e of_scroll_to_node para os nós que abrem). Devolver FALSE recusa: o nó fica como está, e um método devolve -4. Os irmãos que ib_single_expand fecha não são perguntados. Por omissão: TRUE. of_clear_children fecha sem perguntar
ue_delete_requested (string as_keys_json)O utilizador premiu Delete: as_keys_json é o array JSON dos nós selecionados (em SELECT_NONE, o do foco; sem seleção, caso contrário, nada é levantado), nem desativados nem só de leitura. A árvore não retira nada: chame of_remove_node para o que a sua aplicação apaga
ue_copy (string as_tsv)O utilizador premiu Ctrl+C (ou Ctrl+Insert): as_tsv contém os nós selecionados (em SELECT_NONE, o do foco; sem seleção, caso contrário, nada é levantado) pela ordem da árvore, um por linha, o texto depois de tantas tabulações quanto a sua profundidade, depois as colunas de uma lista em árvore alinhadas (primeiro uma linha de cabeçalho), um número bruto (um ponto, sem agrupamento nem símbolo). A árvore tenta também a área de transferência do navegador, que pode ser recusada a uma página: ClipBoard(as_tsv) para ter a certeza
ue_drop_files (string as_keys, string as_files[])Foram largados ficheiros a partir do Explorador sobre um nó (ib_allow_drop): as_keys é o endereço do nó sob o cursor — vazio para uma largada ao lado dos nós, sobre um nó desativado ou sobre um nó cujo ib_drop_target vale false —, as_files os caminhos completos
ue_state_clicked (string as_keys)O utilizador clicou na imagem de estado de um nó (is_state_image): uma bandeira, um estado que a sua aplicação liga e desliga. O nó não é selecionado, tal como com a sua caixa; um nó desativado não levanta nada. Levantado só para um gesto
ue_csv_saved (string as_path, boolean ab_ok, string as_error)O CSV pedido por of_export_csv foi escrito (ab_ok = true) — ou não: as_error diz porquê (o modo de demonstração, um caminho que não se pode escrever). as_path é o caminho escrito, um relativo resolvido
ue_xlsx_saved (string as_path, boolean ab_ok, string as_error)O livro pedido por of_export_xlsx foi escrito (ab_ok = true) — ou não: as_error diz porquê
ue_drag_enter ( )Um arrastar de ficheiros a partir do Explorador entrou no componente (ib_allow_drop)
ue_drag_leave ( )O arrastar de ficheiros saiu sem largar nada — uma largada levanta só ue_drop_files
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)

Teclado e rato #


Exemplos #

Direitos a marcar #

// The rights of a role : a module, then what it allows
uo_rights.ib_checkboxes = true
uo_rights.of_add_node(/*keys*/ "sales", /*text*/ "Sales")
uo_rights.of_add_node(/*keys*/ "sales/read", /*text*/ "Read orders")
uo_rights.of_add_node(/*keys*/ "sales/write", /*text*/ "Create and change orders")
uo_rights.of_add_node(/*keys*/ "sales/delete", /*text*/ "Delete orders")

// What the role already has ; Sales shows mixed
uo_rights.of_node(/*keys*/ "sales/read").ib_checked = true
uo_rights.of_node(/*keys*/ "sales").ib_expanded = true
// event ue_node_checked of uo_rights : (string as_keys, boolean ab_checked)
// Delete never without write : checking it checks write too
if as_keys = "sales/delete" and ab_checked then this.of_node(/*keys*/ "sales/write").ib_checked = true

Reencontrar a disposição no próximo arranque #

// event ue_layout_changed of uo_tree : (string as_layout_json)
// Widths, order, sort and open nodes, kept for the next start
// (the nodes need STABLE keys : a ROLE_KEY column, never the RowIDs a new Retrieve gives)
SetProfileString("app.ini", "tree", "layout", as_layout_json)
// Local variables
string ls_layout

// After the tree is filled : the layout of the last time, if there is one
ls_layout = ProfileString("app.ini", "tree", "layout", "")
if ls_layout <> "" then uo_tree.of_set_layout(/*layout_json*/ ls_layout)

Um menu sobre um nó #

// The entries of the menu, once : uo_menu is a contextmenu of the window, and
// is_menu_keys a string instance variable that keeps the node right-clicked
uo_menu.of_add_item(/*keys*/ "expand", /*text*/ "Expand")
uo_menu.of_add_item(/*keys*/ "delete", /*text*/ "Delete")
// event ue_node_rclicked of uo_tree : (string as_keys, long al_x, long al_y)
// The node clicked is kept : the selection may have stayed elsewhere (a veto that
// refused it, SELECT_NONE). The menu opens where the user clicked
is_menu_keys = as_keys
uo_menu.of_show(/*x*/ al_x, /*y*/ al_y)
// event ue_item_selected of uo_menu : (string as_keys)
// The entry chosen acts on the node right-clicked
choose case as_keys
    case "expand"
        uo_tree.of_node(/*keys*/ is_menu_keys).ib_expanded = true
    case "delete"
        uo_tree.of_remove_node(/*keys*/ is_menu_keys)
end choose

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
is_accessible_name · is_accessible_descriptionO nome e a descrição que um leitor de ecrã diz3.4 Propriedades e eventos opcionais

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