メインコンテンツまでスキップ
バージョン: v20 R4 BETA

コンポーネントの開発

4D のコンポーネントとは、4Dアプリケーションにインストール可能 な、1つ以上の機能を持つ 4D関数やメソッド、フォームの一式です。 たとえば、メールの送受信をおこない、それらを 4D アプリケーションに格納するための機能を持ったコンポーネントを作成できます。

ニーズに合わせて独自の 4Dコンポーネントを開発し、それを非公開とすることができます。 また、作成した コンポーネントを4Dコミュニティで共有 することもできます。

定義

  • マトリクスプロジェクト: コンポーネント開発に使用する4D プロジェクト。 マトリクスプロジェクトは特別な属性を持たない標準のプロジェクトです。 マトリクスプロジェクトはひとつのコンポーネントを構成します。
  • ホストプロジェクト: コンポーネントがインストールされ、それを使用するアプリケーションプロジェクト。
  • コンポーネント: ホストアプリケーションによって使用される目的で、同アプリケーションの Components フォルダーにコピーされたマトリクスプロジェクト (コンパイル済み または ビルド済み)。

基本

4D コンポーネントの作成とインストールは直接 4D を使用しておこないます:

  • コンポーネントをインストールするには、プロジェクトの Components フォルダー にコンポーネントファイルをコピーします。 エイリアスまたはショートカットも使用できます。
  • 言い換えれば、マトリクスプロジェクト自体も1 つ以上のコンポーネントを使用できます。 しかしコンポーネントが "サブコンポーネント" を使用することはできません。
  • コンポーネントは次の 4D の要素を呼び出すことができます: クラス、関数、プロジェクトメソッド、プロジェクトフォーム、メニューバー、選択リストなど。 反面、コンポーネントが呼び出せないものは、データベースメソッドとトリガーです。
  • コンポーネント内でデータストアや標準のテーブル、データファイルを使用することはできません。 しかし、外部データベースのメカニズムを使用すればテーブルやフィールドを作成し、そこにデータを格納したり読み出したりすることができます。 外部データベースは、メインの 4D データベースとは独立して存在し、SQLコマンドでアクセスします。
  • インタープリターモードで動作するホストプロジェクトは、インタープリターまたはコンパイル済みどちらのコンポーネントも使用できます。 コンパイルモードで実行されるホストデータベースでは、インタープリターのコンポーネントを使用できません。 この場合、コンパイル済みコンポーネントのみが利用可能です。

ランゲージコマンドのスコープ

使用できないコマンド を除き、コンポーネントではすべての 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. また、ユーザー&グループテーマの読み出しコマンドはコンポーネントで使用することができますが、読み出されるのはホストプロジェクトのユーザー&グループ情報であることに注意してください (コンポーネントに固有のユーザー&グループはありません)。

The SET DATABASE PARAMETER and Get database parameter commands are an exception: their scope is global to the application. これらのコマンドがコンポーネントから呼び出されると、結果はホストプロジェクトに適用されます。

さらに、Structure fileGet 4D folder コマンドは、コンポーネントで使用するための設定ができるようになっています。

The COMPONENT LIST command can be used to obtain the list of components that are loaded by the host project.

使用できないコマンド

(読み取り専用モードで開かれるため) ストラクチャーファイルを更新する以下のコマンドは、コンポーネントで使用することができません。 コンポーネント中で以下のコマンドを実行すると、-10511, "CommandName コマンドをコンポーネントでコールすることはできません" のエラーが生成されます:

  • 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

注:

  • Current form table コマンドは、プロジェクトフォームのコンテキストで呼び出されると Nil を返します。 ゆえにこのコマンドをコンポーネントで使用することはできません。
  • SQLデータ定義言語のコマンド (CREATE TABLEDROP TABLE等) をコンポーネントのフレームワークで使用することはできません。 ただし、外部データベースの場合は使用することができます (CREATE DATABASE SQL コマンド参照)。

プロジェクトメソッドの共有

