Manager > マネージャー・イベント処理 > ビュー・インタラクター > 例:IlvDragRectangleInteractor クラスの実装
 
例:IlvDragRectangleInteractor クラスの実装
この例は、IlvDragRectangleInteractor メンバー関数の実装方法を例示します。独自のインタラクターを作成するための出発点としてこの例を使用できます。
IlvDragRectangleInteractor インタラクターによって、ビュー内の矩形領域を指定できます。続いて、派生したインタラクターでこの矩形をさまざまな目的で使用できます。たとえば、グラフィック・オブジェクトの作成に特化したサブクラスでこの矩形を使用して、新しいオブジェクトのバウンディング・ボックスを定義できます。
わずかに変更になったこのクラスの概要を以下に示します。
class IlvDragRectangleInteractor
: public IlvManagerViewInteractor
{
public:
IlvDragRectangleInteractor(IlvManager* manager, IlvView* view)
: IlvManagerViewInteractor(manager, view) {}
 
virtual void handleEvent(IlvEvent& event);
virtual void drawGhost();
virtual void doIt(IlvRect&);
virtual void abort();
 
IlvRect& getRectangle();
protected:
IlvRect _xor_rectangle;
IlvPos _firstx;
IlvPos _firsty;
};
次の 3 つの保護フィールドが定義されます。
*_xor_rectangle - ユーザーがドラッグしている矩形の座標を保持します。
*_firstx_firsty - 最初に受信されたボタンダウン・イベントの座標です。このポイントは、選択された矩形の開始点として使用されます。これはユーザーが矩形をドラッグした方向によって、4 隅のいずれかになります。
コンストラクターは何も処理を行わず、初期化は doIt メンバー関数によって行われます。
また、IlvManagerViewInteractor クラスの 4 つのメンバー関数がオーバーロードされます。
*abort メンバー関数
*handleEvent メンバー関数
*drawGhost メンバー関数
*doIt メンバー関数
abort メンバー関数
このメンバー関数は、インタラクションを中止するために呼び出されます。矩形の幅は 0 に設定されます。
void
IlvDragRectangleInteractor::abort()
{
_xor_rectangle.w(0);
}
handleEvent メンバー関数
IlvDragRectangleInteractor::handleEvent メンバー関数の簡易バージョンを以下に示します。
void
IlvDragRectangleInteractor::handleEvent(IlvEvent& event)
{
switch (event.type()) {
case IlvKeyUp:
case IlvKeyDown:
getManager()->shortCut(event, getView());
break;
case IlvButtonDown:
if (event.button() != IlvLeftButton)
getManager()->shortCut(event, getView());
else {
_xor_rectangle.w(0);
IlvPoint p(event.x(), event.y());
if (getTransformer()) getTransformer()->inverse(p);
_firstx = p.x();
_firsty = p.y();
}
break;
case IlvButtonDragged:
if ((event.button() != IlvLeftButton))
getManager()->shortCut(event, getView());
else {
if (_xor_rectangle.w()) drawGhost();
IlvPoint p(event.x(), event.y());
if (getTransformer()) getTransformer()->inverse(p);
_xor_rectangle.move(IlvMin(_firstx, p.x()),
IlvMin(_firsty, p.y()));
_xor_rectangle.resize((IlvDim)(IlvMax(_firstx, p.x())
-_xor_rectangle.x()),
(IlvDim)(IlvMax(_firsty, p.y())
-_xor_rectangle.y()));
ensureVisible(IlvPoint(event.x(), event.y()));
drawGhost();
}
break;
case IlvButtonUp:
if (event.button() != IlvLeftButton)
getManager()->shortCut(event, getView());
else {
if (!_xor_rectangle.w()) return;
drawGhost();
IlvRect rect(_xor_rectangle);
_xor_rectangle.w(0);
doIt(rect);
}
break;
}
ここでは、ボタン・イベントのみが管理されます。それ以外のイベントは無視されるか、IlvManager::shortCut メンバー関数を呼び出すことによりアクセラレーターへのディスパッチのためマネージャーに送られます。
以下の種類のイベントが handleEvent メンバー関数により処理されます。
*キーボード・イベント
*ボタンダウン・イベント
*ボタンドラッグ・イベント
*ボタンアップ・イベント
キーボード・イベント
これらのイベントを無視するとしましょう。これらのイベントを無視するには、次を実施します。自然ビュー・インタラクター・プロセスをバイパスし、アクセラレーターと一致するマネージャーにイベントを送り返します。この方法は、イベントが運ぶ情報を失わずに実施するための最良の方法です。
case IlvKeyUp:
case IlvKeyDown:
getManager()->shortCut(event, getView());
break;
ボタンダウン・イベント
case IlvButtonDown:
...
break;
マウスの位置は _firstx_firsty に格納され、矩形はリセットされます。これは、矩形の幅を 0 に設定することにより行えます。次に、座標がオブジェクト座標系に格納されます。
if (event.button() != IlvLeftButton)
getManager()->shortCut(event, getView());
else {
_xor_rectangle.w(0);
IlvPoint p(event.x(), event.y());
if (getTransformer()) getTransformer()->inverse(p);
_firstx = p.x();
_firsty = p.y();
}
ボタンドラッグ・イベント
case IlvButtonDragged:
...
break;
_xor_rectangle が有効である場合、drawGhost によって既に矩形が描画されており、削除する必要があります。
if (_xor_rectangle.w()) drawGhost();
新しい矩形はオブジェクト座標系で計算されます。
IlvPoint p(event.x(), event.y());
if (getTransformer()) getTransformer()->inverse(p);
_xor_rectangle.move(IlvMin(_firstx, p.x()),
IlvMin(_firsty, p.y()));
_xor_rectangle.resize((IlvDim)(IlvMax(_firstx, p.x())
-_xor_rectangle.x()),
(IlvDim)(IlvMax(_firsty, p.y())
-_xor_rectangle.y()));
以下により、ドラッグしたポイントを画面上に確実に表示できます。ビューがスクロールされたビューにある場合、マウス位置の表示を保つためにビューの座標を変更できます。
ensureVisible(IlvPoint(event.x(), event.y()));
新しい矩形が描画されます。
drawGhost();
ボタンアップ・イベント
ボタンアップ・イベントはインタラクションの終わりを示します。矩形が再定義されています。
case IlvButtonUp:
...
break;
前のゴースト・イメージは消去されます。
drawGhost();
現在の矩形は保存され、インタラクターがリセットされます。
IlvRect rect(_xor_rectangle);
_xor_rectangle.w(0);
doIt メンバー関数が呼び出されます。サブクラスはパラメーターとして提供された矩形を使用して、最終タスクを実行するためにこのメソッドをオーバーロードします。
doIt(rect);
drawGhost メンバー関数
IlvDragRectangleInteractor::drawGhost メンバー関数は _xor_rectangle のゴースト・イメージを描画します。
void
IlvDragRectangleInteractor::drawGhost()
{
IlvManager* mgr = getManager();
if (_xor_rectangle.w()) {
IlvRect rect = _xor_rectangle;
if(getTransformer()) getTransformer()->apply(rect);
getView()->drawRectangle(mgr->getPalette(),rect);
}
}
_xor_rectangle はオブジェクト座標系で表現されるため、矩形を描画する前にビューのトランスフォーマーを適用する必要があります。
doIt メンバー関数
IlvDragRectangleInteractor::doIt メンバー関数は何も行いません。矩形領域が選択されるとアクションを実行するためにオーバーロードされるよう設計されています。
以下の 2 つの例は、このメンバー関数をオーバーロードする方法を示しています。
*最初の例は、新しい IlvRectangle オブジェクトを矩形領域で作成する方法です (IlvMakeRectangleInteractor クラスと同じ方法)。
*2 番目の例は、矩形領域内のすべてのオブジェクトを選択する方法です。選択インタラクターを使用せずにマネージャー内で選択を操作する方法を示しています。
例 1:IlvMakeRectangleInteractor
これは IlvDragRectangleInteractor クラスから派生した IlvMakeRectangleInteractor::doIt メンバー関数の簡易バージョンです。このメンバー関数はマネージャーのすべてのオブジェクトの選択を解除し、IlvRectangle インスタンスを作成してマネージャーに追加し、その上で選択を設定します。
void
IlvMakeRectangleInteractor::doIt(IlvRect& rect)
{
IlvGraphic* obj = new IlvRectangle(getDisplay(), rect);
getManager()->deSelect();
getManager()->addObject(obj);
getManager()->makeSelected(obj);
}
IlvGraphic* obj = new IlvRectangle(getDisplay(), rect);
例 2:セレクター
この例は、グラフィック・オブジェクトを選択するために簡単なインタラクターを実装する方法を説明します。IlvDragRectangleInteractor::doIt メンバー関数は、ユーザーが作成した領域内のすべてのオブジェクトを選択するためにオーバーロードされます。
SelectAnObject 関数が定義されます。これはマネージャーのアプリケーション・メンバー関数によって呼び出されます。マネージャーは manager パラメーターで利用可能です。
static void
SelectAnObject(IlvGraphic* object, IlAny manager)
{
((IlvManager*)manager)->setSelected(object, IlTrue);
}
doIt メンバー関数は、指定された矩形内のすべてのオブジェクトに対して SelectAnObject を呼び出します。これらのオブジェクトを探すには、マネージャー・メンバー関数 applyInside を呼び出します。
void
MyRectangleSelector::doIt(IlvRect& rect)
{
getManager()->applyInside(rect, SelectAnObject, (IlAny)getManager());
}

Version 6.0
Copyright © 2015, Rogue Wave Software, Inc. All Rights Reserved.