Como Programar Componentes em Gambas

Introdução

Todas as informações abaixo são para o Gambas 3.

Componentes Gambas são bibliotecas escritas em C, C ++ ou diretamente no Gambas que adicionam novas classes compartilhadas para o interpretador Gambas.

Um componente escrito em Gambas é um projeto normal do Gambas com as seguintes características distintivas:

  • Na aba "Geral" (General) da janela Propriedades do projeto (Project properties), o ComboBox "Tipo de Projeto" (Project type) deve ser definido como "Component".

  • Algumas das classes do projeto são exportadas.

  • As classes exportadas são controles nos quais devemos declarar algumas constantes públicas especiais que vão dizer a IDE todas as informações necessárias para gerenciar o controle.

  • O guia (Requere)"Requires" da caixa de diálogo Propriedades do componente (Component properties) é preenchido com as dependências do novo componente.

Muitos dos componentes Gambas oficiais são escritos no próprio Gambas, e você pode usá-los como exemplos. O código fonte desses componentes está localizado no diretório /comp/src do arquivo fonte do Gambas.

Aqui está a lista destes componentes: Observe que alguns componentes escritos em C / C ++ também têm uma parte escrita em Gambas: O código-fonte da parte escrita em Gambas está localizado no diretório de origem desses componentes. Por exemplo, a parte de gambas gb.qt4 está localizado em /gb.qt4/src.

Classes Exportadas

O objetivo de um componente é proporcionar novas classes para o interpretador Gambas.

As classes que você deseja fornecer devem ser exportada a partir de seu projeto, do contrário, o componente não vai está disponível para o usuário.

Para marcar uma classe como exportada, você só tem que adicionar a palavra-chave EXPORT no início do código fonte do arquivo de classe.

Se um método ou uma propriedade de uma classe exportada retorna um objeto de outra classe declarada em seu componente, então, essa outra classe também deve ser exportada. Caso contrário, o usuário não será capaz de armazenar uma referência sobre ele, a não ser que ele use o tipo de dados Object.

Se uma classe exportada herda outra classe declarada em seu componente, então, esta outra classe também deve ser exportada. Do contrario, você receberá um erro quando o interpretador carregar o componente.

Para um bom exemplo de um componente simples, com apenas uma classes exportada, veja o código fonte de gb.settings e sua classe Settings.

Classes ocultas exportadas

Se você tem que exportar algumas classes e deseja que o usuário não possa vê-las, você pode ocultá-las, apenas iniciando seu nome com o caractere sublinhado.

Por exemplo, no código-fonte gb.desktop você pode ver muitas classes exportadas que não podem ser vistas de maneira explícita.

Com isso, você pode substituir o conceito de "classes virtuais" que existem apenas em componentes escritos em C / C ++.

Controles

Os controles são classes especiais exportadas que aparecerão na caixa de ferramentas de controle da IDE do Gambas.

Os controles são geralmente controles gráficos, que exibem algo e interage com o usuário. Mas eles também podem ser classes normais, e não apresentar nada, como é o caso do controle Timer. Nesse caso, eles são chamados de controles virtuais.

Os componentes GUI (gb.qt4 ou gb.gtk) fornecer duas classes que você deve usar como classes pai para criar seus próprios controles: UserControl e UserContainer são realmente classes filhas da classe Container. Dessa forma, você pode criar novos controles ou novos contêiner combinando controles ou contêiner já existentes.

Para um bom exemplo faremos uso do UserControl, veja o código-fonte do controle FileView. Este Controle Incorpora um TreeView e um IconView dentro de um UserControl, exibindo cada um deles de a acordo com o tipo de visão solicitada pelo usuário.

Para um bom Exemplo faremos uso do UserContainer, veja o código-fonte do controle ListContainer. este controle e um contêiner que permite criar um ListBox cujos itens são outros controles.

Controles precisam da declaração de algumas constantes especiais ocultas que são usadas pela IDE para gerenciar o controle:

