例: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 メンバー関数
このメンバー関数は、インタラクションを中止するために呼び出されます。矩形の幅は 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; |
前のゴースト・イメージは消去されます。
現在の矩形は保存され、インタラクターがリセットされます。
IlvRect rect(_xor_rectangle); _xor_rectangle.w(0); |
doIt メンバー関数が呼び出されます。サブクラスはパラメーターとして提供された矩形を使用して、最終タスクを実行するためにこのメソッドをオーバーロードします。
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.