C MAGAZINE 2002年10月号より転載
ドローツールには、基本図形をグループにまとめる機能が必要です。たとえばFig.6のように、基本図形を組み合わせてグループ化すれば、複雑な図形を作ることができます。図形が複雑になると移動やコピーなどがめんどうになりますが、グループ化しておけば大丈夫ですね。
Fig.6 グループ化
基本図形やグループを配置する1枚の絵を「ページ」と呼ぶことにしましょう。ページのイメージはFig.7のようになります。ページには、矩形や楕円といった基本図形と、グループとが配置されます。グループの中には、おのおののグループに属する基本図形(またはグループ)が配置されます。
Fig.7 ページのイメージ
さて、グループ化した複数の図形は、まとめて1つの基本図形と同じように移動したりコピーしたりできるようにします。そのためにはグループを基本クラスから派生させて、基本図形の「兄弟」クラスにするのがいいでしょう。つまりグループは、基本クラスの機能を継承しつつ、内部に複数の図形(ここでは子オブジェクトと呼びます)を配置できるクラスです。
また、ページもグループと同じように内部に複数の子オブジェクトを配置できるクラスです。ここではページをグループの一種だと考えて、グループクラスから派生することにします。
まとめると、グループクラス(DGroupとします)とページクラス(DPage)との関係はFig.8のようになります。グループは基本クラスから派生させて、子オブジェクトのリストを追加します。ページはグループから派生させて背景色を追加します。子オブジェクトのリストは、Fig.4やFig.5のようなDObject*の配列またはリストです。
Fig.8 グループクラスとページクラスの構成
●グループクラスのプログラム例
Fig.8の構成に基づいてグループクラスを書いたものがList5です。List5-(1)が子オブジェクトのリストで、List5-(2)は子オブジェクトを操作するためのメソッドです。操作としては、子オブジェクトの追加、表示優先順位の変更、グループ化とグループ解除を用意しました。
List5 グループクラス(DGroup.h)
|
// グループ
class DGroup : public DObject {
protected:
//===================================== (1)
// 子オブジェクトのリスト
TList* Objects;
public:
//===================================== (2)
// 子オブジェクトの操作
void Add(DObject* object);
void OrderTop(DObject* object);
void OrderBottom(DObject* object);
void OrderTop(TList* objects);
void OrderBottom(TList* objects);
void MakeGroup(TList* groupedObjects);
void CancelGroup(TList* groupedObjects);
//===================================== (3)
// 編集操作
void Cut(TList* selected, TList* cutbuf);
void Copy(TList* selected, TList* cutbuf);
void Paste(TList* cutbuf, TList* selected);
// コンストラクタ,複製
DGroup();
DGroup(DGroup* src);
virtual DObject* Clone();
//===================================== (4)
// 描画(通常,当たり判定)
virtual void Paint(TCanvas* canvas);
virtual void PaintHitArea(TCanvas* canvas, TColor color);
//===================================== (5)
// 属性の設定
virtual void SetPos(float left, float top);
virtual void SetRect(TRect rect);
virtual void SetPenColor(TColor color);
virtual void SetBrushColor(TColor color);
virtual void SetFont(TFont* font);
virtual void SetFontColor(TColor color);
virtual void SetFilled(bool filled);
virtual void SetClosed(bool closed);
virtual void ChangePenWidth(int d_width);
};
|
切り取り、コピー、貼りつけといった編集操作も、List5-(3)のようにグループクラスで実現するのがいいでしょう。List5-(3)の3つのメソッドの引数は、selectedが選択中の子オブジェクト、cutbufが切り取りとコピー用のバッファです。
List5-(4)とList5-(5)は基本クラスのメソッドをオーバライドしたものです。グループの場合、描画ではすべての子オブジェクトを描く必要があります。また属性の設定では、すべての子オブジェクトの属性を設定しなければいけません。
●ページクラスのプログラム例
ページクラスはList6のようなプログラムになります。List6-(1)はページ色で、List6-(3)がページ色の取得と設定を行うメソッドです。また、List6-(4)は描画メソッドをオーバライドしたものです。
List6 ページクラス(DGroup.h)
|
// ページ
class DPage : public DGroup {
protected:
//====================================== (1)
// ページ色(背景色)
TColor PageColor;
//====================================== (2)
// 当たり判定用のビットマップと,更新メソッド
Graphics::TBitmap* HitArea;
void UpdateHitArea();
public:
//====================================== (3)
// ページ色の取得と設定
TColor GetPageColor() { return PageColor; }
void SetPageColor(TColor color) { PageColor=color; }
// コンストラクタ,複製
DPage();
DPage(DPage* src);
virtual DObject* Clone();
//====================================== (4)
// 描画(通常,当たり判定)
virtual void Paint(TCanvas* canvas);
//====================================== (5)
// 当たり判定の実行
// 座標(x,y)にあるオブジェクトを返す
// オブジェクトが無いときにはNULLを返す
// 当たり判定領域のサイズをwidth,heightで指定する
DObject* HitObject(float x, float y, float width, float height);
};
|
List6-(2)とList6-(5)は、オブジェクトの当たり判定用の変数とメソッドです。当たり判定については次の節で説明します。
コラム1 Javaへの移植ポイント(クラス設計)
|
Javaでドローツールを作る場合も、クラス設計はC++の場合とほとんど同じ要領です。List1からList6までのプログラムは、少し変更すればJava用になります。変更のポイントは、C++Builder特有のクラス(TPenやTBrushなど)をJava用のクラスに置き換えることと、一部のキーワード(virtualなど)を書き換えることです。virtualキーワードは単に除去するだけでかまいません。
|
関連リンク
C MAGAZINE
ひぐぺん工房
「デスクトップマスコットを作ろう」紹介ページ
「デスクトップマスコットを作ろう」著者ページ
|