Constant Tipo Padrão Descrição
_IsControl Boolean FALSE Esta propriedade deve ser definida como TRUE, para que uma classe exportada torne-se um controle.
_IsContainer Boolean FALSE Se o controle é um contêiner, ou seja, se você pode colocar outros controles dentro dele no editor de formulário da IDE.
_IsMultiContainer Boolean FALSE Se um controle é um contêiner múltiplo, como por exemplo, um TabStrip.
_IsVirtual Boolean FALSE Se um controle é virtual, ou seja, apenas uma classe normal que você pode colocar no editor de formulários, como o Timer ou a classe Printer.
_IsForm Boolean FALSE Se um controle é um formulário, ou seja, é um contêiner de nível superior de todos os controles da mesma família.
_Family String "*" A família do controle, ou seja, o tipo de objeto de nível superior, onde você será capaz de colocar o controle. Por exemplo: "Form" para um controle tipo formulário, "Report" para um controle tipo relatório, e "*" para um controle que pode ser colocado em qualquer lugar.
_Group String _Family O nome da guia na caixa de ferramentas (toolbox ) da IDE onde o controle será colocado. Por padrão, o nome da família é utilizado, ou no grupo "Special" se o controle não tiver família.
_Similar String "" Uma vírgula separa a lista dos grupos similares. O editor de formulário da IDE vai permitir que o controle possa ser substituído por qualquer outro controle compartilhando os mesmos grupos de similaridade. Um grupo de similaridade é normalmente o nome do controle.
_Properties String "" A lista de propriedades do controle. Veja abaixo.
_DefaultEvent String "" O evento padrão do controle. Veja abaixo.
_DefaultSize String "" O tamanho padrão de controle. Veja abaixo.
_DefaultArrangement String "" O arranjo automático, se o controle for um contêiner e organiza seus filhos automaticamente. Veja abaixo.
_DrawWith String "" O controle GUI real usado para desenhar o controle dentro do editor de formulários. Veja abaixo

Apenas as a constantes _IsControl e _Properties são obrigatórias.

Essas constantes ocultas são herdadas como qualquer outra constante. Então você não tem que realmente declará-las em cada controle, logo que há algumas relações de herança entre elas.

A constante _Properties

Esta constante é a mais importante, e é obrigatória. Ele descreve todas as propriedades que serão exibidas na janela de propriedades da IDE para o controle, o seu tipo, o valor padrão, e outras informações, dependendo do tipo da propriedade.

Syntax

Esta constante especial é uma string que tem a seguinte forma:

PUBLIC CONST _Properties AS String = " [ * , ] Property1 , Property2 , ... "

Cada propriedade tem a seguinte sintaxe:

[-] Name [ { Kind [ Arguments ] } ] = Default

  • Name é o nome da propriedade. É claro que a propriedade deve ser declarada e implementada no código fonte do controle.

  • Kind é o tipo da propriedade. Pode ser mais preciso do que o tipo de dados da propriedade. Por exemplo, "Color" significa que a propriedade é um número inteiro, mas a janela de propriedades na IDE vai abrir um seletor de cores para definir o seu valor. Se não for definido, o tipo de propriedade é o seu tipo de dados.

  • Arguments são argumentos opcionais que depende do valor de Kind.

  • Default é o valor padrão da propriedade. A sintaxe depende do tipo da propriedade.

A primeira propriedade pode ser uma estrela, o que significa que o controle recebe automaticamente todas as propriedades declaradas na constante _Properties da sua classe pai. Nesse caso, o nome da propriedade pode começar com um sinal de menos. Isto significa que esta propriedade deve ser removido da lista herdada da classe pai.

Propriedade kinds

Aqui estão os diferentes valores de Kind que são suportados no momento:

Property kind Descrição Argumentos
Color Um inteiro que representa uma cor.

Na IDE vai aparecer um seletor de cores para editar o valor dessa propriedade.
Font A fonte.

