Componentes
A 4D component is a set of 4D methods and forms representing one or more functionalities that can be installed in different applications. For example, you can develop a 4D e-mail component that manages every aspect of sending, receiving and storing e-mails in 4D applications.
Presentation
Definições
- Matrix Project: 4D project used for developing the component. The matrix project is a standard project with no specific attributes. A matrix project forms a single component.
- Host Project: Application project in which a component is installed and used.
- Component: Matrix project, compiled or not, copied into the
Components
folder of the host application and whose contents are used in the host application.
Principles
Creating and installing 4D components is carried out directly from 4D. Basically, components are managed like plug-ins according to the following principles:
- A component consists of a regular 4D project file.
- To install a component, you simply need to copy it into the
Components
folder of the project. You can use aliases or shortcuts. - A project can be both a “matrix” and a “host,” in other words, a matrix project can itself use one or more components. Entretanto um componente não pode usar por si mesmo "subcomponentes".
- A component can call on most of the 4D elements: project methods, project forms, menu bars, choice lists, and so on. Não pode chamar métodos de bancos de dados e triggers.
- Não pode usar tabelas padrão ou arquivos de dados em componentes 4D. Entretanto um componente não pode criar ou usar tabelas, campos e arquivos de dados usando mecanismos de bancos de dados externos. São bancos 4D independentes com as que se trabalha utilizando comandos SQL.
- A host project running in interpreted mode can use either interpreted or compiled components. A host project running in compiled mode cannot use interpreted components. In this case, only compiled components can be used.
Escopo dos comandos de linguagem
Exceto pelos Comandos não utilizáveis, um componente não pode usar qualquer comando da linguagem 4D.
When commands are called from a component, they are executed in the context of the component, except for the EXECUTE METHOD
or EXECUTE FORMULA
command that use the context of the method specified by the command. Also note that the read commands of the “Users and Groups” theme can be used from a component but will read the users and groups of the host project (a component does not have its own users and groups).
The SET DATABASE PARAMETER
and Get database parameter
commands are an exception: their scope is global to the application. When these commands are called from a component, they are applied to the host application project.
Além disso, medidas especificas foram criadas para os comandos Structure file
e Get 4D folder
quando utilizados no marco dos componentes.
The COMPONENT LIST
command can be used to obtain the list of components that are loaded by the host project.
Comandos não utilizáveis
Os comandos abaixo nãoo são compatíveis para seu uso dentro de um componente porque modificam o arquivo de estrutura - que está aberto em apenas leitura. Sua execução em um componente gerará o erro -10511, "O comando NomeComando não pode ser chamado desde um componente":
ON EVENT CALL
Method called on event
SET PICTURE TO LIBRARY
REMOVE PICTURE FROM LIBRARY
SAVE LIST
ARRAY TO LIST
EDIT FORM
CREATE USER FORM
DELETE USER FORM
CHANGE PASSWORD
EDIT ACCESS
Set group properties
Set user properties
DELETE USER
CHANGE LICENSES
BLOB TO USERS
SET PLUGIN ACCESS
Notas:
- O comando
Current form table
devolveNil
quando chamado no contexto de um formulário projeto. Por isso não pode ser usado em um componente. - SQL data definition language commands (
CREATE TABLE
,DROP TABLE
, etc.) cannot be used on the component project. Entretanto são compatíveis com bancos de dados externos (ver o comando SQLCREATE DATABASE
).
Partilhar os métodos de projeto
All the project methods of a matrix project are by definition included in the component (the project is the component), which means that they can be called and executed by the component.
On the other hand, by default these project methods will not be visible, and they can't be called in the host project. In the matrix project, you must explicitly designate the methods that you want to share with the host project. These project methods can be called in the code of the host project (but they cannot be modified in the Method editor of the host project). Estes métodos formam os pontos de entrada no componente.
Conversely, for security reasons, by default a component cannot execute project methods belonging to the host project. In certain cases, you may need to allow a component to access the project methods of your host project. To do this, you must explicitly designate which project methods of the host project you want to make accessible to the components (in the method properties, check the Shared by components and host project box).
Once the project methods of the host projects are available to the components, you can execute a host method from inside a component using the EXECUTE FORMULA
or EXECUTE METHOD
commands. Por exemplo:
// Host Method
component_method("host_method_name")
// component_method
C_TEXT($1)
EXECUTE METHOD($1)
An interpreted host database that contains interpreted components can be compiled or syntax checked if it does not call methods of the interpreted component. Otherwise, a warning dialog box appears when you attempt to launch the compilation or a syntax check and it will not be possible to carry out the operation.
Keep in mind that an interpreted method can call a compiled method, but not the reverse, except via the use of theEXECUTE METHOD
andEXECUTE FORMULA
commands.
Passar variáveis
The local, process and interprocess variables are not shared between components and host projects. The only way to modify component variables from the host project and vice versa is using pointers.
Exemplo usando um array:
//In the host project:
ARRAY INTEGER(MyArray;10)
AMethod(->MyArray)
//In the component, the AMethod project method contains:
APPEND TO ARRAY($1->;2)
Exemplos usando variáveis:
C_TEXT(myvariable)
component_method1(->myvariable)
C_POINTER($p)
$p:=component_method2(...)
Without a pointer, a component can still access the value of a host database variable (but not the variable itself) and vice versa:
//In the host database C_TEXT($input_t)
$input_t:="DoSomething"
component_method($input_t)
// component_method gets "DoSomething" in $1 (but not the $input_t variable)
When you use pointers to allow components and the host project to communicate, you need to take the following specificities into account:
The
Get pointer
command will not return a pointer to a variable of the host project if it is called from a component and vice versa.The component architecture allows the coexistence, within the same interpreted project, of both interpreted and compiled components (conversely, only compiled components can be used in a compiled project). In order to use pointers in this case, you must respect the following principle: the interpreter can unpoint a pointer built in compiled mode; however, in compiled mode, you cannot unpoint a pointer built in interpreted mode. In order to use pointers in this case, you must respect the following principle: the interpreter can unpoint a pointer built in compiled mode; however, in compiled mode, you cannot unpoint a pointer built in interpreted mode.
If component C defines the
myCvar
variable, component I can access the value of this variable by using the pointer->myCvar
.If component I defines the
myIvar
variable, component C cannot access this variable by using the pointer->myIvar
. This syntax causes an execution error.The comparison of pointers using the
RESOLVE POINTER
command is not recommended with components since the principle of partitioning variables allows the coexistence of variables having the same name but with radically different contents in a component and the host project (or another component). The type of the variable can even be different in both contexts. If themyptr1
andmyptr2
pointers each point to a variable, the following comparison will produce an incorrect result:
RESOLVE POINTER(myptr1;vVarName1;vtablenum1;vfieldnum1)
RESOLVE POINTER(myptr2;vVarName2;vtablenum2;vfieldnum2)
If(vVarName1=vVarName2)
//Este teste retorna True mesmo se as variáveis forem diferentes
Neste caso é preciso usar a comparação de ponteiros:
If(myptr1=myptr2) //Este teste retorna False
Error handling
An error-handling method installed by the ON ERR CALL
command only applies to the running application. In the case of an error generated by a component, the ON ERR CALL
error-handling method of the host project is not called, and vice versa.
Access to tables of the host project
Although components cannot use tables, pointers can allow host projects and components to communicate with each other. Por exemplo, aqui está um método que pode ser chamado a partir de um componente:
// chamar a um método componente
methCreateRec(->[PEOPLE];->[PEOPLE]Name;"Julie Andrews")
Dentro do componente, o código do método methCreateRec
:
C_POINTER($1) //Pointer on a table in host project C_POINTER($2) //Pointer on a field in host project C_TEXT($3) // Value to insert
$tablepointer:=$1
$fieldpointer:=$2 CREATE RECORD($tablepointer->)
$fieldpointer->:=$3 SAVE RECORD($tablepointer->)
In the context of a component, 4D assumes that a reference to a table form is a reference to the host table form (as components can't have tables.)
Uso de tabelas e campos
A component cannot use the tables and fields defined in the 4D structure of the matrix project. Mas pode criar e usar bancos de dados externos e então usar suas tabelas e campos de acordo com suas necessidades. Pode criar e gerenciar bancos de dados externos usando SQL. Mas pode criar e usar bancos de dados externos e então usar suas tabelas e campos de acordo com suas necessidades. Usar um banco externo significa designar temporariamente esse banco de dados como o banco atual, em outras palavras, o banco alvo para as pesquisas SQL executadas por 4D. Pode criar bancos externos usando o comando SQL CREATE DATABASE
.
Exemplo
O código abaixo está incluído em um componente e realiza três ações básicas com um banco externo:
- cria o banco externo se não existir ainda
- adiciona dados ao banco externo,
- lê dados do banco externo.
Cria o banco externo:
<>MyDatabase:=Get 4D folder+"\MyDB" // (Windows) armazena os dados em um diretório autorizado
Begin SQL
CREATE DATABASE IF NOT EXISTS DATAFILE :[<>MyDatabase];
USE DATABASE DATAFILE :[<>MyDatabase];
CREATE TABLE IF NOT EXISTS KEEPIT
(
ID INT32 PRIMARY KEY,
kind VARCHAR,
name VARCHAR,
code TEXT,
sort_order INT32
);
CREATE UNIQUE INDEX id_index ON KEEPIT (ID);
USE DATABASE SQL_INTERNAL;
End SQL
Escrita no banco de dados externa:
$Ptr_1:=$2 // retrieves data from the host project through pointers
$Ptr_2:=$3
$Ptr_3:=$4
$Ptr_4:=$5
$Ptr_5:=$6
Begin SQL
USE DATABASE DATAFILE :[<>MyDatabase];
INSERT INTO KEEPIT
(ID, kind, name, code, sort_order)
VALUES
(:[$Ptr_1], :[$Ptr_2], :[$Ptr_3], :[$Ptr_4], :[$Ptr_5]);
USE DATABASE SQL_INTERNAL;
End SQL
Lendo de um banco externo:
$Ptr_1:=$2 // accesses data of the host project through pointers
$Ptr_2:=$3
$Ptr_3:=$4
$Ptr_4:=$5
$Ptr_5:=$6
Begin SQL
USE DATABASE DATAFILE :[<>MyDatabase];
SELECT ALL ID, kind, name, code, sort_order
FROM KEEPIT
INTO :$Ptr_1, :$Ptr_2, :$Ptr_3, :$Ptr_4, :$Ptr_5;
USE DATABASE SQL_INTERNAL;
End SQL
Uso de formulários
- Só os "formulários de projeto" (formulários que não estejam associados a nenhuma tabela específica) podem ser utilizados em um componente. Só os "formulários de projeto" (formulários que não estejam associados a nenhuma tabela específica) podem ser utilizados em um componente.
- A component can call table forms of the host project. Note que nesse caso é necessário usar ponteiros ao invés de nomes de tabelas entre colchetes [] para especificar os formulários no código do componente.
If a component uses the
ADD RECORD
command, the current Input form of the host project will be displayed, in the context of the host project. Por isso se o formulário incluir variáveis, o componente não terá acesso ao formulário.
- You can publish component forms as subforms in the host projects. Pode publicar formulários componentes como subformulários no banco de dados local Isso significa que pode desenvolver componentes oferecendo objetos gráficos. Por exemplo, Widgets fornecidos por 4D são baseados no uso de subformulários em componentes.
In the context of a component, any referenced project form must belong to the component. For example, inside a component, referencing a host project form using
DIALOG
orOpen form window
will throw an error.
Use of resources
Components can use resources located in the Resources folder of the component.
Mecanismos automáticos são operacionais: os arquivos XLIFF encontrados na pasta Resources de um componene serão carregados por esse componente.
In a host project containing one or more components, each component as well as the host projects has its own “resources string.” Resources are partitioned between the different projects: it is not possible to access the resources of component A from component B or the host project.
Executing initialization code
A component can execute 4D code automatically when opening or closing the host database, for example in order to load and/or save the preferences or user states related to the operation of the host database.
Executing initialization or closing code is done by means of the On Host Database Event
database method.
For security reasons, you must explicitly authorize the execution of the
On Host Database Event
database method in the host database in order to be able to call it. To do this, you must check the Execute "On Host Database Event" method of the components option on the Security page the Settings.
Proteção dos componentes: compilação
By default, all the project methods of a matrix project installed as a component are potentially visible from the host project. Em particular:
- The shared project methods are found on the Methods Page of the Explorer and can be called in the methods of the host project. Seu conteúdo pode ser selecionado e copiado na área de vista prévia do Explorador. Também podem ser vistos no depurador. However, it's not possible to open them in the Method editor or modify them.
- The other project methods of the matrix project do not appear in the Explorer but they too can be viewed in the debugger of the host project.
To protect the project methods of a component effectively, simply compile the matrix project and provide it in the form of a .4dz file. When a compiled matrix project is installed as a component:
- The shared project methods are shown on the Methods Page of the Explorer and can be called in the methods of the host project. However, their contents will not appear in the preview area and in the debugger.
- The other project methods of the matrix project will never appear.