マトリクスプロジェクトのすべてのプロジェクトメソッドは 、コンポーネントに含まれます。 つまり、マトリクスプロジェクトをコンポーネント化した後、これらのプロジェクトメソッドは同コンポーネント内で呼び出して実行することができます。

他方、デフォルトでは、これらのプロジェクトメソッドはホストプロジェクトに表示されず、呼び出すこともできません。 マトリクスプロジェクトで、メソッドプロパティダイアログボックスの コンポーネントとホストプロジェクト間で共有 ボックスをチェックすることで、ホストプロジェクトと共有したいメソッドを明示的に設定することができます。

設定することで、共有されたプロジェクトメソッドはホストプロジェクトにおいて呼び出せるようになります (しかしホストプロジェクトのコードエディターで編集することはできません)。 これらのメソッドはコンポーネントの エントリーポイント となります。

セキュリティのため、デフォルトでは、コンポーネントはホストプロジェクトのプロジェクトメソッドを実行することはできません。 特定の場合に、ホストプロジェクトのプロジェクトメソッドにコンポーネントがアクセスできるようにする必要があるかもしれません。 そうするには、ホストプロジェクトのプロジェクトメソッド側で、コンポーネントからのアクセスを可能にするよう明示的に指定しなければなりません。これはメソッドプロパティダイアログボックスの、コンポーネントとホストプロジェクト間で共有 で設定します。

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 command. 例:

// ホストメソッド
component_method("host_method_name")
// component_method
#DECLARE ($param : Text)
EXECUTE METHOD($param)

インタープリターコンポーネントがインストールされたインタープリターホストデータベースは、それがインタープリターコンポーネントのメソッドを呼び出さなければ、コンパイル/シンタックスチェックができます。 そうでない場合、コンパイルまたはシンタックスチェックを実行しようとすると警告ダイアログが表示され、操作を実行することはできません。
一般的に、インタープリターメソッドはコンパイル済みメソッドを呼び出せますが、逆はできません。これをおこなうには EXECUTE METHODEXECUTE FORMULA コマンドを使用します。

クラスや関数の共有

デフォルトでは、ホストプロジェクトの 4Dコードエディターからコンポーネントのクラスと関数を呼び出すことはできません。 コンポーネントのクラスと関数をホストプロジェクトに公開したい場合は、コンポーネント名前空間を宣言する必要があります。 また、コンポーネントのクラスや関数がホストコードエディターでどのように提案されるかをコントロールすることもできます。

コンポーネント名前空間の宣言

コンポーネントのクラスや関数をホストプロジェクトに公開するには、マトリクスプロジェクトの設定の 一般ページにある クラスストア内でのコンポーネント名前空間 オプション に値を入力します。 デフォルトでは、このエリアは空です。つまり、コンポーネントのクラスはコンポーネント外で利用できません。

名前空間 は、同じ名前のクラスや関数を持つ異なるコンポーネントがホストプロジェクトで使用されている場合に、競合が発生しないようにします。 コンポーネント名前空間は、プロパティの命名規則 に準拠する必要があります。

値を入力すると、ホストプロジェクトのコードにおいてユーザークラスストア (cs) 内の cs.<> 名前空間を介して、コンポーネントのクラスと関数が利用可能になることを宣言することになります。 たとえば、getArea() 関数を持つ Rectangle クラスが存在する場合に、コンポーネント名前空間として "eGeometry" を入力すると、このプロジェクトがコンポーネントとしてインストールされると、ホストプロジェクトの開発者は次のように記述することができます:

//in host project
var $rect: cs.eGeometry.Rectangle
$rect:=cs.eGeometry.Rectangle.new(10;20)
$area:=$rect.getArea()
info

コンパイルされた コンポーネントの名前空間は、ホストプロジェクトの コンポーネントメソッドページ にて、コンポーネント名の後に括弧で表示されます。

競合を避けるためには、優れた識別名の使用が推奨されます。 もし、コンポーネントと同じ名前のユーザークラスがすでにプロジェクトに存在していた場合、そのユーザークラスが考慮され、コンポーネントクラスは無視されます。

