@node Concept, ImplementVObjectClass, Top, Top
@chapter 外側（ユーザー側）から見たVObjectクラス群のコンセプト

VObjectクラス群には，ウィンドウや，プッシュボタン，テキストフィールドといった部品，それらをグルーピングする目に見えないボックスなど，GUIの各構成要素に対応する何種類ものクラスがあります。これらは全てVObjectという基底クラスを継承しており，共通したインターフェースを使って取り扱うことができます。

@menu
* VObjectClass::                VObjectクラス                
* subClass::                    各種サブクラス                    
* InitEventloop::               初期化とイベントループ              
@end menu

@node VObjectClass, subClass, Concept, Concept
@section VObjectクラス

全てのクラスは，VObjectクラスを継承しています。VObjectクラスは，次のような機能を提供します。

@menu
* Status::                      ステータス                     
* CreateDestroy::               オブジェクトの生成と破棄              
* SetGet_Status::               ステータスの記憶と取り出し              
* manageTree_C::                ツリーの管理                 
@end menu

@node Status, CreateDestroy, VObjectClass, VObjectClass
@subsection ステータス

各VObjectのインスタンスはVObjectStatus構造体を中に持っており，そこに様々なオブジェクトの状態が格納されています。例えば，オブジェクトのID番号やタイトル，オブジェクトの並べ方，OSなどに依存したオブジェクトの管理に使われるポインタなどです。詳しい内容はh/v/v_types.hを見て下さい。

@node CreateDestroy, SetGet_Status, Status, VObjectClass
@subsection オブジェクトの生成と破棄
（create関数，destroy関数）

VObjectの各サブクラスは，createというstaticな関数を持っており，これを呼び出すことによって各クラスのインスタンスが生成されます。newによって生成する（コンストラクタを直接呼び出す）ことはできません。

ステータスのうち，必要な項目の値と，それに該当するフラグを渡すことで，オブジェクトの生成時にステータスを指定できます。フラグは，ORで繋いで複数同時に指定できます。例えば，プッシュボタンのラベルを指定する場合は

@example
VPushButton *button;
VObjectStatus sts;
sts.parent = window;
sts.descriptor = (L_CHAR[])@{'T','E','S','T','2',0@};
button = VPushButton::create(&sts, VSF_PARENT | VSF_DESC);
@end example

@noindent
のようにします。

createするときには，必ず親オブジェクトを指定する必要があります。ただし，VWindowは例外です。VWindowの親は常にVDisplay::get_main_displayで取得できるVDisplayのインスタンスで，指定しなくても自動的に設定されます。

オブジェクトを解放するときは，deleteを使ってはいけません。
代わりにdestroy()メソッドをコールします。
すると，そのオブジェクトはまず，v_zonbie_listというリストに登録されます。オブジェクトはすぐには解放されず，その間はアクセッサを呼んでも安全です。この場合，エラー値としてV_ER_DESTROYEDが返り，処理は実行されません。
v_zonbie_listに登録された後，秒数V_OBJECT_ZONBIE_DELAYの時間が経過すると，オブジェクトのメモリは解放されます。
これにより，複数スレッドでオブジェクトを参照していても，メモリアクセスフォールトになることを回避しています。

@node SetGet_Status, manageTree_C, CreateDestroy, VObjectClass
@subsection ステータスの記憶と取り出し
　（set_status関数，get_status関数）

これらの値は，set_status関数によって設定し，get_status関数によって取得することができます。例えば，VObject* objの並べ方と間隔の開け方を指定する場合，

@example
VObjectStatus sts;
sts.alignh = VALIGN_LEFT;
sts.padding.w = 10;
obj->set_status(&sts, VSF_PADDING | VSF_ALIGN);
@end example

などのように，設定・取得する必要のある値をフラグで渡すことによって，複数同時に設定・取得することができます。

set_status, get_status関数は実際にはvirtual宣言されていて，各サブクラスによって動作が異なることがあります。

set_status, get_status関数の返値は，VError型です。これはenum型で，h/v/v_errors.hで定義されています。

なお，フラグのVSF_LAYOUT，VSF_CALC_MIN, VSF_MIN_SIZE, VSF_SIZE,
VSF_POSITION，及びそれらに対応するVObjectStatusのメンバは，VLayoutとの通信用に使われるもので，ユーザサイドから使ってはいけません。
（ただし，VWindowクラスのみ，VSF_SIZE，VSF_POSITIONはset_status, get_statusともに可能。）