Na IDE vai aparecer um seletor de tipo de fonte para editar o valor da propriedade.
Font [ :Fixed ]
Use Font:Fixed para permitir apenas fontes fixas.
Path Um caminho de arquivo.

Na IDE vai aparecer um seletor de arquivos para editar o valor da propriedade.
Picture A imagem localizado no diretório do projeto, ou um ícone de stock.

Na IDE vai aparecer um seletor de imagem para editar o valor da propriedade.
Range Um valor inteiro com um valor mínimo e um valor máximo.

A IDE irá usar um controle SpinBox para editar o valor da propriedade.

Range:Minimum;Maximum

O valor Default deve seguir o tipo de dados da propriedade. Para propriedades boolean por exemplo, você pode especificar "True" ou "False" como valor padrão.

Você deve ter cuidado ao definir (ou não) o valor Default de uma propriedade.

  • Em primeiro lugar, se não for especificado, o valor padrão a ser tomado, então, o valor padrão associado ao tipo de dados da propriedade é usado. (FALSE para uma propriedade Boolean, 0 para um numérica ...).

  • Por último, é necessário implementar o valor padrão com a variável que representa a propriedade em seu código. Porque quando uma propriedade é definida para o valor padrão no editor de formulário da IDE, nenhum código é emitido para inicializar a variável que a representa em tempo de execução.

Constant lists

Para propriedades que obtém o seu valor em uma lista de constantes pré-definidas da mesma classe. Você pode especificar uma classe em vez de um tipo para a propriedade, com uma lista opcional de constantes.

Aqui está a sintaxe:

Property kind Descrição Argumentos
Nome da classe A lista de constantes.

A IDE irá usar um controle ComboBox para editar o valor da propriedade, e preenchê-lo com as constantes especificadas.
Class . ( * | Constant1 ; Constant2 ; ... ) [ = Default ]

Se uma estrela é usada em vez de uma lista de constante, então será utilizado todas as constantes da classe especificada.

Se for especificado, o valor Default deve ser o nome de uma das constantes. Não o seu valor real!

Exemplo

Por exemplo, o valor de Control._Properties é:

X{Position},Y{Position},Width{Dimension},Height{Dimension},Visible=True,Enabled=True,Font{Font},
Background{Color}=-1,Foreground{Color}=-1,Tag,
Mouse{Mouse.Default;Blank;Arrow;Cross;Wait;Text;SizeAll;SizeH;SizeV;SizeN;SizeS;SizeW;SizeE;SizeNWSE;SizeNESW;SplitH;SplitV;Pointing}=Default,
ToolTip,Drop,Expand,Ignore

Será herdado por todos os outros controles e contêineres.

Este é o valor de ListBox._Properties:
*,List,Mode{Select.*}=Single,Sorted

Outras constantes especiais

A constante _DefaultEvent

Esta constante é uma string que representa o evento padrão do controle. Este evento padrão é usado quando você clica duas vezes em um controle no editor de formulário da IDE.

Por exemplo:
PUBLIC CONST _DefaultEvent AS String = "Click"

Esta constante é opcional, mas você deve declará-la mesmo assim.

A constante _DefaultSize

Esta constante é uma string que representa o tamanho padrão do controle quando ele é retirado da caixa de ferramentas do editor de formulários. É a largura e altura como múltiplo de Desktop.Scale, separados por vírgulas.

Por exemplo:
PUBLIC CONST _DefaultSize AS String = "36,36"

Esta constante é opcional. Se não for declarada, a IDE vai tentar fazer o seu melhor possível.

A constante _DrawWith

Esta constante é uma string que indica a IDE que o controle deve ser usado para desenhá-lo no editor de formulários.

Por padrão, os controles que são membro de gb.qt4, /wiki/comp/gb.qt.ext, gb.form e gb.form.mdi - Interface Multi Documento são desenhados por serem instanciado com a propriedades design definida.

Se um controle não é um membro dos componentes acima, então o IDE irá desenhar um quadro com o ícone do controle e o nome do controle dentro.

