Jak programovat komponenty v Gambasu

Úvod

Všechny níže uvedené informace jsou pro Gambas 3.

Gambas komponenty jsou sdílené knihovny napsané v C, C++ nebo přímo v gambasu, a přidávají mu nové třídy.

Komponenty napsana v gambasu je normální gambas projekt s následujícími charakteristickými rysy:
  • Ve vlastnostech projektu, záložce "Volby", bloku "Tento projekt je komponentou" je nastaveno "Ano".

  • Některé třídy z projektů jsou definovány jako exported.

  • Exportované třídy exported tvořící ovladací prvky musí mít deklarované speciální veřejné konstanty. Ty pak sdělí IDE všechny informace potřebné pro řízení prvku.

  • Záložka "Závislosti" v dialogu Vlastnosti projektu obsahuje závislosti nových komponenty.

Mnoho oficiálních komponent gambasu bylo již v Gambasu napsáno, a můžete je používat jako příklad. Zdrojový kód těchto komponent se nachází v adresáři /comp/src ve zdrojovém archívu gambasu.

Zde je seznam těchto komponent: Všimněte si, že některé komponenty psané v C/C++ mají také část psanou v gambasu: Komponenty napsané z části v gambasu jsou umístěny ve zdrojovém adresáři komponenty. Například, gb.qt4 je částečně umistěna v /gb.qt4/src.

Exportované třídy

Účelem Komponenty, je rozšířit interpret Gambasu o nové třídy.

Třídy které chcete poskytovat musí být z projektu exportované, jinak uživatel Vaší komponenty nic neuvidí.

Pro Třída označené jako exportované, musíte přidat klíčové slovo gambasu EXPORT na začátek zdrojového kódu třídy.

Pokud Metody nebo vlastnosti z exportované třídy vrací objekt z jiné třídy deklarované ve Vaší komponentě, pak tato jiná třída by měla být také exportovaná. V opačném případě nemůže uživatel uložit odkaz, pokud používá datový typ objektu.

Pokud exportovaná třída dědí z jiné třídy deklarované ve vaší komponentě, pak i tato třída musí být exportovaná. V opačném případě nastane chyba, když bude chtít interpret komponentu načíst.

Jako dobrý příklad jednoduché komponenty s exportovanou třídou, se podívejte na zdrojový kód komponenty gb.settings a její třídu Settings.

Skryté exportované třídy

Když máte exportovanou nějaké třídy a chcete aby ji uživatel neviděl, můžete ji skrýt tak že před její jméno napíšete znak podtržítka.

Například, podívejte se na zdrojový kód gb.desktop a uvidíte mnoho exportovaných tříd, které nejsou explicitně vidět.

Takto můžete nahradit koncept " tříd" které existují pouze v komponentách napsaných v C/C++.

Kontroly

Kontroly jsou speciální exportované třídy, které se objeví v ovládacích prvcích IDE.

Controls are usually graphical controls that display something and interact with the user. But they can be normal classes too, and display nothing, like the Timer control. In that case, they are called controls.

The GUI components (gb.qt4 or gb.gtk) provide two classes that you should use as parent classes for creating your own controls: UserControl and UserContainer are actually children classes of the Container Třída. This way, you can create new controls or new containers by mixing already existing controls or containers.

For a good example of the use of UserControl, look at the source code of the FileView control. This control embeds one TreeView and one IconView inside a UserControl, displaying one of them according to the kind of view requested by the user.

For a good example of the use of UserContainer, look at the source code of the ListContainer control. This control is a container that allows to create a ListBox whose items are other controls.

Controls need to declare some special hidden constants that are used by the IDE to manage the control:

