# codeeditor — `u_pbt_codeeditor` #

← Referência dos componentes · Índice do guia

> Editor de código com realce de sintaxe: dez linguagens, números de linha, dobragem de regiões, pesquisa integrada e largada de ficheiros.

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

## Em resumo #

Userobject | `u_pbt_codeeditor`
Classe de items | — (componente sem items)
Serve para | Introduzir ou apresentar código, uma consulta SQL, um ficheiro de configuração: em todos os casos em que um `multilineedit` carece de legibilidade
Opções opt-in | `ib_track_caret`, `ib_allow_drop`, `ib_folding`

## Início rápido #

    // event open da window
    uo_editeur.is_syntax = uo_editeur.SYNTAX_SQL
    uo_editeur.is_text   = "SELECT c.name, SUM(o.amount) AS total~r~n" &
                           + "FROM customer c~r~n" &
                           + "WHERE o.status = 'paid'"

    // Reler o que o utilizador introduziu realmente
    string ls_sql

    ls_sql = uo_editeur.of_get_text()

> `is_text` devolve o mesmo: aquilo que o utilizador escreve chega lá assim que a escrita assenta (event `ue_changed`).

## Linguagens reconhecidas #

`is_syntax` aceita uma destas constantes, ou `SYNTAX_NONE` (cadeia vazia) para texto simples sem realce.

Linguagem | Constante | Outras grafias aceites
--- | --- | ---
PowerScript | `SYNTAX_POWERSCRIPT` | `pb`, `powerbuilder`
SQL | `SYNTAX_SQL` | `tsql`, `plsql`
JavaScript | `SYNTAX_JAVASCRIPT` | `js`, `jsx`
JSON | `SYNTAX_JSON` | `jsonc`
Família C | `SYNTAX_C` · `SYNTAX_CPP` · `SYNTAX_CSHARP` · `SYNTAX_JAVA` | `c++`, `cxx`, `cs`
HTML / XML | `SYNTAX_HTML` · `SYNTAX_XML` | `htm`, `xhtml`, `svg`
CSS | `SYNTAX_CSS` | `scss`, `less`
Python | `SYNTAX_PYTHON` | `py`
YAML | `SYNTAX_YAML` | `yml`
Markdown | `SYNTAX_MARKDOWN` | `md`, `mkd`

As linguagens de uma mesma família partilham o realce (`SYNTAX_JAVA` colore como `SYNTAX_C`, `SYNTAX_XML` como `SYNTAX_HTML`): a constante escolhida documenta a intenção do programador, mas o resultado no ecrã é o mesmo. O valor não distingue maiúsculas de minúsculas e um nome desconhecido recai no texto simples, sem erro.

## Propriedades #

### Conteúdo e linguagem #

Propriedade | Tipo | Predefinição | Função
--- | --- | --- | ---
`is_text` | string | `""` | O código apresentado no editor. Em leitura, devolve o conteúdo vivo, incluindo aquilo que o utilizador escreveu
`is_syntax` | string | `""` | Linguagem de realce: constantes `SYNTAX_*` (ver a tabela acima). `SYNTAX_NONE` = texto simples
`ib_readonly` | boolean | `false` | Editor só de leitura: o utilizador consulta sem poder modificar

### Apresentação #

Propriedade | Tipo | Predefinição | Função
--- | --- | --- | ---
`ib_line_numbers` | boolean | `true` | Mostra ou oculta a calha de números de linha, à esquerda
`ib_current_line` | boolean | `true` | Realça a linha onde se encontra o cursor. Sem realce enquanto `ib_wrap` estiver ativo.
`ib_folding` | boolean | `false` | Opt-in: permite a dobragem das regiões (`#region`, blocos entre chavetas) a partir da calha
`ib_wrap` | boolean | `false` | Muda as linhas longas de linha em vez de deslocar lateralmente
`ii_tab_size` | integer | `4` | Número de colunas ocupadas por uma tabulação
`is_font_family` | string | `""` | Tipo de letra do editor (vazio = tipo de letra monoespaçado do tema)
`ii_font_size` | integer | `0` | Tamanho do tipo de letra em pontos (`0` = tamanho do tema)