コンポーネントの ORDAクラスは、ホストプロジェクトでは使用できません。 たとえば、コンポーネントに Employees というデータクラスがある場合、ホストプロジェクトで "cs.Mycomponent.Employee" クラスを使用することはできません。

非表示クラス

アンダースコア ("_") を名前の前に付けることで、コンポーネントのクラスや関数を非表示にすることができます。 コンポーネント名前空間が定義されている 場合、非表示のクラスや関数はコード補完の際に提案されません。

ただし、名前がわかっていれば使用することは可能です。 たとえば、_Rectangle クラスが非表示の場合でも、次のシンタックスは有効です:

$rect:=cs.eGeometry._Rectangle.new(10;20)

非表示のクラス内の、非表示でない関数は、そのクラスを 継承 するクラスでコード補完を使用すると提案されます。 たとえば、あるコンポーネントに _Person クラスを継承した Teacher クラスがある場合、Teacher のコード補完では _Person の非表示でない関数が提案されます。

コンパイル済みコンポーネントのコード補完

開発者に向けてコンポーネントを使いやすくするため、マトリクスプロジェクトの設定で、 一般ページの コンパイル時にコード補完用のシンタックスファイルを生成する オプション をチェックすることができます。

すると、コンパイル時にシンタックスファイル (JSON形式) が自動生成され、そこにコンポーネントのクラス、関数、および 公開メソッド のシンタックスを格納し、コンポーネントプロジェクトの \Resources\ja.lproj フォルダーに配置されます。 4D は、このシンタックスファイルをもとに、コード補完や関数シンタックスなどのコードエディター用のヘルプを生成します。

コンポーネント名前空間 を入力しない場合、シンタックスファイル生成のオプションがチェックされていても、クラスや公開メソッド用のリソースは生成されませ ん。

変数の渡し方

ローカル、プロセス、インタープロセス変数は、コンポーネントとホストプロジェクト間で共有されません。 ホストプロジェクトからコンポーネントの変数を編集、またはその逆をおこなう唯一の方法はポインターを使用することです。

配列を使用した例:

// ホストプロジェクト側:
ARRAY INTEGER(MyArray;10)
AMethod(->MyArray)

// コンポーネント側で AMethod プロジェクトメソッドは以下の通りです:
APPEND TO ARRAY($1->;2)

変数を使用した例:

C_TEXT(myvariable)
component_method1(->myvariable)
C_POINTER($p)
$p:=component_method2(...)

ポインターを使用しない場合でも、コンポーネント側からホストデータベースの (変数そのものではなく) 変数の値にアクセスすること自体は可能ですし、その逆も可能です:

// ホストデータベース内
C_TEXT($input_t)
$input_t:="DoSomething"
component_method($input_t)
// component_method は $1 に "DoSomething" を受け取ります ($input_t 変数を受け取るわけではありません)

ホストプロジェクトとコンポーネント間でポインターを使用して通信をおこなうには、以下の点を考慮する必要があります:

  • Get pointer をコンポーネント内で使用した場合、このコマンドはホストプロジェクトの変数へのポインターを返しません。また逆にこのコマンドをホストプロジェクトで使用した場合も同様です。

  • コンパイル済みプロジェクトでは、コンパイルされたコンポーネントしか使用できませんが、インタープリタープロジェクトの場合には、インタープリターおよびコンパイル済みコンポーネントを同時に使用することができます。 この場合、ポインターの利用は以下の原則を守らなければなりません: インタープリターモードでは、コンパイルモードにおいて作成されたポインターを解釈できます。逆にコンパイルモードでは、インタープリターモードにて作成されたポインターを解釈することはできません。 以下の例でこの原則を説明します: 同じホストプロジェクトにインストールされた 2つのコンポーネント C ( コンパイル済) と I ( インタープリタ) があります:

  • コンポーネントC が定義する変数 myCvar があるとき、コンポーネントI はポインター ->myCvar を使用して変数の値にアクセスすることができます。

  • コンポーネントI が定義する変数 myIvar があるとき、コンポーネントC はポインター ->myIvar を使用しても変数の値にアクセスすることはできません。 このシンタックスは実行エラーを起こします。

  • RESOLVE POINTER を使用したポインターの比較はお勧めできません。 変数の分離の原則により、ホストプロジェクトとコンポーネント (あるいは他のコンポーネント) で同じ名前の変数が存在することができますが、根本的にそれらは異なる内容を持ちます。 両コンテキストで、変数のタイプが違うことさえありえます。 ポインター myptr1myptr2 がそれぞれ変数を指すとき、以下の比較は正しくない結果となるかもしれません:

     RESOLVE POINTER(myptr1;vVarName1;vtablenum1;vfieldnum1)