Konstanta Typ Výchozí hodnota Popis
_IsControl Boolean FALSE This vlastnosti must be set to TRUE, so that an exported class becomes a control.
_IsContainer Boolean FALSE If a control is a container, i.e. if you can put other controls inside in the IDE form editor.
_IsMultiContainer Boolean FALSE If a control is a multiple container, like a TabStrip.
_IsVirtual Boolean FALSE If a control is virtual, i.e. just a normal class that you can put in the form editor, like the Timer or Printer class.
_IsForm Boolean FALSE If a control is actually a form, i.e. the top-level container of all controls of the same family.
_Family String "*" The family of the control, i.e. the kind of top-level objekt where you will be able to put the control. For example: "Form" for a form control, "Report" for a control report, and "*" for a control that can be put anywhere.
_Group String _Family The IDE toolbox tab name where the control will be put. By default, the family name will be used, or the "Special" group if the control has no family.
_Similar String "" A comma separated list of similarity groups. The IDE form editor will allow the control to be replaced by any other control sharing the same similarity groups. A similarity group is normally a control name.
_Properties String "" The list of control properties. See below.
_DefaultEvent String "" The control default Události. See below.
_DefaultSize String "" The control default size. See below.
_DrawWith String "" The real GUI control used for drawing the control inside the form editor. See below
_Arrangement Integer 0 The automatic arrangement if the control is a container and if it arranges its children automatically. See below.

Only the _IsControl and the _Properties constants are mandatory.

These hidden constants are inherited like any other constant. So you don't have to actually declare them in each control, as soon as there is some inheritance relationships between them.

Vlastnosti konstant

This constant is the most important, and is mandatory. It describes all properties that will appear in the IDE vlastnosti sheet for the control, their type, their default value, and other information depending on the property type.

Syntaxe

This special constant is a string having the following form:

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

Each vlastnosti has the following syntax:

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

  • Name is the name of the property. Of course, the property must be declared and implemented in the control source code.

  • Kind is the kind of the property. It can be more accurate than the property datatype. For example, "Color" will mean that the property is an integer, but the IDE property sheet will open a color chooser to define its value. If not defined, the kind of the property is its datatype.

  • Arguments are optional arguments that depends on the value of Kind.

  • Default is the default value of the property. The syntax there depends on the property kind.

The first property can be a star, meaning that the control automatically gets all properties declared in the _Properties constant of its parent Třída. In that case, a property name can start with a minus sign. It means that this property must be removed from the list inherited from the parent class.

Druhy vlastností

Here are the different values of Kind that are supported at the moment:

Property kind Description Arguments
Color An integer that represents a color.

The IDE will popup a color chooser to edit the value of this vlastnosti.
Font A font.

The IDE will popup a font chooser to edit the value of this property.
Font [ :Fixed ]
Use Font:Fixed to allow fixed fonts only.
Path A file path.

The IDE will popup a file chooser to edit the value of this property.
Picture A picture located in the project directory, or a stock icon.

The IDE will popup a picture chooser to edit the value of this property.
Range An integer value with a minimum and a maximum.

The IDE will use a SpinBox control to edit the value of this property.
Range:Minimum;Maximum

The Default value must follow the datatype of the property. For boolean properties, you can specify "True" or "False" as default value.

You must be careful when defining (or not) the Default value of a property.

  • First, if not specified, the taken default value is the default value associated with the property data type (FALSE for a Boolean property, 0 for a numerical one...).

  • Last, the default value must be accurate with the property implementation. Because when a property is set to its default value in the IDE form editor, no code is emitted to initialize the property at run time.

Seznamy konstant

For properties that take their value into a list of predefined constants of the same Třída, you can specify a class instead of a vlastnosti kind, with an optional list of constants.

Here is the syntax:

Property kind Description Arguments
Class name A list of constants.

The IDE will will use a ComboBox control to edit the value of the property, and will fill it with the specified constants.
Class . ( * | Constant1 ; Constant2 ; ... ) [ = Default ]

If a star is used instead of a constant list, then all constants of the specified class will be used.

If specified, the value of Default must be the name of one of the constants. Not its real value!

Příklady

For example, the value of Control._Properties is:
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

It is inherited by all other controls and containers.

Here is the value of ListBox._Properties:
*,List,Mode{Select.*}=Single,Sorted

Jiné speciální konstanty

Konstanta _DefaultEvent (výchozí událost)

This constant is a string that represents the default Události of the control. This default event is used when you click twice on a control in the IDE form editor.

For example:
PUBLIC CONST _DefaultEvent AS String = "Click"