@node manageTree_C,  , SetGet_Status, VObjectClass
@subsection ツリーの管理

各VObjectのインスタンスは，ツリー状の階層構造を持っています（クラスの継承とは別です）。たとえば，ディスプレイにウィンドウがいくつか属し，その中のあるウィンドウの中にはボックスがあり，その中にボタンがいくつか含まれている，といった具合です。ボックスの中にさらにボックスが含まれていることもあるでしょう。

各クラスの子は，画面上でそのツリー構造に従って自動的にレイアウトされます。

各サブクラスによって，持てる子の数は決まっています。例えば，VWindowクラスの子は一つまでです。それ以上の子を格納する場合は，VAlignViewオブジェクトなどでパッキングする必要があります。これによって，GUI部品の並び方を指定することができるようになります。


@node subClass, InitEventloop, VObjectClass, Concept
@section 各種サブクラス

現在，以下のようなサブクラスがインプリメントされています。

@menu
* VDisplayClass::               
* VWindowsClass::               
* VButtonClass::                
* VPushButtonClass::            
* VCheckBoxClass::              
* VRadioButtonClass::           
* VAlignViewClass::             
* VDrawClass::                  
* VSliderClass::                
* VScrollViewClass::                
* VStaticTextClass::                
* VEditTextClass::                
@end menu

@node VDisplayClass, VWindowsClass, subClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VDisplayクラス

このクラスのインスタンスはv_object_initの実行時に一つだけ作られ，全てのVWindowクラスのインスタンスの親になります。

@node VWindowsClass, VButtonClass, VDisplayClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VWindowクラス

ウィンドウを管理します。descriptorがウィンドウのタイトルになります。

@node VButtonClass, VPushButtonClass, VWindowsClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VButtonクラス

ボタン類（プッシュボタン，ラジオボタン，チェックボックスetc.）の基底クラスです。抽象クラスで，インスタンス化することはありません。

@node VPushButtonClass, VCheckBoxClass, VButtonClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VPushButtonクラス

プッシュボタンを管理します。descriptorがボタンの名前になります。ボタンがクリックされると，事前に登録されたvalue_event_handlerが呼び出されます。（実際にはvalueは変化しません。）

@node VCheckBoxClass, VRadioButtonClass, VPushButtonClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VCheckBoxクラス

チェックボックスを管理します。descriptorがボタンの名前になります。ボタンがクリックされると，事前に登録されたvalue_event_handlerが呼び出されます。valueはチェックされているとき1，されていないとき0になります。

@node VRadioButtonClass, VAlignViewClass, VCheckBoxClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VRadioButtonクラス

ラジオボタンを管理します。descriptorがボタンの名前になります。ボタンがクリックされると，事前に登録されたvalue_event_handlerが呼び出されます。valueは選択されているとき1，されていないとき0になります。
set_radio_group(VRadioButton*)に別のラジオボタンを渡すと、そのボタンと同一グループとなります。そして、常に同一グループ内のどれか一つのラジオボタンのみが選択された状態になります。

@node VAlignViewClass, VDrawClass, VRadioButtonClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VAlignViewクラス

VAlignViewクラスは，複数のオブジェクトをグループ化し，またそのオブジェクトを一列に並べる，視覚的には見えないオブジェクトのためのスーパークラスです。
サブクラスに，オブジェクトを横に並べるVHAlignViewクラス，縦に並べるVVAlignViewクラスがあります。
子オブジェクトのalignh/alignv，paddingなどの指定が考慮されます。

@node VDrawClass, VSliderClass, VAlignViewClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VDrawクラス

任意のビットマップ画像を表示し，またマウス操作に対応するイベントをハンドリングできるオブジェクトです。

画像はまず，VImage構造体として表現します。
VImageは，ref / unref方式でメモリの解放を管理します。v_image_newで新しく 構造体を作ったとき，参照カウントは１です。このカウントはv_image_refをコールすると1増え，unrefで1減ります。0になると，メモリは解放されます。