RESOLVE POINTER(myptr2;vVarName2;vtablenum2;vfieldnum2)
If(vVarName1=vVarName2)
// 変数が異なっているにもかかわらず、このテストはtrue を返します

このような場合には、ポインターを比較しなければなりません:

     If(myptr1=myptr2) // このテストはFalse を返します

エラー処理

ON ERR CALL コマンドによって実装された エラー処理メソッド は、実行中のプロジェクトに対してのみ適用されます。 コンポーネントによって生成されたエラーの場合、ホストプロジェクトの ON ERR CALL エラー処理メソッドは呼び出されず、その逆もまた然りです。

ホストプロジェクトのテーブルへのアクセス

コンポーネントでテーブルを使用することはできませんが、ホストプロジェクトとコンポーネントはポインターを使用して通信をおこなうことができます。 たとえば、以下はコンポーネントで実行可能なメソッドです:

// コンポーネントメソッドの呼び出し
methCreateRec(->[PEOPLE];->[PEOPLE]Name;"Julie Andrews")

コンポーネント内の methCreateRec メソッドのコード:

C_POINTER($1) // ホストプロジェクトのテーブルへのポインター
C_POINTER($2) // ホストプロジェクトのフィールドへのポインター
C_TEXT($3) // 代入する値

$tablepointer:=$1
$fieldpointer:=$2
CREATE RECORD($tablepointer->)

$fieldpointer->:=$3
SAVE RECORD($tablepointer->)

コンポーネントのコンテキストにおいて、テーブルフォームへの参照はすべてホスト側のテーブルフォームへの参照だと 4D はみなします (コンポーネントはテーブルを持つことができないからです)。

テーブルやフィールドの利用

コンポーネントは、マトリクスプロジェクトのストラクチャーで定義されたテーブルやフィールドを使用することはできません。 しかし外部データベースを作成し、そのテーブルやフィールドを必要に応じ利用することはできます。 外部データベースの作成と管理は SQL を用いておこないます。 外部データベースは、メインの4Dプロジェクトから独立している別の 4Dプロジェクトですが、メインプロジェクトから操作が可能です。 外部データベースの利用は、そのデータベースを一時的にカレントデータベースに指定することです。言い換えれば、4Dが実行する SQL クエリのターゲットデータベースとして外部データベースを指定します。 外部データベースの作成は SQL の CREATE DATABASE コマンドを使用します。

例題

以下のコードはコンポーネントに実装されており、外部データベースに対して3つの基本的なアクションをおこないます:

  • 外部データベースを作成します (存在しない場合)
  • 外部データベースにデータを追加します
  • 外部データベースからデータを読み込みます

外部データベースの作成:

<>MyDatabase:=Get 4D folder+"\MyDB" // (Windows) データを許可されているディレクトリに保存します
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

外部データベースへのデータ書き込み:

 $Ptr_1:=$2 // ポインターを介してホストプロジェクトからデータを取得します
$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

外部データベースからデータを読み込み:

 $Ptr_1:=$2 // ホストプロジェクトへのデータアクセスはポインターを通じておこないます
$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

