form — u_pbt_form #
← Referência dos componentes · Índice do guia
form é um ecrã de introdução de dados inteiro em um só controlo: campos tipados — texto, número, lista, botões de opção, data, hora, cor, caixa de verificação, palavra-passe, e-mail, texto longo, imagem, etiquetas, estrelas — dispostos em colunas e em secções que se recolhem, cada um com o seu rótulo que sobe para a margem. As regras de cada campo (obrigatório, limites, padrão, máscara…) e os seus erros de negócio verificam-se em conjunto;
of_is_dirtydiz o que mudou desde o carregamento,of_load_row/of_save_rowleem e escrevem uma linha de DataWindow. O seu próprio botão OK chamaof_validate.
▶ Ver ao vivo — Aplicação de demonstração, mosaico Form: a pré-visualização, o código que o produz e esta página, lado a lado.
Em resumo #
| Userobject | u_pbt_form |
| Classes de itens | n_pbt_form_section (secção) → n_pbt_form_field (campo) |
| Serve para | Substituir um ecrã de introdução feito de dezenas de controlos colocados à mão por um formulário com tema que se dispõe sozinho e verifica o que se escreve: ficha de cliente, encomenda, definições, um passo de um assistente |
| Valores | Sempre texto, um a um (of_field(endereço).is_value); todos de uma vez e tipados com of_values; uma linha de DataWindow com of_load_row / of_save_row |
| Opções opt-in | ib_veto_changes |
Início rápido #
// Two columns ; a name at the top, then a section
uo_form.ii_columns = 2
uo_form.of_add_field(/*keys*/ "name", /*label*/ "Name", /*type*/ u_pbt_form.TYPE_STRING, /*value*/ "")
uo_form.of_field(/*keys*/ "name").ib_required = true
uo_form.of_add_section(/*key*/ "order", /*title*/ "Order")
uo_form.of_add_field(/*keys*/ "order/qty", /*label*/ "Quantity", /*type*/ u_pbt_form.TYPE_NUMBER, /*value*/ "1")
uo_form.of_add_field(/*keys*/ "order/due", /*label*/ "Due on", /*type*/ u_pbt_form.TYPE_DATE, /*value*/ "")
// event clicked of cb_ok
// Local variables
n_pbt_json lnv_json
// Every error shown at once, the keyboard on the first
if uo_form.of_validate() > 0 then return
// Valid : read the values, typed, along the same addresses
lnv_json.of_load(/*json*/ uo_form.of_values())
of_save_order(lnv_json.of_get_string(/*path*/ "name"), lnv_json.of_get_number(/*path*/ "order/qty"))
Um endereço por campo #
Um campo designa-se pelo seu endereço: a sua chave sozinha no primeiro nível ("name"), a secção e depois o campo unidos por / dentro de uma secção ("order/qty") — um nível, nunca mais. Uma secção designa-se pela sua chave sozinha. No primeiro nível, uma chave nomeia uma única coisa: uma secção e um campo de cima não a podem partilhar. Os eventos levam o mesmo endereço, o que escreveu; a chave de um campo (o seu último nível) é também o nome da coluna que of_load_row e of_save_row leem.
// A section by its key, a field by its address
uo_form.of_section(/*key*/ "order").ib_collapsed = true
uo_form.of_field(/*keys*/ "order/qty").is_value = "3"
Os tipos de campo #
O tipo escolhe-se uma vez, em of_add_field, e dá o controlo. O valor, esse, é sempre texto — dado, lido, entregue pelos eventos — escrito da mesma forma qualquer que seja a língua do posto. Uma lista, uma data e uma cor abrem-se nas janelas nativas partilhadas por toda a biblioteca, com as cores do tema.
| Constante | Controlo | O valor, em texto |
|---|---|---|
TYPE_STRING | Caixa de texto; uma máscara (is_mask, sintaxe de um EditMask) mostra os seus literais durante a escrita; um botão «…» (ib_ellipsis) abre a sua pesquisa | O texto tal como está; mascarado, sem os seus literais (5551234567) |
TYPE_TEXTAREA | Texto em várias linhas; Enter muda de linha | O texto, com as quebras de linha |
TYPE_NUMBER | Caixa de texto que lê um número na língua de apresentação: o seu separador decimal ou um ponto, o seu agrupamento dos milhares bem formado (1,000 vale mil em inglês, 1.500 mil e quinhentos em alemão, 1 234,5 em francês). Uma entrada ambígua (1,5 em inglês, 1 2) ou que não seja um número fica no ecrã com a mensagem Not a number traduzida, e o valor em vigor não se mexe; Cima / Baixo aumentam-no ou diminuem-no do seu passo (id_step) | Com ponto: "12.5"; "" = vazio. Mantido algarismo a algarismo; 12.50 reescrito por 12.5 não é uma alteração |
TYPE_BOOLEAN | Um interruptor (por omissão) ou uma caixa de verificação (is_boolean_style), com o rótulo ao lado | "true" · "false" |
TYPE_ENUM | Botão que abre a lista partilhada; as suas opções acrescentam-se uma a uma (of_add_option) | O valor da opção escolhida, nunca o seu texto; um valor que nenhuma opção oferece é mantido e mostrado tal como está, como um DataWindow sem tabela de códigos |
TYPE_RADIO | Um botão de opção por opção, lado a lado; as setas passam de um para o outro | O valor da opção escolhida |
TYPE_DATE | Botão que abre o calendário partilhado; a data aparece no formato da língua de apresentação | "yyyy-mm-dd" |
TYPE_TIME | Caixa de texto: 9:5 passa a 09:05; o que não é uma hora de 24 h fica no ecrã com a sua mensagem | "hh:mm" |
TYPE_COLOR | Botão com a amostra da cor, que abre o seletor partilhado | O long RGB escrito em texto: String(RGB(255, 0, 0)) = "255" |
TYPE_PASSWORD | Caixa de texto mascarada | O texto tal como está |
TYPE_EMAIL | Caixa de texto que verifica a forma de um endereço | O texto tal como está |
TYPE_IMAGE | Uma imagem, não uma entrada: nunca validada, nunca em of_values; com ii_rowspan cobre várias linhas (a fotografia de uma ficha) | A sua origem: um ficheiro, ou mono: / tint: seguido de um caminho (com as cores do tema); um endereço http:// é recusado |
TYPE_TAGS | Etiquetas em pastilhas numa caixa: escreve-se uma palavra e depois Enter, uma vírgula ou Tab; Backspace na entrada vazia retira a última, cada pastilha tem a sua cruz, Esquerda / Direita percorrem-nas. As opções do campo (of_add_option) são sugestões filtradas durante a escrita; ib_options_only torna-as as únicas escolhas, ii_max_tags limita o seu número | As etiquetas unidas por uma vírgula e um espaço: "vip, b2b" (o valor da opção para uma sugestão escolhida). A vírgula é o separador: nunca dentro de uma etiqueta; escrita pelo código separa, os espaços à volta desaparecem, a mesma etiqueta duas vezes (sem distinguir maiúsculas) fica uma vez |
TYPE_RATING | Estrelas para clicar, ii_star_count (5 por omissão), meias estrelas com ib_half_stars. Passar o rato pré-visualiza sem mover nada; um clique no valor atual apaga-o. No teclado: setas, Home / End, um algarismo, 0 ou Delete. Uma estrela cheia usa o destaque do componente | O número de estrelas: "4", "3.5"; "" = sem classificação (0 também). Escrito pelo código, arredondado ao passo e mantido dentro das estrelas; um texto ou um negativo é recusado |
A validação #
Cada campo leva as suas regras: ib_required (uma caixa obrigatória tem de estar assinalada), is_min / is_max (um número, uma data, uma hora), ii_max_length, is_pattern (uma expressão regular que o valor inteiro deve seguir), is_mask (uma máscara preenchida), is_match (igual a outro campo), e a forma de um e-mail, de um número ou de uma hora. A sua aplicação acrescenta os seus erros de negócio (is_error: já existe), que ficam até o utilizador alterar o campo. Nada aparece a vermelho enquanto o utilizador não tiver saído de um campo: um formulário novo não está a vermelho. of_is_valid e of_invalid_keys respondem sem mostrar nada; of_validate mostra tudo de uma vez e põe o teclado no primeiro campo com erro. Um campo oculto, desativado ou só de leitura não é julgado pelas suas regras: o utilizador não o poderia corrigir.
// A customer code : two capital letters, then four digits
uo_form.of_field(/*keys*/ "code").is_pattern = "[A-Z]{2}[0-9]{4}"
uo_form.of_field(/*keys*/ "code").is_pattern_message = "Two capital letters, then four digits"
// A rule only your database knows
if of_email_taken(uo_form.of_field(/*keys*/ "email").is_value) then
uo_form.of_field(/*keys*/ "email").is_error = "Already used by another customer"
end if
Propriedades #
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
ii_columns | integer | 1 | Número de colunas, de 1 a 12 (um valor fora dos limites é trazido para dentro). Cada secção acompanha. Um campo abrange mais com ii_colspan, começa numa coluna dada com ii_col, cobre várias linhas com ii_rowspan; os outros campos preenchem as células livres |
ib_readonly | boolean | false | O formulário inteiro só de leitura: cada valor lê-se, nenhum se altera — uma ficha que se consulta. O seu código pode continuar a escrever os valores |
ib_veto_changes | boolean | false | Opt-in: perguntar antes de escrever um valor do utilizador (levanta ue_value_changing, que pode recusar: o campo volta a mostrar o valor anterior). Um valor escrito pelo seu código nunca pergunta |
is_theme_style | string | "" | Estilo visual do componente (constantes THEME_STYLE_*); vazio = o da aplicação, seguido a cada mudança |
is_theme_mode | string | "" | Variante clara ou escura (constantes THEME_MODE_*); vazio = a da aplicação, seguida a cada mudança |
il_theme_accent | long | -1 | Cor de destaque deste componente (-1 = destaque da aplicação, ou o do tema) |
is_tooltip | string | "" | Tooltip simples apresentado ao passar sobre o componente |
is_super_tooltip_title | string | "" | Título do tooltip enriquecido (prevalece sobre is_tooltip) |
is_super_tooltip_text | string | "" | Texto do tooltip enriquecido (aceita marcação enriquecida) |
is_super_tooltip_image | string | "" | Imagem do tooltip enriquecido |
Propriedades de uma secção — n_pbt_form_section #
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
is_title | string | "" | Título do cabeçalho. Aceita o texto formatado com etiquetas. Vazio, o cabeçalho mostra a chave |
ib_collapsed | boolean | false | true recolhe a secção: o seu cabeçalho fica, os seus campos escondem-se — mantêm os seus valores e continuam julgados. Segue-se ue_section_toggled, como num clique no cabeçalho. Lida em direto |
ib_visible | boolean | true | false retira a secção, e todos os seus campos, do formulário; mantêm os seus valores (of_values continua a devolvê-los) e não são julgados |
is_tooltip | string | "" | Tooltip simples apresentado ao passar sobre o item |
is_super_tooltip_title | string | "" | Título do tooltip enriquecido do item (prevalece sobre is_tooltip) |
is_super_tooltip_text | string | "" | Texto do tooltip enriquecido do item (aceita marcação enriquecida) |
is_super_tooltip_image | string | "" | Imagem do tooltip enriquecido do item |
il_accent | long | -1 | Destaque do cabeçalho da secção: o traço sob o seu título usa-o (-1 = o do componente). Os seus campos mantêm o seu |
il_back_color | long | -1 | Fundo do cabeçalho da secção, em RGB(r,g,b) (-1 = o que o tema dá) |
il_text_color | long | -1 | Cor do texto do cabeçalho da secção (-1 = o que o tema dá) |
il_back_color_hover | long | -1 | Fundo do cabeçalho da secção sob o ponteiro (-1 = o que o tema dá) |
il_text_color_hover | long | -1 | Cor do texto do cabeçalho da secção sob o ponteiro (-1 = o que o tema dá) |
Propriedades de um campo — n_pbt_form_field #
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
is_value | string | "" | O valor, em texto (ver os tipos). Escrevê-lo não levanta nada, como SetItem; lê-lo dá o valor atual, seja quem for que o escreveu — o que está a ser escrito conta. Um valor que o tipo não pode conter (uma data que não existe, um texto num número) é recusado: o anterior fica e of_get_last_error diz porquê |
is_label | string | "" | O rótulo, no campo: sobe para a margem quando o campo tem um valor ou o teclado. Aceita o texto formatado com etiquetas. Uma estrela segue o rótulo de um campo obrigatório. Vazio, a chave |
is_placeholder | string | "" | Uma indicação num campo de texto vazio enquanto tem o teclado |
is_help | string | "" | Uma linha de ajuda sob o campo (texto formatado com etiquetas); esconde-se enquanto um erro ocupa o seu lugar |
is_error | string | "" | Um erro de negócio da sua aplicação (já existe): mostrado de imediato, o formulário inválido, até o utilizador alterar o campo ou of_clear_errors; "" apaga-o. Lido, dá a mensagem que o campo mostra — ou mostrará quando o utilizador sair dele: o erro de negócio, senão o das suas regras, "" se for válido. Num campo que o utilizador não pode alcançar (oculto, desativado) é mantido e relê-se, mas não conta: o formulário continua válido até o campo voltar |
is_min | string | "" | O menor valor aceite para um número (com ponto), uma data (yyyy-mm-dd) ou uma hora (hh:mm); a mensagem diz Minimum e o limite. Um limite que o tipo não lê é ignorado; "" = nenhum — para um número, o extremo inferior da SpinRange da sua coluna de DataWindow (of_load_row). Lido, dá o limite em vigor |
is_max | string | "" | O maior valor aceite, lido como is_min; a mensagem diz Maximum e o limite |
is_pattern | string | "" | Uma expressão regular (sintaxe JavaScript) que o valor inteiro deve seguir: [A-Z]{2}[0-9]{4} aceita AB1234, não xAB1234. Um valor vazio é deixado a ib_required |
is_pattern_message | string | "" | A mensagem quando is_pattern falha; vazio: Invalid format, traduzida |
is_mask | string | "" | Uma máscara de introdução. Num TYPE_STRING, a sintaxe de um EditMask do PowerBuilder: # um algarismo, ! qualquer carácter em maiúscula, ^ qualquer carácter em minúscula, a uma letra ou um algarismo, X qualquer carácter, o resto escrito para o utilizador enquanto escreve ((###) ###-####); o cursor fica depois do que foi escrito. O valor só mantém o que foi escrito nas posições, como um EditMask (5551234567, pronto para uma coluna de algarismos); um valor do código é o valor em bruto, sem os seus literais (312345678 sob +33 # ## ## ## ##), os literais iniciais escrevem-se assim que o campo recebe o teclado, um valor que não preenche todas as posições é Incomplete, e pôr uma máscara depois de um valor não muda nada do que o utilizador fez. Depois de of_load_row, uma máscara vazia usa o EditMask da coluna. Num TYPE_NUMBER: uma máscara numérica na sintaxe do PowerBuilder (EditMask, formato DataWindow): # um algarismo opcional, 0 um algarismo obrigatório, , o agrupamento, . o separador decimal, % o número mostrado vezes 100, literais ($, um texto entre aspas, \x) e secções positivo;negativo ("$#,##0;($#,##0)"). A vírgula e o ponto designam os separadores da língua de apresentação. Durante a escrita, o agrupamento aparece à medida que chegam os algarismos, as casas decimais ficam limitadas à máscara, as letras são recusadas, o cursor mantém o seu lugar entre os algarismos e um número colado é lido na língua de apresentação; ao sair do campo a máscara completa (12 passa a 12,00). O valor mantém o número tal como o código o escreve ("1234.5"), sem agrupamento nem símbolo. Um limite inferior (is_min) de 0 ou mais recusa o sinal menos; os limites aplicam-se ao sair do campo, e a sua mensagem mostra-os através da máscara; vazio num TYPE_NUMBER (por omissão): o campo escreve-se segundo o seu is_format sem os seus literais ($#,##0.00 escreve-se #,##0.00, #,##0 "px" escreve-se #,##0; um % fica, é uma escala) |
is_format | string | "" | Um TYPE_NUMBER: o seu formato de apresentação, como o número se mostra enquanto o campo não tem o teclado — a mesma sintaxe de is_mask, com os seus literais: #,##0 "px" mostra 575 px, $#,##0.00;($#,##0.00) um preço, 0.0% uma taxa (0,125 mostra 12,5%). Quando o campo recebe o teclado, o seu texto passa a ser o de is_mask (575), o cursor mantendo o seu lugar entre os algarismos; ao sair volta o texto de apresentação. A troca nunca altera o valor e não levanta nada: ue_value_changed só relata o que o utilizador escreveu, o número nu. Vazio: o campo mostra o seu is_mask |
is_boolean_style | string | "switch" | Um TYPE_BOOLEAN: como é desenhado. BOOLEAN_SWITCH (por omissão): um interruptor, uma pista e um círculo que desliza para o fim, na cor de destaque do componente, quando está ligado — uma definição ligado / desligado. BOOLEAN_CHECKBOX: a caixa de verificação clássica — uma aceitação, uma escolha entre opções. Ambos respondem a Espaço e a um clique no rótulo, dão o mesmo valor e os mesmos eventos; desativados ou só de leitura continuam legíveis. O círculo desliza num quarto de segundo, nada quando o Windows pede menos animações; numa língua escrita da direita para a esquerda desliza para a esquerda |
ii_max_tags | integer | 0 | Um TYPE_TAGS: o número máximo de etiquetas (0 = sem limite). Uma a mais escrita pelo utilizador é recusada: fica na entrada com a mensagem At most N; uma lista mais longa escrita pelo código é mantida, e o campo fica inválido (of_is_valid, is_error) — mostrado depois de o campo ser tocado ou após of_validate, nunca logo |
ib_options_only | boolean | false | Um TYPE_TAGS: true limita as suas etiquetas às opções do campo (of_add_option) — um texto que não nomeia nenhuma (pelo seu texto ou valor, sem maiúsculas nem acentos) é recusado com Not in the list. false: qualquer texto é uma etiqueta, as opções são só sugestões |
ii_star_count | integer | 5 | Um TYPE_RATING: o número de estrelas, de 1 a 10 (um número fora é trazido para dentro). O valor atual fica dentro delas, sem evento: definir o número antes de um valor acima de cinco |
ib_half_stars | boolean | false | Um TYPE_RATING: true permite meias estrelas — a primeira metade da estrela sob o ponteiro (no sentido de leitura), Esquerda / Direita de meia estrela — e o valor escreve-se "3.5". Desligado, o valor atual é arredondado a uma estrela inteira, sem evento: ligá-lo antes de um meio valor |
is_match | string | "" | O endereço de outro campo ao qual este deve ser igual — repetir uma palavra-passe, um e-mail. A mensagem acompanha cada alteração de um ou de outro |
is_prefix | string | "" | Um texto curto no campo, antes do valor (um símbolo de moeda); não faz parte do valor |
is_suffix | string | "" | Um texto curto no campo, depois do valor (uma unidade); não faz parte do valor |
ii_max_length | integer | 0 | O texto mais longo aceite (0 = sem limite) por um TYPE_STRING, TYPE_TEXTAREA, TYPE_PASSWORD ou TYPE_EMAIL — um número ou uma hora não tem comprimento, ignorado; 0 usa o Limit da sua coluna de DataWindow (of_load_row), lido dá o comprimento em vigor: a escrita para aí, um contador aparece sob um campo de texto; um valor mais longo escrito pelo código é Too long. Num TYPE_TAGS: a etiqueta mais longa — uma colagem de várias etiquetas nunca é cortada, cada uma é julgada |
ii_colspan | integer | 1 | Quantas colunas o campo abrange (no máximo ii_columns); -1 = toda a largura |
ii_rowspan | integer | 1 | Quantas linhas o campo cobre — uma imagem ao lado de vários campos; os seguintes preenchem as células livres ao lado |
ii_col | integer | 0 | A coluna onde o campo começa, a partir de 1; 0 = onde o fluxo o coloca. A tecla Tab segue a ordem do ecrã — primeiro os campos de cima, depois cada secção —, qualquer que seja a coluna |
ib_required | boolean | false | O campo tem de ser preenchido — uma caixa tem de estar assinalada (uma caixa Aceito), um campo de etiquetas conter uma, uma classificação ter uma estrela. Uma estrela segue o seu rótulo; o erro Required aparece quando o utilizador sai do campo ou em of_validate. Uma coluna cujo estilo de edição diz Required torna-o obrigatório também (of_load_row); lido, dá o estado em vigor |
ib_readonly | boolean | false | Mostra o valor sem o deixar mudar: um texto ainda pode ser selecionado e copiado; uma lista, uma data, uma cor, um interruptor ou botões de opção mantêm o teclado (Tab alcança-os, um leitor de ecrã diz só de leitura) mas não se abrem nem mudam. Não é julgado pelas suas regras; o seu código pode continuar a escrever is_value |
ib_enabled | boolean | true | false desativa o campo: sem teclado (sai da ordem de tabulação), sem clique, não é julgado pelas suas regras |
ib_visible | boolean | true | false retira o campo do formulário; mantém o seu endereço e o seu valor (of_values continua a devolvê-lo) e não é julgado |
is_column | string | "" | A coluna do DataWindow que of_load_row e of_save_row leem e escrevem para este campo; "" (por omissão) = a sua chave, o último nível do seu endereço. Duas secções podem assim ter a mesma chave (billing/town, shipping/town) ligada a duas colunas, e um campo manter uma chave legível para uma coluna chamada cust_nm |
id_step | double | 0 | Um TYPE_NUMBER: o que Cima / Baixo (e os seus botões, ib_spin) acrescentam ou retiram, mantido entre is_min e is_max; 0 (por omissão) = o SpinIncr da sua coluna de DataWindow (of_load_row), senão 1. Um passo é um gesto do utilizador: ue_value_changed é levantado (e ue_value_changing colocado antes com ib_veto_changes). Um campo vazio parte de is_min, senão de 0; um passo negativo é recusado |
ib_ellipsis | boolean | false | Um campo de texto (TYPE_STRING, TYPE_NUMBER, TYPE_EMAIL…): true mostra um botão … no seu fim — a sua pesquisa, um cliente, um artigo. Um clique nele, ou Ctrl+Enter no campo, levanta ue_ellipsis_clicked; fica fora da ordem de Tab. Funciona também num campo só de leitura (um valor escolhido só pela pesquisa), nunca num desativado |
ib_spin | boolean | false | Um TYPE_NUMBER: true mostra dois pequenos botões no seu fim, cima e baixo, que acrescentam ou retiram id_step entre is_min e is_max — um gesto do utilizador (ue_value_changed). A roda do rato também o faz enquanto o campo tem o teclado; os botões ficam fora da ordem de Tab (Cima / Baixo no campo fazem o mesmo) e escondem-se num campo só de leitura. Uma coluna cujo EditMask diz Spin dá-os por of_load_row, com o seu SpinIncr como passo e a sua SpinRange como limites. Ignorado pelos outros tipos; lido, dá o estado em vigor |
of_type ( ) → string | — | — | O tipo dado a of_add_field (uma constante TYPE_*). Só de leitura: um tipo escolhe-se uma vez |
of_is_dirty ( ) → boolean | — | — | TRUE quando este campo difere da sua referência (ver of_is_dirty do formulário) |
of_is_valid ( ) → boolean | — | — | TRUE quando este campo não tem nenhum erro; is_error diz qual |
is_tooltip | string | "" | Tooltip simples apresentado ao passar sobre o item |
is_super_tooltip_title | string | "" | Título do tooltip enriquecido do item (prevalece sobre is_tooltip) |
is_super_tooltip_text | string | "" | Texto do tooltip enriquecido do item (aceita marcação enriquecida) |
is_super_tooltip_image | string | "" | Imagem do tooltip enriquecido do item |
il_accent | long | -1 | Destaque do campo: a sua margem usa-o quando tem o teclado, e o seu rótulo depois de subir (-1 = o do componente) |
il_back_color | long | -1 | Fundo do campo, em RGB(r,g,b) (-1 = o que o tema dá) |
il_text_color | long | -1 | Cor do texto do campo (-1 = o que o tema dá) |
il_back_color_hover | long | -1 | Fundo do campo sob o ponteiro (-1 = o que o tema dá) |
il_text_color_hover | long | -1 | Cor do texto do campo sob o ponteiro (-1 = o que o tema dá) |
Métodos #
No componente #
| Método | Função | |
|---|---|---|
of_add_section (string as_key, string as_title) → long | Acrescenta uma secção no fim: um cabeçalho que se recolhe, sublinhado com o destaque, sob o qual se acrescentam depois os campos "chave/nome". Um título vazio mostra a chave. Devolve 0 uma vez acrescentada, -5 para uma chave vazia, que contenha / ou ` | , ou já ocupada por uma secção ou um campo de cima, -2` se o componente não estiver criado |
of_add_field (string as_keys, string as_label, string as_type, string as_value) → long | Acrescenta um campo no seu endereço, no fim do que o contém: a sua secção ou o topo do formulário. as_type é uma constante TYPE_*, as_value o seu valor em texto (a origem de uma imagem). Devolve 0 uma vez acrescentado, -5 para um endereço já ocupado (um campo, ou uma secção no primeiro nível), um nível vazio, mais de dois níveis, uma secção nunca acrescentada, uma chave que contenha ` | , um tipo desconhecido ou um valor que o tipo não pode conter (of_get_last_error diz porquê), -2` se o componente não estiver criado |
of_add_option (string as_keys, string as_value, string as_text) → long | Acrescenta uma opção, no fim, a uma lista TYPE_ENUM, a botões TYPE_RADIO ou às sugestões de um TYPE_TAGS: as_value é o que o campo contém (e o que ue_value_changed dá), as_text o que o utilizador lê, como texto simples ("" mostra o valor). Devolve 0 uma vez acrescentada, -5 para um endereço que não seja uma lista, botões de opção nem etiquetas, um valor já oferecido, um valor que contenha ` | ou / (of_keys_at junta-o ao endereço do campo) — e para etiquetas um valor vazio ou com uma vírgula —, -2` se o componente não estiver criado |
of_remove_option (string as_keys, string as_value) → long | Retira uma opção de uma lista, de botões de opção ou de etiquetas, pelo seu valor; o valor do campo fica como está. Devolve 0 uma vez retirada, -5 para um endereço que não seja uma lista, botões de opção nem etiquetas, ou um valor que não oferece, -2 se o componente não estiver criado | |
of_clear_options (string as_keys) → long | Retira todas as opções de uma lista, de botões de opção ou de etiquetas, para carregar outra lista sem perder o campo, o seu handle nem o seu estado; o seu valor fica como está. Devolve 0 uma vez limpa, -5 para um endereço que não seja uma lista, botões de opção nem etiquetas, -2 se o componente não estiver criado | |
of_remove_field (string as_keys) → long | Retira um campo pelo seu endereço, com o seu handle; o resto do formulário mantém o seu estado. Devolve 0 uma vez retirado, -5 para um endereço nunca acrescentado, -2 se o componente não estiver criado | |
of_remove_section (string as_key) → long | Retira uma secção e todos os seus campos, com os seus handles. Devolve 0 uma vez retirada, -5 para uma secção nunca acrescentada, -2 se o componente não estiver criado | |
of_clear ( ) → long | Limpa o formulário: secções, campos e os seus handles. Ao contrário de of_reset, as colunas, a só leitura e a pergunta ficam. Devolve 0 uma vez limpo, -2 se o componente não estiver criado | |
of_section (string as_key) → n_pbt_form_section | O handle de uma secção, pela sua chave: título, recolhimento, visibilidade, cores e dica. Criado no primeiro acesso | |
of_field (string as_keys) → n_pbt_form_field | O handle de um campo, pelo seu endereço: of_field("order/qty").is_value = "3". Criado no primeiro acesso | |
of_values ( ) → string | Todos os valores de uma vez, lidos em direto, num objeto JSON: os campos de cima, depois cada secção como um objeto próprio — ocultos incluídos, imagens excluídas; o que o utilizador ainda escreve é validado primeiro, como faz AcceptText: ue_value_changing colocado com ib_veto_changes, depois ue_value_changed levantado — ambos antes da leitura, nunca a meio: o seu OK lê o que está no ecrã. Tipados: um número é um número (escrito algarismo a algarismo, null se vazio), um booleano um booleano, uma cor o seu long RGB, o resto texto. Lê-se com n_pbt_json, pelo mesmo endereço: lnv_json.of_get_number("order/qty") | |
of_load (string as_json) → long | Carrega um registo: um objeto JSON de valores por endereço — os campos de cima, depois um objeto por secção, ou chaves "order/qty" —, a forma que of_values devolve; números e booleanos podem vir tipados — um número com mais de 15 algarismos é lido algarismo a algarismo, um booleano vale true, false, 1 ou 0 (qualquer outro valor é recusado). Os valores escrevem-se em silêncio e passam a ser a referência de of_is_dirty; os erros mostrados e os erros de negócio apagam-se. Um campo que o objeto não nomeia mantém o seu valor. Devolve 0 uma vez carregado, -5 para um texto que não seja um objeto JSON, ou um valor que o seu campo não pode conter (abc para um número) — nada é escrito então, of_get_last_error nomeia os campos —, -2 se o componente não estiver criado | |
of_load_row (powerobject apo_data, long al_row) → long | Carrega uma linha de um DataWindow, de um DataStore ou de um DataWindowChild: cada campo recebe o valor da sua coluna — a que is_column nomeia, senão a sua chave (o último nível do seu endereço) —, tipado — uma data yyyy-mm-dd, uma hora hh:mm, um número com ponto, um booleano lido pelo valor On de uma coluna caixa de verificação (senão 1, Y, true…). O que o DataWindow diz da coluna vem com ela, relido a cada carregamento: um campo sem rótulo mostra o texto de cabeçalho da sua coluna, um campo sem máscara nem formato usa o seu EditMask e o seu Format (um número $#,##0), uma lista ou botões de opção sem opções próprias oferecem a sua tabela de códigos ou as linhas da sua DropDownDataWindow; um campo sem regras próprias torna-se obrigatório quando o estilo de edição diz Required e limitado ao seu Limit, e um número cujo EditMask diz Spin recebe os seus botões (ib_spin), o seu passo (SpinIncr) e os seus limites (SpinRange). A linha seguinte do mesmo DataWindow não redesenha nenhum campo: o que tem o teclado mantém-no. Como em of_load, os valores passam a ser a referência. Devolve 0 uma vez carregada, -5 para um objeto que não seja um DataWindow, um DataStore nem um DataWindowChild, uma linha que não exista, ou um valor que o seu campo não pode conter (nada muda então: nem um valor nem o que o DataWindow diz), -2 se o componente não estiver criado | |
of_save_row (powerobject apo_data, long al_row) → long | Escreve os valores que o utilizador alterou (desde a referência: of_load_row, of_reset_update) numa linha de um DataWindow, de um DataStore ou de um DataWindowChild: cada campo alterado na sua coluna (is_column, senão a sua chave), por SetItem, tipado para a coluna (data, datetime, hora, número, texto; um booleano como valor On / Off de uma coluna caixa de verificação, 1 / 0 numa coluna numérica, true / false numa coluna de texto; um campo vazio escreve um NULL — um texto vazio, um NULL onde a sua coluna diz NilIsNull, uma cadeia vazia senão, como o DataWindow). Um campo que o utilizador não alterou não é escrito: a linha mantém o seu estado, o seu Update só envia o que mudou. Um TYPE_DATE mantém a hora de uma coluna datetime, um TYPE_TIME a sua data. O que o utilizador ainda escreve é validado primeiro, e ue_value_changed levantado, antes de qualquer leitura; o Update continua a ser seu. Devolve 0 uma vez escrita, -5 para um objeto que não seja um DataWindow, um DataStore nem um DataWindowChild, ou uma linha que não exista, -4 quando uma coluna ficou como estava — um SetItem recusado, um campo cujo tipo a coluna não pode conter (um TYPE_STRING numa coluna de data), ou um valor com casas decimais para uma coluna inteira (3.5 estrelas num long: SetItem arredondá-lo-ia): of_get_last_error nomeia a primeira, os outros campos alterados são escritos na mesma —, -2 se o componente não estiver criado | |
of_is_valid ( ) → boolean | TRUE quando nenhum campo mostrado tem um erro: cada campo obrigatório preenchido (uma caixa obrigatória assinalada), cada regra seguida, nenhum erro de negócio. Lido em direto, sem mostrar nada; um erro de negócio só conta num campo que o utilizador pode alcançar (mostrado e ativo) | |
of_invalid_keys (ref string as_keys[]) → long | Preenche as_keys[] com os endereços dos campos com erro, pela ordem do ecrã, sem mostrar nada, e devolve o seu número (0 = o formulário é válido) | |
of_validate ( ) → long | Mostra todos os erros de uma vez e põe o teclado no primeiro campo com erro (ue_focus_changed) — o que o seu botão OK chama antes de gravar. O teclado sai do botão para o formulário: a tecla seguinte vai para o campo; o que o utilizador ainda escreve é validado primeiro, e um leitor de ecrã lê as mensagens de imediato. Devolve o número de campos com erro (0 = o formulário é válido, nada se mexe), -2 se o componente não estiver criado | |
of_clear_errors ( ) → long | Apaga todos os erros de negócio (is_error escrito pelo seu código); os erros das regras ficam. Devolve 0 uma vez aplicado, -2 se o componente não estiver criado | |
of_is_dirty ( ) → boolean | TRUE quando pelo menos um campo difere da sua referência: o valor dado ao acrescentar, ou o que of_load, of_load_row ou of_reset_update fizeram dele; o que o utilizador ainda escreve é validado primeiro. Um número escrito de outra forma (12.50 por 12.5) é o mesmo valor | |
of_dirty_keys (ref string as_keys[]) → long | Preenche as_keys[] com os endereços dos campos alterados desde a referência, pela ordem do ecrã, e devolve o seu número | |
of_reset_update ( ) → long | Os valores no ecrã passam a ser a referência: of_is_dirty volta a responder FALSE. Chame-o depois de o seu Update ter resultado, como ResetUpdate de um DataWindow. Devolve 0 uma vez aplicado, -2 se o componente não estiver criado | |
of_revert ( ) → long | Repõe cada campo no seu valor de referência, em silêncio, e esconde os erros — o Cancelar do utilizador. Devolve 0 uma vez aplicado, -2 se o componente não estiver criado | |
of_focus_field (string as_keys) → long | Põe o teclado num campo, como um clique: a sua secção recolhida abre-se primeiro (ue_section_toggled), segue-se ue_focus_changed. Devolve 0 uma vez feito, -5 para um endereço nunca acrescentado ou um campo que o utilizador não pode alcançar (oculto, desativado — incluindo o que tinha o teclado —, uma imagem, para lá do limite da demonstração), -2 se o componente não estiver criado | |
of_current_key ( ) → string | Endereço do campo que tem o teclado — ou o teve por último, enquanto o teclado está noutro sítio da janela: "order/qty", "" se ainda nenhum. Sempre o atual, lido do componente; é também o que ue_focus_changed dá | |
of_get_last_error ( ) → string | Porque é que a última escrita foi recusada: um valor que o tipo não pode conter (is_value não tem código de retorno; uma imagem http://, um número infinito como 1e400), um is_pattern que o formulário não sabe ler, um valor que of_load recusou, uma coluna que of_save_row deixou. Vazio quando passou; senão o último erro da biblioteca, como em qualquer componente | |
of_reset ( ) → long | Limpa o formulário e depois repõe cada propriedade do componente no seu valor por omissão: uma coluna, nem só leitura nem pergunta. Devolve 0 uma vez aplicado, -2 se o componente não estiver criado |
Numa secção e num campo #
Uma secção contém campos; uma lista ou botões de opção contêm as suas opções, designadas pelo seu valor. Os três métodos percorrem-nos.
| Método | Função |
|---|---|
of_count ( ) → long | Número de campos da secção, ocultos incluídos; número de opções de uma lista, de botões de opção ou de etiquetas (0 para os outros tipos) |
of_keys_at (long al_index) → string | Endereço do campo de posição al_index (a partir de 1) — "order/qty", reutilizável tal como está em of_field; numa lista, o endereço seguido do valor da opção. "" fora dos limites |
of_has (string as_key) → boolean | A secção contém este campo? A lista oferece este valor? |
Eventos #
| Evento | Acionado quando |
|---|---|
ue_value_changed (string as_keys, string as_value) | O utilizador alterou um valor: uma entrada validada ao sair do campo ou com Enter, uma caixa assinalada, um botão de opção, uma opção, uma data ou uma cor escolhidas (Cima / Baixo percorrem uma lista, Delete limpa uma lista, uma data ou uma cor). as_keys é o endereço do campo, as_value o seu novo valor em texto; já está escrito. Um valor escrito pelo seu código não levanta nada, como SetItem. O que o utilizador ainda escreve quando o seu código lê o formulário (of_values, of_save_row, is_value…) é validado nesse momento, como faz AcceptText: o evento é levantado aí, antes da leitura |
ue_value_changing (string as_keys, string as_value) → boolean | Cancelável, colocado antes de um valor do utilizador ser escrito, e só quando ib_veto_changes = true (desativado por omissão). Devolver FALSE recusa: o campo volta a mostrar o valor anterior, que of_field(as_keys).is_value ainda devolve durante o evento. Devolva TRUE para aceitar. Quando o seu código lê o formulário (of_values, of_validate, is_value…) enquanto o utilizador ainda escreve num campo, a pergunta é colocada de imediato, antes da leitura: a leitura devolve o valor que aceitou |
ue_focus_changed (string as_from_keys, string as_keys) | O campo que tem o teclado mudou: um clique, a tecla Tab, o seu código (of_focus_field, of_validate — uma ordem também o levanta, como SetColumn), ou o campo saiu: retirado, ocultado, limpo (as_keys vale então ""). O teclado que sai do formulário para outro controlo da janela não levanta nada |
ue_section_toggled (string as_key, boolean ab_collapsed) | Uma secção recolheu-se (ab_collapsed = TRUE) ou expandiu-se: um clique no seu cabeçalho (Enter ou Espaço quando tem o teclado), o seu ib_collapsed definido pelo seu código, ou of_focus_field sobre um campo de uma secção recolhida |
ue_ellipsis_clicked (string as_keys) | O botão … de um campo (ib_ellipsis) foi clicado, ou Ctrl+Enter premido no campo: abra a sua pesquisa (um cliente, um artigo) e escreva o que o utilizador escolheu em of_field(as_keys).is_value. O que foi escrito já está validado (ue_value_changing colocado antes com ib_veto_changes, ue_value_changed levantado). Nunca levantado para um campo desativado |
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 #
| Gesto | Efeito |
|---|---|
| Tab, Shift+Tab | Passam de um campo para o outro, pela ordem do ecrã: os campos de cima, depois cada secção, primeiro o seu cabeçalho; um campo desativado é saltado; os botões de opção são uma paragem, as setas escolhem |
| Enter num campo de uma linha | Valida a entrada e depois passa para a janela: o seu botão por omissão (o seu OK) lê um formulário atualizado. Com ib_veto_changes, a página não pergunta nada: a entrada fica pendente, e a leitura do botão por omissão valida-a (ue_value_changing colocado nesse momento) — sem botão por omissão, valida-a a saída do campo |
| Esc | Num campo que o utilizador alterou, repõe o seu valor; senão passa para a janela: o seu botão Cancelar |
| Lista, data, cor: Enter, Espaço, F4, Alt+Baixo | Abrem a janela partilhada (lista, calendário, seletor de cor); Enter fica por aí, não passa para o botão por omissão da janela — nem num cabeçalho de secção, que recolhe ou expande |
| Lista: Cima / Baixo | Opção anterior / seguinte, sem abrir a lista |
| Lista, data, cor: Delete, Backspace | Limpam o valor |
| Etiquetas: Enter, vírgula, Tab | Acrescentam o que foi escrito (Tab mantém o teclado no campo); Backspace na entrada vazia retira a última etiqueta; Esquerda / Direita percorrem as etiquetas, Delete retira a assinalada; Baixo abre as sugestões, Esc fecha-as |
| Estrelas: setas, Home / End, algarismos, Delete | Direita / Cima uma estrela a mais (meia com ib_half_stars), Esquerda / Baixo uma a menos — trocadas numa língua escrita da direita para a esquerda; Home uma estrela, End todas; um algarismo tantas estrelas; 0, Delete ou Backspace apagam a classificação |
| Número: Cima / Baixo | Acrescentam ou retiram o passo do campo (id_step, 1 por omissão), mantido entre is_min e is_max: segue-se ue_value_changed. Com ib_spin, os seus dois botões fazem o mesmo, e a roda enquanto tem o teclado |
| Ctrl+Enter, clique em … | Um campo com ib_ellipsis: valida o que foi escrito e depois levanta ue_ellipsis_clicked — a sua pesquisa |
| Clique num cabeçalho de secção | Recolhe ou expande a secção (ue_section_toggled) |
Exemplos #
Uma ficha de cliente #
// The whole form in one paint, two columns
uo_form.of_set_redraw(/*on*/ false)
uo_form.ii_columns = 2
// Identity : two required names, an e-mail, a phone with its mask
uo_form.of_add_section(/*key*/ "identity", /*title*/ "Identity")
uo_form.of_add_field(/*keys*/ "identity/first_name", /*label*/ "First name", /*type*/ u_pbt_form.TYPE_STRING, /*value*/ "")
uo_form.of_field(/*keys*/ "identity/first_name").ib_required = true
uo_form.of_add_field(/*keys*/ "identity/last_name", /*label*/ "Last name", /*type*/ u_pbt_form.TYPE_STRING, /*value*/ "")
uo_form.of_field(/*keys*/ "identity/last_name").ib_required = true
uo_form.of_add_field(/*keys*/ "identity/email", /*label*/ "E-mail", /*type*/ u_pbt_form.TYPE_EMAIL, /*value*/ "")
uo_form.of_add_field(/*keys*/ "identity/phone", /*label*/ "Phone", /*type*/ u_pbt_form.TYPE_STRING, /*value*/ "")
uo_form.of_field(/*keys*/ "identity/phone").is_mask = "(###) ###-####"
// Account : a credit limit with a bound, shown as a price and typed without the
// dollar sign ; a list ; a switch
uo_form.of_add_section(/*key*/ "account", /*title*/ "Account")
uo_form.of_add_field(/*keys*/ "account/credit_limit", /*label*/ "Credit limit", /*type*/ u_pbt_form.TYPE_NUMBER, /*value*/ "2500")
uo_form.of_field(/*keys*/ "account/credit_limit").is_format = "$#,##0.00"
uo_form.of_field(/*keys*/ "account/credit_limit").is_max = "50000"
uo_form.of_add_field(/*keys*/ "account/country", /*label*/ "Country", /*type*/ u_pbt_form.TYPE_ENUM, /*value*/ "gb")
uo_form.of_add_option(/*keys*/ "account/country", /*value*/ "gb", /*text*/ "United Kingdom")
uo_form.of_add_option(/*keys*/ "account/country", /*value*/ "fr", /*text*/ "France")
uo_form.of_add_field(/*keys*/ "account/vip", /*label*/ "VIP customer", /*type*/ u_pbt_form.TYPE_BOOLEAN, /*value*/ "false")
// Shown at once, the keyboard on the first field
uo_form.of_set_redraw(/*on*/ true)
uo_form.of_focus_field(/*keys*/ "identity/first_name")
Editar uma linha de DataWindow #
A chave de cada campo é o nome da sua coluna: o formulário lê a linha, o utilizador altera-a, o formulário escreve-a.
// The current row of dw_customers fills the form ; nothing is dirty yet
uo_form.of_load_row(/*data*/ dw_customers, /*row*/ dw_customers.GetRow())
// event clicked of cb_save
if uo_form.of_validate() > 0 then return
// Write the values back into the row, then save it
if uo_form.of_save_row(/*data*/ dw_customers, /*row*/ dw_customers.GetRow()) < 0 then
MessageBox("Save", uo_form.of_get_last_error())
return
end if
// Saved : what is on screen is the new reference
if dw_customers.Update() = 1 then
COMMIT USING SQLCA;
uo_form.of_reset_update()
end if
Etiquetas e estrelas #
Uma avaliação de um produto: uma nota em cinco com meias estrelas, e etiquetas livres com sugestões. Os dois valores continuam a ser texto, que of_save_row escreve numa coluna numérica e numa coluna de texto.
// Local variables
string ls_score, ls_tags
// The score : five stars, half stars set BEFORE a half value
uo_form.of_add_field(/*keys*/ "score", /*label*/ "Overall", /*type*/ u_pbt_form.TYPE_RATING, /*value*/ "")
uo_form.of_field(/*keys*/ "score").ib_half_stars = true
uo_form.of_field(/*keys*/ "score").is_value = "3.5"
// Tags : free text, the options are suggestions, five at most
uo_form.of_add_field(/*keys*/ "tags", /*label*/ "Tags", /*type*/ u_pbt_form.TYPE_TAGS, /*value*/ "office, led")
uo_form.of_add_option(/*keys*/ "tags", /*value*/ "eco", /*text*/ "Eco-friendly")
uo_form.of_add_option(/*keys*/ "tags", /*value*/ "usb", /*text*/ "USB powered")
uo_form.of_field(/*keys*/ "tags").ii_max_tags = 5
// Read back : "3.5" and "office, led"
ls_score = uo_form.of_field(/*keys*/ "score").is_value
ls_tags = uo_form.of_field(/*keys*/ "tags").is_value
Avisar antes de perder alterações #
// event closequery of the window
if not uo_form.of_is_dirty() then return 0
// Changes since the load : ask, and put them back if the user gives up
if MessageBox("Customer", "Discard your changes ?", Question!, YesNo!) = 2 then return 1
uo_form.of_revert()
return 0
Boas práticas #
- Um valor é um texto: um número escreve-se com ponto (
"12.5"), um booleano"true"/"false", uma corString(RGB(…)), uma data"yyyy-mm-dd", uma hora"hh:mm"— qualquer que seja a língua do posto. Para valores tipados,of_valuesen_pbt_json. - O seu botão OK decide:
of_validatemostra os erros e devolve o seu número; o formulário não grava nada sozinho. - Dê aos campos o nome das colunas:
of_load_roweof_save_rowfazem então todo o trabalho; senão,is_columnnomeia a coluna de um campo. ib_readonlyem vez deib_enabled = falsepara um valor que o utilizador deve ler: um texto só de leitura seleciona-se e copia-se.- Modo de demonstração: sem chave, o formulário desenha 6 campos, os primeiros mostrados pela ordem do ecrã — um campo de uma secção recolhida também conta, expandi-la não redesenha nada; os outros ficam em memória e em
of_values, mas não são desenhados nem julgados (ver Licença).
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.
| Membros | Função | Detalhado em |
|---|---|---|
of_count · of_keys_at · of_has | Percorrer o que o componente contém | 3.2 Os items |
of_reset | Repor o componente a zero | 3.6 Repor um componente a zero: of_reset() |
of_register_shortcut · of_clear_shortcuts | Atalhos de teclado do componente | 3.5 Os atalhos de teclado |
of_is_created · of_is_ready · of_get_last_error | Se nasceu, se está pronto, o que falhou | 3.7 Diagnóstico |
of_save_as_png · of_save_as_jpg | Exportar a renderização como imagem | 3.8 Exportar a representação como imagem |
of_set_redraw | Agrupar as alterações num único repinte | 3.10 Boas práticas |
of_preload_icons | Ícones mostrados sem atraso | Apresentação instantânea: of_icon |
of_set_translation | Traduzir uma legenda do componente | 5.2 Adaptar uma etiqueta: of_set_translation |
of_focus_webview | Dar o foco ao componente | 6.4 Teclado e focus |
of_print · of_print_to_pdf | Imprimir, ou escrever um PDF | 6.9 Imprimir |
of_set_property · of_get_property · of_component_name | Controlar uma propriedade pelo nome | 3.1 O motor de propriedades |
is_accessible_name · is_accessible_description | O nome e a descrição que um leitor de ecrã diz | 3.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.