VImageに画像を書き込むためには，まずv_image_draw_startを呼び出してロックしておき，v_image_draw_endを呼び出してロックを解除する必要があります。ロックと書きましたが，単純に2回以上連続してv_image_draw_startが呼び出されるとエラーになるだけであり，特にマルチスレッドに対応しているわけではありませんので，複数のスレッドで同時に書き換えようとしてはいけません。
VImageは，今のところ32ビットのバッファのみをサポートしています。RGB値をこの バッファに格納するためのマクロRGB8_32(r,g,b)と，バッファからr，g，bの各 値を読みとるGET_RGB8_32(pix,r,g,b)を使って，このバッファにアクセスできます。

VDrawを新規作成し，set_imageメソッドにVImage構造体を渡すと，そのイメージ構造体を表示します。オブジェクトのサイズはそのイメージの大きさになります。refカウントは1増えます。もしすでにVimageに画像がセットされていた場合，その画像のrefカウントは1減り，場合によってはメモリが解放されます。

draw_start()を呼び出すと，set_imageしたVImage構造体は，v_image_draw_startされた上で返ります。VDraw自身もロックされます。画像に対してピクセルを取得したり書き換えたりしたあと，draw_endを呼び出して下さい。v_image_draw_endが実行され，ロックが解除されます。

set_mouse_event_handlerを使ってマウスイベントハンドラを登録できます。現在，マウスダウン，アップ，移動，VDrawへのポインタの出入り，ダブルクリックを扱えます。マウス移動イベントは，ドラッグ中（マウスダウン〜アップ）はドラッグを開始したVDrawオブジェクトで扱います。


@node VSliderClass,  VScrollViewClass, VDrawClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VSliderクラス

整数値をコントロールするスライダーを管理します。createするときに、スライダーでコントロールしたい値の範囲(最小値、最大値、ステップ数)を渡します。現在の値を取得・設定するには，get/set_status でVSF_VALUEを指定し，ステータスのvalueを取得・設定します。

@node VScrollViewClass,  VStaticTextClass, VSliderClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VScrollViewクラス

水平・垂直方向のスクロールバーを持つ長方形のビューを管理します。このオブジェクトの内側には，直接の子オブジェクトを一つ配置できます。

子オブジェクトの大きさは，set_internal_sizeメソッドによってこのビューの大きさに無関係に指定できます。設定されたinternal_sizeの方がこのビューよりも大きい場合，スクロールバーで内側の子オブジェクトが見えている場所を調節できます。

設定したinternal_sizeよりもビューの方が大きくなった場合は，子オブジェクトの大きさはビューの大きさに合わせられます。

create時に，スクロールバーをいつ表示するかを，水平・垂直それぞれについて指定できます。
h_always, h_automatic, h_neverのうち一つ，v_always, v_automatic, v_neverから一つ選択して，そのOR値をattrに指定します。
h_...は水平方向，v_...は垂直方向のスクロールバーに対する指定です。
alwaysだと常に，automaticだと子を表示しきれないときのみスクロールバーが追加され，neverだとスクロールバーは表示されなくなります。

@node VStaticTextClass,  VEditTextClass, VScrollViewClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VStaticTextクラス

静的なテキストを描画するオブジェクトです。他のオブジェクト（スライダーなど）のラベルなどとして利用することができます。descriptorに指定されたテキストが描かれます。

@node VEditTextClass,  , VStaticTextClass, subClass
@comment  node-name,  next,  previous,  up
@subsection VEditTextクラス

1行だけのテキストを編集するためのボックスを作ります。

create時に，ボックス内で編集できる文字数の最大値（<=32767）を指定します。

内容の取得・設定は，ステータスのdescriptorをget_status/set_statusすることで行えます。内容が変更されると，descriptor_event_handlerが指定されていれば呼び出されます。
また，create時にattrステータスにinteger_onlyを指定すると，正の整数値のみしか入力できなくなります。また，この数値をvalueステータスを介して取得・設定することができるようになります。数値が変更されれば，value_event_handlerも指定しておくと呼び出されます。

@node InitEventloop,  , subClass, Concept
@comment  node-name,  next,  previous,  up
@section 初期化とイベントループ

v_object_init を呼び出した後，必要ならいくつかウィンドウやその他のVObjectを作り，v_object_mainを呼び出すと，メインループが始まります。
イベントハンドラなどの中で，v_object_quitを呼ぶと，メインループを抜け，プログラムを終了します。