フォームの使用

  • 特定のテーブルに属さない" プロジェクトフォーム" のみが、コンポーネント内で利用できます。 マトリクスプロジェクトのすべてのプロジェクトフォームをコンポーネントで使用することができます。
  • コンポーネントはホストプロジェクトのテーブルフォームを使用できます。 この場合、コンポーネントのコードでフォームを指定するにあたっては、テーブル名ではなく、テーブルへのポインターを使用しなければならないことに注意してください。

コンポーネントが ADD RECORD コマンドを使用すると、ホストプロジェクトのコンテキストで、ホストプロジェクトのカレントの入力フォームが表示されます。 したがって、その入力フォーム上に変数が含まれている場合、コンポーネントはその変数にアクセスできません。

  • You can publish component forms as subforms in the host projects. これは具体的には、グラフィックオブジェクトを提供するコンポーネントを開発できることを意味します。 たとえば、4D社が提供するウィジェットはコンポーネントのサブフォーム利用に基づいています。

コンポーネントのコンテキストにおいては、参照されるプロジェクトフォームはすべてコンポーネント内に存在している必要があります。 たとえば、コンポーネント内において、DIALOG または Open form window コマンドを使用してホスト側のプロジェクトフォームを参照しようとした場合にはエラーが生成されます。

リソースの使用

コンポーネントは、自身の Resourcesフォルダーにあるリソースを使用することができます。

これによって自動メカニズムが有効となり、コンポーネントの Resources フォルダー内で見つかった XLIFF ファイルは、 同コンポーネントによってロードされます。

1つ以上のコンポーネントを含むホストプロジェクトでは、ホストプロジェクトと同様にそれぞれのコンポーネントも固有のリソースチェーンを持っています。 リソースは異なるプロジェクト間で分離されます。コンポーネントA のリソースにコンポーネントB やホストプロジェクトからアクセスすることはできません。

初期化のコードの実行

コンポーネントは、ホストデータベースを開いたときまたは閉じたときに、自動的に 4Dコードを実行することができます。これによってたとえば、ホストデータベースに関連する設定やユーザーの状態などを読み込み・保存することができます。

初期化やデータベースを閉じるコードの実行は、 On Host Database Event データベースメソッド を使用しておこなわれます。

セキュリティ上の理由から、On Host Database Event データベースメソッドを使用可能にするためには、その実行をホストデータベースで明示的に許可する必要があります。 セキュリティ上の理由から、On Host Database Event データベースメソッドを使用可能にするためには、その実行をホストデータベースで明示的に許可する必要があります。

コンポーネントの保護: コンパイル

コンポーネントとしてインストールされたマトリクスプロジェクトのコードは、ホストプロジェクトからデフォルトでアクセス可能です。 特に:

  • エクスプローラーのメソッドページに存在する共有のプロジェクトメソッドは、ホストプロジェクトのメソッドから呼び出し可能です。 エクスプローラーのプレビューエリアでそれらの内容を選択してコピーすることが可能です。 また、その内容はデバッガーで見ることもできます。 しかし、それらをコードエディター上で開いたり編集したりすることはできません。
  • マトリクスプロジェクトの他のプロジェクトメソッドはエクスプローラーに現れません。しかし、ホストプロジェクトのデバッガーには内容が表示されます。
  • 名前空間が宣言されていれば、非表示でないクラスや関数はデバッガーで確認することができます。

コンポーネントのコードを効果的に保護するには、マトリクスプロジェクトを コンパイルしビルドして、.4dz ファイルとして提供します。 コンパイルされたマトリクスプロジェクトがコンポーネントとしてインストールされると:

  • 共有のプロジェクトメソッド、クラス、および関数は、ホストプロジェクトのメソッドから呼び出し可能です。共有のプロジェクトメソッドは、エクスプローラーのメソッドページにも表示されます。 しかし、その内容はプレビューエリアにもデバッガーにも表示されません。
  • マトリクスプロジェクトの他のプロジェクトメソッドは一切表示されません。

コンポーネントの共有

開発したコンポーネントを GitHub で公開し、4D開発者のコミュニティをサポートすることをお勧めします。 正しく参照されるためには、4d-component トピックをご利用ください。