This constant is optional, but you should declare it anyway.

Konstanta _DefaultSize (výchozí velikost)

This constant is a string that represents the default size of the control when it is dropped from the toolbox on the form editor. It is the width and height as multiple of Desktop.Scale, separated by commas.

For example:
PUBLIC CONST _DefaultSize AS String = "36,36"

This constant is optional. If not declared, the IDE will try to do its best.

Konstanta _DrawWith (vykresli s)

This constant is a string that tells the IDE which control should be used for drawing it on the form editor.

By default, controls that are member of gb.qt4, /wiki/comp/gb.qt.ext, gb.form and gb.form.mdi are drawn by being instanciated with the Design vlastnosti set.

If a control is not a member of the components above, then the IDE will draw a frame with the control icon and the control name inside.

By defining this constant, the IDE will not use a DrawingArea, but the control you specified.

For example:
PUBLIC CONST _DrawWith AS String = "TextBox"

Konstanta _Arrangement (zarovnání)

This constant is an integer value that represents the arrangement style forced by the IDE to order children controls inside a container before saving them to disk.

The value is one of the integer value of the Arrange Třída constants.

For example:
PUBLIC CONST _Arrangement AS Integer = 2 ' Arrange.Vertical

You cannot use directly the Arrange constants in the declaration because you are in a constant declaration. This is a limitation of the Gambas language.

That constant is only used if the control is a container, and is optional. If not defined, no arrangement is forced.

Kontrola ikon

Each control must have an icon that will be displayed in the IDE control tool box.

To provide the icons of your Komponenty controls, you must create a /control directory at the root of your project, and put one PNG file for each control icon in it.

In Gambas 3, the control directory must be created inside the .hidden directory. This is the "Project" section in the development environment project treeview.

The name of a control icon must be the Třída name of the control in lower case with the .png extension.

For example:

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

Požadavky komponenty

You can specify the Komponenty requirements in the "Require" tab of the IDE project vlastnosti dialog.

Note that this tab is not visible when a project is not a component.

In this tab, you will list all the dependencies of your component on other components.

The "Features" section has four check-boxes, each one being a feature provided by one or many components. You use this section when your component needs a specific feature, that does not rely on a specific component.

If you really need some specific components, you can select them in the "Components" section of the tab.

The components that you select in the "Components" tab of the vlastnosti dialog have nothing to do with the components you specify in the "Requires" tab.

They are only used when you run the component project from the IDE for debugging purpose.

Ladění, instalace a balení komponenty

Ladění

To debug your Komponenty, you can directly use and run its project as is!

The startup Třída of the project, and the components checked in the "Components" tab of the project vlastnosti dialog will not interfer at all with the behaviour of the component when it will be installed and used by other projects.

Instalace

You can install the Komponenty in your home directory by checking the corresponding option in the "Make executable" dialog.

Once installed there, the component will be visible in the "Components" tab of the project vlastnosti dialog as any other globally installed components.

To uninstall the component from your home directory, just uncheck the option in the "Make executable" dialog, and make the executable again.

Balení

The IDE can make binary packages of your Komponenty, as it does for any other normal projects.

You just will have to define less options: a component has no menu entry, for example.

The binary package will install the component globally, and will be usable as any other official component provided by Gambas.

If you want to distribute your component, you will have to name it by following a precise scheme, so that components packages do not conflict.

The name of your component will have to be: gambas3-/vendor/-/name/

  • gambas3 is the prefix for all gambas components.

  • vendor is the vendor name. For official gambas components, the vendor name is simply gb.

  • name is the name of the component.

Even if the packager wizard allows to insert the package vendor string into the package name, please avoid it.

Put your vendor name inside the component project name, so that it appears in the final component name, and the user sees it.

At the moment, there is a flaw in the packager that does not take into account the component project version to generate the package dependencies. Consequently, you have to set the version of your component project to the current Gambas version!

Závěr

I try to find the easiest way of making components with the IDE. It is not perfect yet, but if you have any comment or question about that, please use the mailing-list!

Note that some things will change for sure before the final release of Gambas 3.

And, of course, if you want to fix or enhance that article, you are welcome.