Ao definir esta constante a IDE não vai usar um DrawingArea, e sim, o controle especificado.

Por exemplo:
PUBLIC CONST _DrawWith AS String = "TextBox"

A constante _DefaultArrangement

Esta constante é um valor string que representa o estilo de arranjo usado pela IDE para ordenar controles filhos dentro de um contêiner antes de salvá-los no disco.

O valor pode ser um das seguinte string:

Constante Arrangement
"H" Arrange.Horizontal
"V" Arrange.Vertical
"R" Arrange.Row
"C" Arrange.Column
"F" Use o valor atual da propriedade Arrange.

Por exemplo:
PUBLIC CONST _DefaultArrangement AS Integer = "V" ' Arrange.Vertical

Essa constante é usado apenas se o controle for um contêiner, e é opcional. Se não for definida, o contêiner não terá nenhum tipo de arranjo.

Ícones do controle

Cada controle deve ter um ícone que será exibido na caixa de ferramentas de controles da IDE.

Para fornecer os ícones dos controles do componente, você deve criar um diretório /control na raiz do seu projeto, e colocar no mesmo um arquivo PNG para cada ícone de cada controle.

Em Gambas 3, o diretório control deve ser criado dentro do diretório .hidden, que é representado na IDE pelo ícone da seção "Project" que fica no painel a esquerdo (que é um treeview) no ambiente de desenvolvimento do projeto.

O nome de um ícone de controle deve ser o nome da classe do controle em minúsculo com a extensão ".png".

Por exemplo:

$ cd gb.db.form
$ cd control
$ ls
databrowser.png  datacombo.png  datacontrol.png  datasource.png  datatree.png  dataview.png

Requisitos do componente

Você pode especificar os requisitos dos componentes na guia "Require" do diálogo Propriedade do componente (Component properties) na IDE.

Neste guia, você irá listar todas as dependências que seu componente tem de outros componentes.

A seção "Recursos" (Features) tem quatro caixas de seleção, cada um sendo um recurso fornecido por um ou mais componentes. Use esta seção quando o seu componente necessitar de uma característica específica, que não depende de um componente específico.

Se você realmente necessitar de alguns componentes específicos, você pode selecioná-los na seção "Components" da guia.

Os componentes que você selecionar na aba "Components" do diálogo de Propriedades do projeto (Project properties) não têm nada a ver com os componentes que você especificar no guia "Requires".

Estes só são usados quando você executar o projeto do componente na IDE para fins de depuração.

Debugging, montar e empacotar o componente

Debugging

Para depurar seu componente, você pode usar e executar o seu projeto diretamente como um projeto normal!

A classe inicial do projeto (Startup class), e os componentes adicionados na guia "Components" do diálogo de Propriedades do projeto, não vai interferir em nada com o comportamento do componente quando ele for instalado e utilizado por outros projetos.

Empacotar

A IDE pode fazer pacotes binários do seu componente, como faz para quaisquer outros projetos normais.

Você só vai ter que definir menos opções: o componente não tem nenhuma entrada de menu, por exemplo. O pacote binário irá instalar o componente de forma global, e poderá ser usado como qualquer outro componente oficial fornecido pelo Gambas.

O nome do pacote binário será gambas3-<vendor>-<project name>, de modo que o nome do seu projeto não deve incluir o nome do fornecedor e o prefixo gambas3.

Por exemplo, para criar o pacote para o componente gambas3-mycompany-foo, o projeto deve ser nomeado foo, e deve "mycompany", mas, será especificado com o nome do fornecedor no assistente empacotador.

No momento, há uma falha no empacotador que não leva em conta a versão do projeto do componente para gerar as dependências do pacote. Consequentemente, você tem que definir a versão do seu projeto componente para a versão atual Gambas!

Conclusão

Eu tento encontrar a maneira mais fácil de fazer componentes com o IDE. Ainda não é perfeito, mas, se você tiver qualquer comentário, dúvida ou problema, por favor use a lista de discussão!