### Navegação e interações #

Propriedade | Tipo | Predefinição | Função
--- | --- | --- | ---
`ib_search_enabled` | boolean | `true` | Ativa a barra de pesquisa integrada (Ctrl+F)
`ii_doc_line` | integer | `-1` | Desloca até à linha indicada e seleciona-a (numeração a partir de 1). Sem realce enquanto `ib_wrap` estiver ativo; o deslocamento continua a funcionar.
`ib_track_caret` | boolean | `false` | Opt-in: aciona `ue_caret_changed` em cada deslocação do cursor
`ib_allow_drop` | boolean | `false` | Opt-in: aceita a largada de ficheiros a partir do Explorador do Windows; os caminhos completos chegam através de `ue_drop_files`
`is_theme_style` | string | `fluent` | Estilo visual do componente (constantes `THEME_STYLE_*`)
`is_theme_mode` | string | `light` | Variante clara ou escura (constantes `THEME_MODE_*`)
`il_theme_accent` | long | `-1` | Cor de destaque deste componente (`-1` = destaque 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

## Métodos #

Método | Função
--- | ---
`of_get_text ( )` → string | Devolve o conteúdo vivo: o mesmo valor que `is_text`, para código que prefira uma chamada de método
`of_find (string as_text)` | Abre a barra de pesquisa e realça todas as ocorrências do texto
`of_insert_text (string as_text)` | Insere texto no cursor, exatamente como se o utilizador o tivesse escrito: a seleção atual é substituída e o cursor fica depois da inserção. É o método por detrás de um botão inserir excerto, onde `is_text` deitaria fora o trabalho em curso. Quando o editor tem o foco, a inserção passa pela via de edição do navegador, pelo que Ctrl+Z continua a anulá-la
`of_reset ( )` | Repõe todas as propriedades nos respetivos valores predefinidos e esvazia o editor
`of_set_redraw (boolean)` | Agrupa uma rajada de modificações numa única representação
`of_save_as_png (string)` · `of_save_as_jpg (string)` | Exporta a representação como imagem

## Eventos #

Evento | Acionado quando
--- | ---
`ue_changed (string as_text)` | O utilizador modificou o conteúdo e a escrita estabilizou; `as_text` transporta o novo código completo
`ue_caret_changed (long al_line, long al_col)` | O cursor deslocou-se; linha e coluna contadas a partir de 1 — requer `ib_track_caret = true`
`ue_find_result (long al_count, long al_index)` | Uma pesquisa foi concluída: `al_count` ocorrências encontradas, `al_index` = posição daquela que está destacada
`ue_drop_files (string as_files[])` | Foram largados ficheiros a partir do Windows: caminhos completos, uma entrada por ficheiro. Requer `ib_allow_drop = true`
`ue_drag_enter ( )` | Um arrastamento de ficheiros entra no editor (`ib_allow_drop`)
`ue_drag_leave ( )` | O arrastamento de ficheiros sai do editor
`ue_ready ( )` | O componente terminou o carregamento; tudo o que foi enviado antes foi reproduzido
`ue_runtime_missing ( )` | O runtime WebView2 está ausente: o componente permanece vazio
`ue_bg_color (long al_color)` | O componente calculou a cor de fundo do respetivo tema; o userobject já a adotou (`backcolor`)

## Exemplos #

### Um editor de consultas SQL #

    uo_requete.of_set_redraw(false)

    uo_requete.is_syntax = uo_requete.SYNTAX_SQL
    uo_requete.is_text   = "-- Melhores clientes por volume de negocios recebido~r~n" &
                           + "SELECT c.name, SUM(o.amount) AS total~r~n" &
                           + "FROM customer c~r~n" &
                           + "  INNER JOIN orders o ON o.cust_id = c.id~r~n" &
                           + "WHERE o.status = 'paid'~r~n" &
                           + "GROUP BY c.name~r~n" &
                           + "ORDER BY total DESC"

    uo_requete.of_set_redraw(true)

    // event clicked de cb_executer
    string ls_sql

    ls_sql = uo_requete.of_get_text()     // o que o utilizador introduziu realmente
    of_executer(ls_sql)

### Um visualizador só de leitura #

Ideal para apresentar código gerado, um registo ou um excerto que o utilizador deve ler sem o modificar.

    uo_apercu.is_syntax = uo_apercu.SYNTAX_POWERSCRIPT

    uo_apercu.ib_readonly     = true      // apenas consulta, sem cursor de escrita
    uo_apercu.ib_line_numbers = false     // oculta a calha de numeros
    uo_apercu.ib_current_line = false     // sem realce da linha atual
    uo_apercu.ib_wrap         = true      // muda de linha em vez de deslocar
    uo_apercu.ii_tab_size     = 2         // tabulacoes apresentadas em 2 colunas

    uo_apercu.is_text = of_generer_code()

### Acompanhar a posição do cursor numa barra de estado #

    uo_editeur.ib_track_caret = true       // subscricao explicita: caso contrario nenhum evento

    // event ue_caret_changed de uo_editeur : (long al_line, long al_col)
    uo_statut.of_item("pos").is_text = "Linha " + String(al_line) + ", col. " + String(al_col)

Sem `ib_track_caret`, o cursor não comunica nada: este acionador é de frequência elevada e permanece desligado enquanto não for pedido.

### Pesquisar e ir para uma linha #

    // Abre a barra de pesquisa e realca todas as ocorrencias
    uo_editeur.of_find(/*texto*/ "ll_total")

    // event ue_find_result de uo_editeur : (long al_count, long al_index)
    if al_count = 0 then
        uo_statut.of_item("main").is_text = "Nenhuma ocorrência"
    else
        uo_statut.of_item("main").is_text = String(al_index) + " / " + String(al_count)
    end if

    // Ir diretamente para a linha assinalada por um compilador
    uo_editeur.ii_doc_line = ll_ligne_erreur     // desloca e seleciona a linha

### Abrir um ficheiro largado a partir do Explorador #

    uo_editeur.ib_allow_drop = true

    // event ue_drop_files de uo_editeur : (string as_files[])
    string ls_contenu, ls_ligne
    integer li_fichier

    // as_files[1] transporta o caminho COMPLETO do primeiro ficheiro largado
    li_fichier = FileOpen(as_files[1], StreamMode!, Read!)
    if li_fichier > 0 then
        FileReadEx(li_fichier, ls_contenu)
        FileClose(li_fichier)

        uo_editeur.is_syntax = of_langage_selon_extension(as_files[1])
        uo_editeur.is_text   = ls_contenu
    end if

### Reagir às modificações #

    // event ue_changed de uo_editeur : (string as_text)
    ib_modifie = true
    uo_statut.of_item("main").is_text = String(Len(as_text)) + " caracteres"

O evento só é despoletado depois de a escrita estabilizar: uma introdução contínua não gera um evento por cada tecla.

## Boas práticas #

- Definir sempre `is_syntax` antes de `is_text`: o código é realçado logo na primeira apresentação, sem que se veja um novo realce.
- Para uma apresentação em modo de consulta, a combinação `ib_readonly` + `ib_line_numbers = false` + `ib_wrap` produz um visualizador sóbrio, que deixa de parecer um editor.
- Para recuperar o que foi introduzido, ler `is_text` (ou `of_get_text()`) assim que a escrita assentar, ou usar o parâmetro `as_text` de `ue_changed`.
- `ib_folding` só tem interesse em ficheiros longos e estruturados; deve manter-se desligado para excertos curtos.
- O carregamento de um ficheiro grande deve ser enquadrado por `of_set_redraw(false)` / `of_set_redraw(true)`.
- Chamar `of_reset()` antes de carregar um documento de outra natureza: caso contrário, a linguagem, o tamanho de tabulação ou o modo só de leitura anteriores mantêm-se em vigor.

← Referência dos componentes · Índice do guia