Kデスクトップ環境

2.3. イベント

イベントは2つの要素、イベントネームつまり文字列とイベント引数 CORBA::Any value で 成り、それゆえ開発者は自由に選択できます。

指定されたオブジェクトに送られたイベントは、イベントが目的地となるオブジェクトまでの パイプを通されていると考えることができます。 このパイプはインストールされているイベントフィルタで満たされています。 フィルタには三種類があります。

KOM の現在の実装では、これらのフィルタモードはイベント処理の命令を指示するだけです。 イベントが発信される場合、まずフィルタモードFM_WRITEで全てのイベントフィルタがフィルタリングされます。 そしてFM_IMPLEMENTに続き、 最終的にFM_READと続きます。 イベントフィルタには実際のイベントで行うことができる二つの可能性があります。 これらのフィルタはイベントを単に読み込むだけ可、 あるいはそのイベントを廃棄することができます。 つまりそのイベントは破棄され、その行き先のオブジェクトを決して受け取らないということです。

実際のイベントネームは、イベントフィルタに関して特別な意味を持っています。 あるオブジェクトに対してイベントフィルタをインストールした場合、 フィルタオブジェクトのリファレンスやフィルタマッピング機能の名称に加えて、 一連のいわゆるイベントタイプパターンについても指示しなければなりません。 あるイベントタイプパターンは、特別なパターンだけではなく単一のイベント名称です。 (イベントパターンについて、詳しくはkom.idlを ご覧ください)。

イベントがフィルタによって処理される際、引数としてのイベントネームとイベント値で 指定されたフィルタ関数が呼ばれます。 このフィルタ関数は、イベントが廃棄されるかどうかを(ブール値を通じて) 返さなければなりません。

全てのフィルタリングが実行され、インストールされたどのフィルタがイベントを破棄しない場合、最終的に行き先のオブジェクトによって受け取られます。 つまり、オブジェクトのevent()メソッドを呼ぶことによって KOM::Base インターフェースに定義されます。 デフォルトの実装は実際には何も行いません。 ですからもしかするとこの仮想関数の再実装が必要になるかもしれません。

イベントの低レベルな使用方法は、イベント送信用オブジェクトの receive/receiveASyncメソッドを呼んだり、イベントをマッピングするために KOMBase::event を 再インプリメントすることです。 しかし KOM には、イベント処理を単純化する素晴らしいマクロがいくつか用意されています。

2.3.1. イベントの送信

送信用に komBase.h は、役立つEMIT_EVENTマクロを定義してあり、全て同じ文法EMIT_EVENT_x(destination_object, event_name, event_argument)を使用しています。

"destination_object" は、イベントの受け取り/処理を予定しているオブジェクトのリファレンスです。 イベントは、この目的オブジェクトにインストールされている全てのイベントフィルタで処理されます。 "event_name" は、自明でしょう;-)。 イベント引数は、特定のマクロに従います。それらは特に以下のようなものです:

2.3.2. イベントの受信

イベントの受信は送信に比べて若干困難です。 というのは、あらゆる種類のイベントを処理しなければならないので、 オブジェクトは1つのハンドラメソッド KOM::Base ::event (IDL) / KOMBase::event (C++)で受け取ることができるます。 イベントの送信のように、低CORBAレベルで全てのことを行うことができます。 しかし、なぜ堅実な方法を採ろうとするのでしょう? KOMは、これに関してもとても素晴らしく、使いやすいマクロがあります(komBase.hで定義されています):-)。 たいていが次のサンプルのような感じになっています:
   1 #include <kom.idl>
   2 
   3 module MyModule
   4 {
   5   // イベント引数は文字列
   6   const string eventFirstFoo = "MyFooEventNameOrWhateverYouNameIt";
   7 
   8   struct MyStruct
   9   {
  10     boolean kde_rules;
  11   };
  12 
  13   const string eventSecondFoo = "Blaafooo";
  14   typedef MyStruct EventSecondFoo;
  15 
  16   interface SomethingElse
  17   {
  18     //..
  19   };
  20 
  21   const string eventThirdFoo = "KOMIsCool";
  22   typedef SomethingElse EventThirdFoo;
  23 
  24   interface Foo : KOM::Base
  25   {
  26     //...
  27   };
  28 
  29 };
  30 
  31 bool FooImpl::event( const char *event, const CORBA::Any &value )
  32 {
  33   EVENT_MAPPER( event, value );
  34 
  35   MAPPING_STRING( MyModule::eventFirstFoo, mappingFirstFoo );
  36 
  37   MAPPING( MyModule::eventSecondFoo, MyModule::EventSecondFoo, mappingSecondFoo );
  38 
  39   MAPPING( MyModule::eventThirdFoo, MyModule::EventThirdFoo_ptr, mappingThirdFoo );
  40 
  41   END_EVENT_MAPPER; //マクロは "return false;" を実行します。
  42                     //このポイントに達したときイベントを取り扱わなかったことを示します。
  43 }
  44 
  45 bool FooImpl::mappingFirstFoo( const char *myArgument )
  46 {
  47   ...
  48   //忘れずにブール値を用いて返して下さい。
  49   //イベント処理が成功したかどうかを暗示します。
  50 }
  51 
  52 bool FooImpl::mappingSecondFoo( MyModule::MyString anotherArg )
  53 {
  54   //...
  55 }
  56 
  57 bool FooImpl::mappingThirdFoo( MyModule::SomethingElse_ptr whaaboo )
  58 {
  59   //...
  60 }

ご覧のように、イベントハンドラはたいていEVENT_MAPPERマクロで始まっており、END_EVENT_MAPPERで終わっています。 EMIT_EVENT_xマクロと類似し、 MAPPINGマクロは通常のMAPPINGマクロと以下のものから構成されています:

多少イベント処理を構造化するには、どのイベントも関数を取り扱っている独自のイベントを得ます。 これらの関数はマッピングマクロ(最後の引数)で呼ばれます。 上記で用いられたネーミングスキームは、必要ではありませんが、KOMを使用しているアプリケーションではだいたい用いられています。