« 2008年04月 | メイン | 2008年06月 »



2008年05月 アーカイブ

2008年05月07日

ラテックスで手ができました。

DSCF2351.jpg このエントリの続きです。ラテックスでいくつか手を作っていくうちにうまくできました。4セットくらい作り直したのですが、最終的に出来上がったものは指もしっかりと曲がるし、丈夫にできています。\(^o^)/
カラダと足は特に問題なく作れそうなので、次の難関はカオです。ラテックスで仮面を作って、カオにギミックを仕込んで口をあけたり笑わせたり怒らせたりしたいので歯車なんかも購入してあります。
映像+によると、ナイトメアビフォークリスマスの顔のギミックは、耳からドライバーを突っ込んで回すと笑ったりするように出来ているみたいです。詳しい写真があまり載っていなかったので、いろいろ設計しながらやってみます。でかい顔になりそうです。ストップモーションのパペット造りって職人技らしいですよ。(暗に俺も職人だぞという主張をしてみました)(いやらしい)
ちなみにこれで作成された人形は、咲と五月女ではないのに使おうかと思います。

スポンサードリンク(amazon)
eizoplus.jpg
映像+ 1 (1)

[ 最近のエントリーとその関連エントリー ]


[ スポンサードリンク ]

2008年05月27日

やる夫がデザインパターンをやるようです 第16回

≪第15回第17回≫


   / ̄ ̄\  オブザーバだってのっけから言ってんだから
 /   _ノ  \ 意識して実装してもらわなきゃ困るだろ
 |    ( ●)(●)
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)






      ____   「オブザーバとは」でググっても
    /_ノ   ヽ_\ 日本語でおkなサイトしかなかったからだお
   /( ●) ( ●)\
 / ::::::⌒(__人__)⌒:::::\
 |        ̄      |
 \              /






       ____  この業界の8割は自分で言ってることが
     /⌒  ⌒\ なんだか分かってないやつばかりだお
   /( ―)  (―)\
  /::::::⌒(__人__)⌒::::: \
  |              |
  \               /






 コンポジットしているインスタンスにデリゲートして拡張し、
 具象実装に対する依存度をへらすのである。
          ____
       / \  /\  キリッ
.     / (ー)  (ー)\
    /   ⌒(__人__)⌒ \
    |      |r┬-|    |
     \     `ー'´   /
    ノ            \
  /´               ヽ
 |    l              \
 ヽ    -一''''''"~~``'ー--、   -一'''''''ー-、.
  ヽ ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒))



     |  |   |   |
     _||_||__||  ||
    (__/   `ー――
   (___/  r
    (_レノ)\   ___
    (__/__/

       ____   VIPならポンコまで読んだ
     /⌒  ⌒\  って言われるお
   /( ●)  (●)\
  /::::::⌒(__人__)⌒::::: \
  |     |r┬-|     |
  \      `ー'´     /
■コンポジットしているインスタンス
→あるクラスが保持しているメンバインスタンス
class Hoge {
	private Moge mogeInst; // <-コレ
}
■デリゲートして
→委譲する→(処理を)任して
class Hoge {
	private Moge mogeInst;
	public void method(){
		mogeInst.doit(); // <-コレ
	}
■拡張し、
→上記mogeInstは拡張したサブクラスでnewされることで処理を動的に入れ替えできる
class Hoge {
	private Moge mogeInst;
	public void setMoge( Moge param ){
		mogeInst = param; // <- コレ
	}
////////// 使うときは //////////////
hogeInst.setMoge( new SubMoge() ); // <- コレ
■具象実装に対する依存度をへらすのである。
→インターフェイスやスーパータイプへのプログラミングの
	Dog dog = new Dog(); 
	dog.bark(); // <- 犬が吠えるという具象実装がされている例
	Animal dog = getAnimal();
	// 動物インターフェイス・スーパータイプへの(吠える)実装がされている例
	dog.makeSound(); 
→前者でこれを実装したクラスは、Dogに依存し、後者は動物というインターフェイス・スーパータイプへ依存している。
               ごちゃごちゃいってねぇで
        / ̄ ̄\   コードなおせこのハゲ
      /       \ いつになったらカプセル化を覚えんだ
      |::::::        |
     . |:::::::::::     |
       |::::::::::::::    |          ....,:::´, .
     .  |::::::::::::::    }          ....:::,,  ..
     .  ヽ::::::::::::::    }         ,):::::::ノ .
        ヽ::::::::::  ノ        (:::::ソ: .
        /:::::::::::: く         ,ふ´..
-―――――|:::::::::::::::: \ -―,――ノ::ノ――
         |:::::::::::::::|ヽ、二⌒)━~~'´



    _/⌒  ⌒\_
  /:●))(__人__)((● \  はいお。。。
  |     |r┬-|     |  あんまりぶたないでほしいお。
  \      `ー'┃     /









     ____
   /      \ ( ;;;;( オブザーバ・・・?ってのは
  /  _ノ  ヽ__\) ;;;;) ヲチャ(watcher)のことらしいお
/    (─)  (─ /;;/  てことは
|       (__人__) l;;,´
/      ∩ ノ)━・'/
(  \ / _ノ´.|  |
.\  "  /__|  |
  \ /___







     ____
   /      \   NicoshDataクラスがステータスを受ける
  /  ─    ─\  ブリッジをしてくれるわけだから
/    (●)  (●) \ こいつをヲチすればいいお。。。
|       (__人__)    |
/     ∩ノ ⊃  /
(  \ / _ノ |  |
.\ “  /__|  |
  \ /___ /







     ____
   /      \  表示系のcharactericDspInstインスタンスとかが
  /  ─    ─\ NicoshDataクラスのヲチャってことかお。。
/    (○)  (○) \
|       (__人__)    |
/     ∩ノ ⊃  /
(  \ / _ノ |  |
.\ “  /__|  |
  \ /___ /








        ノ L____
       ⌒ \ / \   なぞは全てときtあろ!!!
      / (○) (○)\
     /    (__人__)   \
     |       |::::::|     |
     \       l;;;;;;l    /l!| !
     /     `ー'    \ |i
   /          ヽ !l ヽi
   (   丶- 、       しE |そ  ブヒッ!!
    `ー、_ノ       ∑ l、E ノ <
               レY^V^ヽl








   / ̄ ̄\     (こいつ今 噛んだのか?)
 /   _ノ  \   わかったようだな。
 |    ( ●)(●) オブザーバとして表示系の実装をすれば
. |     (__人__) NicoshDataクラスはそいつらの扱いが楽だろ
  |     ` ⌒´ノ NicoshDataクラスはjavaで言うObservableで
.  |         } 考えることが出来るだろう。
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)




       ____ (おならをかき消したのはばれてないみたいだお)
     /⌒三 ⌒\ じゃあ実装してみるお
   /( ―)三(―)\
  /::::::⌒(__人__)⌒::::: \
  |     |r┬-|     |
  \      `ー'´     /






public interface Observer {
	// 通知を受ける
	public void update( int hp, int sp, string itemNm );
}

public interface Subject {
	// オブザーバを登録できる。
	public void registerObserver( Observer obsrvInst );
	// 登録したオブザーバを削除できる。
	public void removeObserver( Observer obsrvInst );
	// 登録したオブザーバに通知する。
	public void notifyObservers();
}




     ____
    / ⌒  ⌒  \
  ./( ―) ( ●)  \
  /::⌒(_人_)⌒:::::  | チラッ
  |    ー       .|
  \          /







   / ̄ ̄\
 /   _ノ  \   インターフェイスは悪くないな
 |    ( ●)(●) (なんか匂うんだが。。。)
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)





public class NicoshData implements Subject {
    // 通知するオブザーバ群を保持する
    private ArrayList observers;


     ____  あとはインターフェイスのインプリメントだお
    / ⌒  ⌒  \
  ./( ―) ( ●)  \
  /::⌒(_人_)⌒:::::  | チラッ
  |    ー       .|
  \          /




   / ̄ ̄\
 /   _ノ  \   (チラチラうぜぇな)
 |    ( ●)(●) そういうことだ。
. |     (__人__) じゃあ次回はオブザーバを
  |     ` ⌒´ノ やる夫がまとめてみろ。
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)









        ノ L____
       ⌒ \ / \  おいらにまかせてくださいお!
      / (○) (○)\
     /    (__人__)   \
     |       |::::::|     |
     \       l;;;;;;l    /l!| !
     /     `ー'    \ |i
   /          ヽ !l ヽi
   (   丶- 、       しE |そ  ブヒッ!!
    `ー、_ノ       ∑ l、E ノ <
               レY^V^ヽl








   / ̄ ̄\
 /   _ノ  \   (ブヒッ・・・だと・・・?)
 |    ( ○)(○)  ・・・お、おお。がんばれ。
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)






     ____
    / ⌒  ⌒  \
  ./( ―) ( ○)U \
  /::⌒(_人_)⌒:::::  | チラッ
  |    ー    U  .|
  \          /






   / ̄ ̄\
 /   _ノ  \  (それでさっきからチラチラみてんのか)
 |    ( ○)(○)なにを俺に通知したいんだ・・・?
. | U   (__人__)
  |     ` ⌒´ノ
.  |U U      }
.  ヽ        }
実は、javaにはjava.util.Observerというインターフェイスがあります。このインターフェイスは、やる夫が書いたようにupdateというインターフェイスを持っていて、実際にはupdate(Observable o, Object arg) というメソッドをインプリメントする必要があります。
第2引数は通知内容ですが、第1引数は上記サンプルで言うSubjectインターフェイスです。なぜこのインターフェイスを渡すのかなどもあわせて次回解説したいと思います。

≪第15回第17回≫


[ 最近のエントリーとその関連エントリー ]


2008年05月26日

やる夫がデザインパターンをやるようです 第15回

≪第14回第16回≫

ネットオークションや、アマゾンなどのサービスでウォッチリストという言葉を聴いたことがありませんか。あるいは、好きなブログをRSSにて定期購読していたりしませんか。このように、ある情報や事象を監視する人たちのことをオブザーバとかって言われるのですが、デザインパターンでもオブザーバパターンというものがあります。今回はこのオブザーバパターンを使って「疎結合」についてさらに触れていきたいと思います。
   / ̄ ̄\      今回オマエに覚えておいてほしいパターンは
 /   _ノ  \    オブザーバパターンだ。
 |    ( ●)(●) オブザーバという意味は分かるか?
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)






           ____ 
        /⌒  ⌒\     まかせてくれお!
.      /( ●)  (●)\   「オブザーバとは」っと!
     / ::::::⌒(__人__)⌒::::: \ 
    |      |r┬-|     |  
     \       `ー'´     / 
    ノ            \ 
  /´               ヽ                 カ 
 |    l   l||l 从人 l||l      l||l 从人 l||l   カ    タ 
 ヽ    -一''''''"~~``'ー--、   -一'''''''ー-、.     タ 
  ヽ ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒)) 
     ┌┬┬┐┌┬┬┬┐┌┬┬┬┐┌┬┬┬┐ 
  ,. - ''"| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ρ ̄`l 
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ノ ̄ 







         会議での発言権はあるが議決権はない存在
         ____   ラテン語で監視するを意味するobsevare
      /::::::─三三─\ 会議などで特別に出席する事を許された人
    /:::::::: ( ○)三(○)\  立会人 
    |::::::::::::::::::::(__人__)::::  | ________
     \:::::::::   |r┬-|  / | |          |
    ノ::::::::::::  `ー'´   \ | |          | 







         ___
       / ⌒  ⌒\  日本語でおkなのがいっぱいだったお!
      / (●)  (●) \
    /   ///(__人__)/// \
     |   u.   `Y⌒y'´    |
      \       ゙ー ′  ,/
      /⌒ヽ   ー‐    ィヽ
      / rー'ゝ       〆ヽ
    /,ノヾ ,>      ヾ_ノ,|
    | ヽ〆        |´ | 








   / ̄ ̄\   (なんでそんなにキラキラしてんだ?)
 /   _ノ  \  そうか。デザインパターンでは総じて
 |    ( ●)(●) 「見てる人」で理解してもらえればいいだろう
. |     (__人__) オマエ向けに言うと「ヲチ」とも言える。
  |     ` ⌒´ノ オマエのブラウザのお気に入りを・・・
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)







        ノ L____
       ⌒ \ / \   そんなこと言っても
      / (○) (○)\ ブラウザの履歴は見せられないお!!
     /    (__人__)   \
     |       |::::::|     |
     \       l;;;;;;l    /l!| !
     /     `ー'    \ |i
   /          ヽ !l ヽi
   (   丶- 、       しE |そ  ドンッ!!
    `ー、_ノ       ∑ l、E ノ <
               レY^V^ヽl 

   / ̄ ̄\  いやいや前回の主張を無理にかぶせてくんなボケ
 /   _ノ  \  (満足に説明できたためしがねぇ)
 |    ( ○)(○)
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)








        ノ L____
       ⌒ \ / \   
      / (○) (○)\ googleの検索履歴も見せられないお!!
     /    (__人__)   \
     |       |::::::|     |
     \       l;;;;;;l    /l!| !
     /     `ー'    \ |i
   /          ヽ !l ヽi
   (   丶- 、       しE |そ  ドンッ!!
    `ー、_ノ       ∑ l、E ノ <
               レY^V^ヽl 
それでは早速オブザーバパターンについて見ていきます。
やる夫が今回携わるのは、ニコッシュブラザーズXというアクションゲームのキャラクターのステータス表示部分です。各々のステータスはヒットポイント(体力)・ダメージ蓄積ポイント(必殺ゲージ)・持ち物(保持アイテム)があります。
コードを見てみると非常に単純なものでした。
class NicoshData{
    public int getHitPoint();
    public int getNicoshPoint();
    public String getCurrentItem();
    public void stateChanged();
}
これらの体力や、必殺ゲージの値が誰がどうやって設定しているかは知らなくていいとのことで、またstateChangedメソッドはステータスが新しいデータに変更されるたびに呼び出されます。呼び出すタイミングなどは知りませんが、呼び出されるということだけが分かっています。
そして、これらのステータス群をグラフ表示や数値表示など様々な方法で表示するというのがやる夫の仕事です。
  把握したお。あんまりぶたないでほしいお。
    _/⌒  ⌒\_
  /:●))(__人__)((● \
  |     |r┬-|     |
  \      `ー'┃     / 







         ____ こんなん来たもんを更新していきゃいいだけだお
       /      \
      /  ─    ─\
    /    (●)  (●) \
    |       (__人__)    | ________
     \      ` ⌒´   ,/ .| |          |
    ノ           \ | |          |
  /´                 | |          |
 |    l                | |          |
 ヽ    -一ー_~、⌒)^),-、   | |_________|
  ヽ ____,ノγ⌒ヽ)ニニ- ̄   | |  | 



// メンバインスタンス
// ・・・・

// 更新時に呼ばれるらしい
public void stateChanged(){

    int hitPoint = getHitPoint();
    int nicoshPoint = getNicoshPoint();
    String itemName = getCurrentItem();

    // 数値・文字列で表示
    charactericDspInst.update( hitPoint, nicoshPoint, itemName );

    // グラフで表示
    graphDspInst.update( hitPoint, nicoshPoint, itemName );

    // イメージで表示
    imageDspInst.update( hitPoint, nicoshPoint, itemName );

}






          ____
       / \  /\  キリッ
.     / (ー)  (ー)\
    /   ⌒(__人__)⌒ \  これ以上でもこれ以下でもない
    |      |r┬-|    | 流麗なコードがかけてしまったお
     \     `ー'´   / 
    ノ            \
  /´               ヽ





        / ̄ ̄\
      /       \  正直こういうコードを書くことを期待してたわ
      |::::::        | (1発で理解されてもかなわんしな)
     . |:::::::::::     |
       |::::::::::::::    |          ....,:::´, .
     .  |::::::::::::::    }          ....:::,,  ..
     .  ヽ::::::::::::::    }         ,):::::::ノ .
        ヽ::::::::::  ノ        (:::::ソ: .
        /:::::::::::: く         ,ふ´..
-―――――|:::::::::::::::: \ -―,――ノ::ノ――
         |:::::::::::::::|ヽ、二⌒)━~~'´ 




    |┃三 ガラッ
    |┃  ____
    |┃/⌒  ⌒\
    |┃(●)  (●) \   ぎゃっは。天才は帰るお
――‐.|┃:⌒(__人__)⌒:::::\  じゃあおつかれしたーお
    |┃  |r┬-|     |⌒)
    |┃   `ー'ォ     //
    (⌒ヽ       ̄ /
    |┃ノ       /
    

   / ̄ ̄\  ( ;;;;(   
 / _ノ  ヽ\ ) ;;;;)   勝手に帰んじゃねーダボが
 |  ( ○) (○)/;;/   
. |   (__人__) l;;,    
  |    ∩ ノ)━・'/   
.  |   /  ノ´ } 
.  ヽ  / /    } 
   ヽ/ /   ノ 





          せっかくおいらのハカーがスーパーになったのに
          おまいらエラソな肩書きもってるのはダボの
          言うことはスーパーに帰ってもいいはずだから
          勝手じゃなくて肩書きがおまいらにハカーだお
                    γ ⌒⌒ヽ
   / ̄ ̄\           ( ( ヽ ) ノ
 /_ノ     \     (⌒) 三  ノ 从 ゝ
 ( ●)( ●)  ヽ   三/ | ニ  ____     (⌒)  
. | (__人__) u  }   |  |   /\  / ) し   / |  ミ 
  | ` ⌒´    ノ   !   、 /(○ )::(○ )⌒\/ | ミ
.  |         }    \./:::::::(_人_)::::::::  i'   |
.  ヽ        }      |     )ww)     |  |
   ヽ     ノ   ヘ   \    `ー"      ノ
   /    く 、_/っ/      \ .    .   \
   |     \--一''           \
    |    |ヽ、二⌒)、          \
わかったわかった





           とりあえず冷静になってくれ
           updateメソッドを使ってる3つのクラスは
   / ̄ ̄\    インターフェイスがそろってんのになんで
 /   _ノ  \  あんな硬直した使い方してるんだ?
 |    ( ●)(●)               ____
. | U   (__人__)            /      \
  |     ` ⌒´|           /─    ─  \  フヒ?
.  |        }  \      / (●) (●)    \ 
.  ヽ        }     \     |   (__人__)       |
   ヽ     ノ       \   \            _/ 
   /    く. \      \  ノ           \
   |     \  \    (⌒二              |
    |    |ヽ、二⌒)、      \         |  |
やる夫が実装した方法でももちろん実現は可能です。ですが、3つのインスタンス(charactericDspInst / graphDspInst / imageDspInst)をまともに具象実装に対してコーディングしているため、これ以外の表示系インスタンスの追加や削除を行える方法がありません。多分、「拡張をどうするのか?」と問われると「継承すればいいお!」とかいいはじめるんだと思います。
次回は、オブザーバパターンを使った解決へ進めていきたいと思います。

≪第14回第16回≫


[ 最近のエントリーとその関連エントリー ]


ペペロンチーノは今すぐ腹を切って死ぬべき

DSCF2355.jpg エントリタイトルはホッテントリメーカーで作ったので何の意味もないです。雑記をポストしたいときにホッテントリメーカー使うと面白いね。
で、先日休日出勤があったので、今日は代休で家にいます。午前中に免許証の更新に行って、午後は家内が出かけるというので料理しました。腹を切って死ぬべきかどうかはどうでもよいのですが、写真はペペロンチーノです。折角の休みなのでなにか凝ったことをやりたくて、冷凍庫で眠っていたサイコロステーキと、にんじん、玉葱、庭に生えてる西洋パセリ、胡椒、ローレルなど色々と炒めてから煮込んでダシをとりました。サイコロステーキは近所の酒屋さんで冷凍食品として購入したのですが、不味いわ脂っこいわでそのまま食べることに躊躇していたのですが、ダシになら使えそうなのでやってみたら成功しました。\(^o^)/
ペペロンチーノのパスタを茹で上げてフライパンに投入する時にこのダシをオタマでひとすくいして投入してやるとコクが深くなります(と無理にでも感じるようにしています)。ひさしぶりにペペロンチーノを作ったのですが、ニンニクがカリッとしているのとまだそこまで揚がりきってないのとがよく混ざっていて美味く出来ました。パセリは庭に生えていたやつを使っています。エコとかトレーサビリティとか言い出したいのではなく、そこにあったので使いました。(トマトとか勝手に生えてこないかなー)(近所にたくさんの畑があります)(最近野菜ドロボーがでるようです)(うそです)

[ 最近のエントリーとその関連エントリー ]


2008年05月22日

GoogleSiteと聞いて飛んでいって作った

twitterでコマネタ帳のiyoupapaさんが
iyoupapa ToDo: Google Sitesをチェックしておく
と言っていたので何も知らないワタクシはgoogleSiteをググって何なのか調べて作りましたのがこれ。うわぁ。なにに使おうかしら。
そんなことよりtwitterおもしろい。おもしろいよみんな。だれか。(エントリのタイトルを台無しにする良い例をポストしてみました)

[ 最近のエントリーとその関連エントリー ]


Ext.tree.TreePanelの使い方

simple-tree.PNG ExtJSのエントリはこちらにまとめてあります

ダウンロードページより、アーカイブ(Ext JS 2.1 SDK)をダウンロードして解凍してください。20080522時点のバージョンは ext-2.1 です。解凍したら、以下のパスのファイルを開いて見ましょう。
【パス】
ext-2.1\examples\tree\reorder.html
開いてみると、ツリーのルートノードが表示されているだけでクリックしても以下のノードが見えませんね。これはサーバサイトスクリプトを参照しに行っていて、その参照先がローカルのget-nodes.phpにあるためです。ですので直接ExtJSのTreePanelサンプルを見てみます。
このウィジェットがTreePanelと呼ばれるものです。サンプルでは(ローカルパスで言う)ext-2.1\source以下のディレクトリ構造がツリーパネルで表現されていて、ディレクトリをクリックすると以下のノード一覧をロードしてずらっと表示する仕組みになっています。今日はこのTreePanelの基本的な実装を解説してみたいと思いますが、サーバサイドスクリプト抜きで静的なツリー構造をサンプルとして使いたいと思います。あと、いきなりTreePanelとか言われても・・と言う方にはここにExtJSのチュートリアルを簡単にまとめてみました。
まず、以下に今回解説するTreePanelのソースを全て載せてみましたので、この実装方法とコンフィグを解説します。
動作サンプルとサンプルソース
Ext.onReady( function(){
    var idx = 0;
    var root  = createNode( idx++, "root", false, false ); // branch unDraggable
    var node1 = createNode( idx++, "hoge", true, true );   // leaf draggable
    var node2 = createNode( idx++, "moge", false, true );  // branch draggable
    var node3 = createNode( idx++, "piyo", true, false );  // leaf unDraggable

    root.appendChild( node1 );
    root.appendChild( node2 );
    node2.appendChild( node3 );

    var tree = new Ext.tree.TreePanel({
        title:'SimpleTree',
        width:300,
        useArrows:true,
        enableDD:true,
        root:root,
        renderTo:'renderTarget',
        tbar:[ 
            { text: 'OpenAll', handler:function(){ tree.expandAll(); } },'-',
            { text: 'CloseAll', handler:function(){ tree.collapseAll(); } },'-',
            { text: 'AddNode-Recursive', handler:function(){ 
                function recursiveNode( pNode ){
                    alert( 'this->' + this.toString() + 
                           '\ndepth:' + pNode.getDepth() + 
                           '\ntext:' + pNode.text + 
                           '\nid:' + pNode.id );
                    pNode.eachChild( recursiveNode );
                    if( !pNode.isLeaf() ){
                        var setIdx = idx++;
                        pNode.appendChild( createNode( setIdx, 'add-' + setIdx, false, true ) );
                    }
                };
                root.eachChild( recursiveNode );
                tree.expandAll();
            }}
        ]
    });
    root.expand();
//    node2はデフォルトクローズの状態
//    node2.expand();
    function createNode( id, text, isLeaf, isDrag ){
        return new Ext.tree.TreeNode({
            draggable:isDrag,
            id:id,
            text:text,
            leaf:isLeaf
        });
    }
});

【Ext.tree.TreePanelの解説】

それではTreePanelを見ていきたいと思います。
    var tree = new Ext.tree.TreePanel({
という箇所がツリーパネルそのものになります。ツリーを表現する以上、ノードとなるデータがひとつ以上必要になってきて、そのデータコンテンツはTreeNodeというクラスインスタンスを使うことになります。GridPanelやDataViewで使ったデータストアとは違ってくるようです。
ドキュメントには、以下のようにTreePanelがレンダリングされる前までに、コンフィグオプションのrootに有効なノードが入っていてくれとあります。コンフィグオプションのrootに直接突っ込んでもいいし、rootに対するセッターであるsetRootNode()メソッドでもよいとのことです。
A TreePanel must have a root node before it is rendered. This may either be specified using the root config option, or using the setRootNode method.
それではツリーパネルのコンフィグオプションを見てみます。
といっても、先述のとおり重要なコンフィグオプションはrootだけです。ここには次に述べるrootというTreeNodeのインスタンスを設定してあげてきます。
enableDD:true,は、ノードのドラッグアンドドロップが出来るかどうかです。TreeNodeインスタンスを作成するときにノード1つ1つに対してドラッグアンドドロップの設定が出来るのですが、TreePanelでfalseにすると全てのノードに対してドラッグアンドドロップが無効になります。
useArrows:true,は、表示系のコンフィグオプションで、これがfalseだとwindowsVista以前のエクスプローラのような[+]とか[-]のドリル表示になります。trueだとアロー型のドリル表示になります。
    var tree = new Ext.tree.TreePanel({
        title:'SimpleTree',
        width:300,
        useArrows:true,
        enableDD:true,
        root:root,
        renderTo:'renderTarget',
続いてtbarというコンフィグオプションを設定していますが、この部分は最後に記述したいと思います。

【TreeNodeの解説】

次は、実際のデータであるTreeNodeの部分を見ていきます。
    function createNode( id, text, isLeaf, isDrag ){
        return new Ext.tree.TreeNode({
            draggable:isDrag,
            id:id,
            text:text,
            leaf:isLeaf
        });
    }
メソッドcreateNodeはワタシが勝手に作ったメソッドです。このメソッドはパラメータに従ってTreeNodeをnewして返すだけのものですので特に細かい解説はいらないかと思います。

ではTreeNodeのコンフィグオプションを見ていきます。まず、draggable:isDrag,はそのノードがドラッグアンドドロップできるかどうかを表していて、今回はパラメータに依存するつくりになっていて、trueでそのノードがドラッグアンドドロップできるようになり、falseで出来なくなります。
続いてidはそのツリー構造内のidを表すものです。明示的に設定しなくても勝手に振ってくれるようですが、ツリー構造内で一意にノードを特定したりすることがあるかと思いますので実装者が設定してあげたほうがいいと思います。ちなみに一意でなくとも動くには動くようです。
textは、そのままそのノードのテキスト表示部分です。このテキスト部分にはhrefというコンフィグオプションを加えることによってアンカーリンクを貼ることが出来ます。さらにhrefTargetでターゲットフレームの指定も出来ます。
最後のleafは、そのノードがリーフ(末端)であるかどうかです。leaf:trueですと、そのノード以下に子ノードを与えることが出来ません。leaf:falseだとブランチ(枝)を表していて子ノードを追加することが出来ます。

【Toolbarの解説】

最後にTreePanelの残りのコンフィグオプション、tbarについて解説したいと思います。tbarというコンフィグオプションはExt.Panelクラスを継承しているクラスであれば使えるコンフィグオプションです。~Panelという以下のパネル一覧であれば使えます。また、tbarはパネル上部にレンダリングされ、bbarはパネルの下部にレンダリングされます。

<パネル一覧>
EditorGridPanel Ext.grid.EditorGridPanel
FormPanel Ext.form.FormPanel
GridPanel Ext.grid.GridPanel
Panel Ext.Panel
TabPanel Ext.TabPanel
TreePanel Ext.tree.TreePanel
このtbarやbbarの実体はExt.Toolbarなのですが、このコンストラクタが以下のように追加したいボタンオブジェクトのコンフィグを配列としてパラメータに与えることが出来るので非常に分かりやすいです。
tbar:[ 
    { text: 'OpenAll', handler:function(){ tree.expandAll(); } },'-',
    { text: 'CloseAll', handler:function(){ tree.collapseAll(); } },'-',
    { text: 'AddNode-Recursive', handler:function(){ 
        function recursiveNode( pNode ){
            alert( 'depth:' + pNode.getDepth() + '\ntext:' + pNode.text + '\nid:' + pNode.id );
            pNode.eachChild( recursiveNode );
            if( !pNode.isLeaf() ){
                var setIdx = idx++;
                pNode.appendChild( createNode( setIdx, 'add-' + setIdx, false, true ) );
            }
        };
        root.eachChild( recursiveNode );
        tree.expandAll();
    }}
]
もうちょっと詳しく説明すると、上記のようにオブジェクトを配列で渡した場合、その1つ1つはExt.Toolbar.Buttonオブジェクトを表しています。→APIドキュメント
Ext.Toolbar.Buttonのコンフィグオプションには、上記のようにtextとhandlerをあたえれば、その表示と挙動を実装することが出来ます。コンフィグオプションにxtypeと言うものがあるのですが、これを与えないで置くと、デフォルトでtbbuttonでレンダリングされ、xtype:'tbsplit'とするとボタンの横に▼が表示されてメニュードロップの表示が出来るようになります。また、ボタンとボタンの間にセパレータ(|←こんなの)を表示させたい場合は、配列の要素として文字列の'-'を与えます。以下にToolbarコンポーネントのxtype一覧を記します

<Toolbar components:xtype一覧>
Toolbar components
---------------------------------------
toolbar          Ext.Toolbar
tbbutton         Ext.Toolbar.Button
tbfill           Ext.Toolbar.Fill
tbitem           Ext.Toolbar.Item
tbseparator      Ext.Toolbar.Separator
tbspacer         Ext.Toolbar.Spacer
tbsplit          Ext.Toolbar.SplitButton
tbtext           Ext.Toolbar.TextItem
実装の解説に戻りますが、handlerの内容は、上からノードヒエラルキーの全体オープンとクローズです。tree.expandAll() / tree.collapseAll()を使っています。
最後のAddNode-Recursiveと言うボタンは、ハンドラにちょこちょこ実装が入っていますが、内容はルートノードから全てのノードをアラートして、そのノードがブランチである場合、直下に1つブランチを追加していく実装となっています。
    { text: 'AddNode-Recursive', handler:function(){ 
        function recursiveNode( pNode ){ /* ... */ };
        root.eachChild( recursiveNode );
        tree.expandAll();
    }}
途中にrecursiveNodeというメソッドの定義がハンドラの中に入ってきていますのでちょっと分かりにくいですが、recursiveNodeを省いて見ると、このハンドラは
・ルートノードが持つ子ノード毎にrecursiveNodeと言うメソッドを呼んで
・最後にツリーを開くと言う処理だけです。
その"ノード毎に..."というところでeachChildメソッドが出てきましたので最後にTreeNodeに戻って解説します。
eachChild( Function fn, [Object scope], [Array args] ) : void
このメソッドはTreeNodeのメソッドなのですが、ノードが持つ子ノード分イテレートしてFunction fnを呼び出すというものです。第2引数のスコープは実際に与えるか、与えないとイテレート中のカレントのノードがFunction fnに与えられるみたいです。第3引数の"引数"も同様です。
ですので、function recursiveNode( pNode )の引数pNodeにはイテレート中のカレントノードが与えられてきます。そこから引数のpNodeで、さらにeachChildを呼び出して再帰します。再帰した後、ノードがブランチであれば、さらにブランチを追加すると言う仕組みになっています。

【余談】

1.マウスでノードをぐりぐりとドラッグアンドドロップしてみると、ちゃんとDepthが変わってくれます。ツリー構造とデータをそのまま維持しながらどこかにポストしたいとかがあれば、(jsonやXMLに変換する必要があるかもしれませんが)それも可能のようです。

2.今回はノードデータを自前で実装しましたが、Tree.TreeLoaderというデータのローダがあります。とても便利です。


というわけで、TreePanelの解説をしてみました。ワタシの理解を多分に含めておりますので、誤った情報である可能性がありますのでご注意ください。

[ 最近のエントリーとその関連エントリー ]


2008年05月19日

ノードビューアブックマークレット作ったよ

nodeviewer.PNG firebugをいろいろいじくってまして、ウェブ関係の開発に使えそうなブックマークレットを作りました。ウェブ開発に使えそうとか言いながらIEでは動かないという素敵な仕様です。

nodeViewerブックマークレット

ブックマークレットを起動すると、HTMLのbodyにマウスオーバとかのイベントを追加していきますので、どこかをクリックすると、そのノードが持つオブジェクトを捜査してgridで表示します。

あと、関係ないけど、twitterがおもしろそうなので登録しました。正確に言うと、登録して放置していたのですが面白そうなので再開です。友達いませんのでどなたか友達になってください!

[ 最近のエントリーとその関連エントリー ]


2008年05月17日

ついカッときてやる夫ケータイストラップ作った

         ____
       /::::::::::  u\ 
      /:::::::::⌒ 三. ⌒\ ち、ちんこもついてるお。。。 
    /:::::::::: ( ○)三(○)\          
    |::::::::::::::::⌒(__人__)⌒  | 
     \::::::::::   ` ⌒´   ,/ 
    ノ::::::::::u         \ 
DSCF2353.jpg 紙粘土でつくったやる夫にラテックスをコーティングして型を取りました。さらに型に石膏を流し込んでやる夫携帯ストラップの出来上がりです。無駄に量産中です。
刺身の上にタンポポのせる仕事の採用試験に受かったお!」のポーズをしています。

[ 最近のエントリーとその関連エントリー ]


2008年05月15日

ExtJSをfirebugでデバッグする便利な方法

firebugonextjs01.PNG
firebugonextjs02.PNG
firebugonextjs03.PNG
firebugonextjs04.PNG
firebugonextjs05.PNG
firebugonextjs06.PNG
firebugonextjs07.PNG
firebugonextjs08.PNG
firebugonextjs09.PNG
firebugonextjs10.PNG
firebugonextjs11.PNG
これまでにExtJSの使い方を何度かポストしていて、日本語のチュートリアルがあることもポストしましたが、チュートリアルのほとんどは英語で書かれています。ので、しっかりと読むには腰をすえなければならず、ちょこちょことtipsなんかを斜め読みしていたのですが、このページにExtJSの作りこみやデバッグを飛躍的に向上させる方法が載っていました。

javascriptのデバッグというとFireFoxプラグインのfirebugを思い浮かべます。そのとおり上記チュートリアルもfirebugを使ったデバッグです。もちろんこのブログで紹介しているExtJS関連のポストもfirebugを使ってデバッグしてはいますが、あまり使い込んでおらず適宜ブレークポイントを置いて変数なんかをウォッチする程度のものでした。知らなかったのはコンソールにスクリプトを直接書いて実行させることが出来るってことです。え・・・それって常識・・・とかドン引きされることかと思いますが、コンソールにスクリプトを直接書いて実行出来るらしいですよ!(同じことを2度言ってみました)(恥ずかしい子!)

恥ずかしい子はどうでもよいのですが、上記ページのチュートリアルを引用してキャプチャをいくつか追加しながらポストしたいと思います。
ココまで読んでいる方なら以下の資材はお持ちかと思いますが一応リンクしておきます。 firefoxをインストールしてfirebugを入れたらfirefoxでExt2.1-API Dcumentationを開きます。なぜこのページを開くのかと言いますと理由は単純でExtJSが全てロードされているためです。
開きましたら図のようにfirebugを立ち上げます。
ツール>Firebug>Open Firebugで開きます。
次にEnable FirebugをクリックしてこのExt2.1-API Dcumentationページをデバッグできる状態にします。
さらにConsoleタブをクリックして、コンソールを開きます。右ペインの複数行入力できるコンソールが開いていなければ右下のアイコンをクリックしてペインを開きます。
開いたらこのコンソールに以下のコードを入力し、RunをクリックするかCTRL+ENTERを押下します。
Ext.get(document.body).update('<div id="test"></div>');
このコードはページのdocument.bodyを取得し、そのinnerHTMLをdiv id="test"で更新すると言うものです。HTMLタブをクリックしてbodyノードを開くとinnerHTMLが<div id="test"></div>になっていることが確認できます。同時に画面からコンテンツが消えます。コンテンツは消えますが、ExtJSのライブラリはロードされたままですので、コイツを利用してスクリプトのテストが行えるんです。

ためしに、
new Ext.Panel({
    renderTo: 'test',
    width: '200px',
    title: 'My Title',
    html: 'My HTML content'
});
をコンソールにコピペ(追記)してCTRL+ENTERを押下します。すると、Ext.Panelが表示されます!
    renderTo: 'test',
というコンフィグオプションでdiv id="test"をレンダリング先としていますので、1行目は消さないでください。続けて、html: 'My HTML content'というコンフィグオプションの直後に
    ,collapsible : Boolean
を挿入してみます。地味ですが、パネルのタイトルバー右に[▲]アイコンが表示され、パネルのボディが開いたり閉じたり出来るようになりました!ということはAPI DocumentationにあるExtクラスのメソッドや、コンフィグなどがリアルタイムにどんなものなのか確認できるようになったということですね。うわーすげー便利だ。

では次にrenderTo: 'test',と言う箇所を// でコメントアウトします。
    //renderTo: 'test',
画面からパネルが消えますので,collapsible : Booleanの直後に以下のコードを挿入します。
    ,x: 100
    ,y: 100
    ,renderTo: Ext.getBody()
    ,floating: true
    ,frame: true
    ,height: 200
    ,draggable: {
        insertProxy: false,
        onDrag : function(e){
            var pel = this.proxy.getEl();
            this.x = pel.getLeft(true);
            this.y = pel.getTop(true);
            var s = this.panel.getEl().shadow;
            if (s) {
               s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
            }
        },
        endDrag : function(e){
            this.panel.setPosition(this.x, this.y);
        }
    }
すると、パネルがドラッグ&ドロップできるようになりました!
というわけで、日本語チュートリアルと全然変わりありませんが知ってるのと知らないのでは大違いなのでポストしてみました。何が一番びっくりしたのかと言いますと、このコンソールの使い方がgetfirebug.comにデカデカと載っていたことです。あーびっくりした。(しらじらしい)

[ 最近のエントリーとその関連エントリー ]


2008年05月13日

Ext.DataViewの使い方

simpledataview.PNG ExtJSのエントリはこちらにまとめてあります

ダウンロードページより、アーカイブ(Ext JS 2.1 SDK)をダウンロードして解凍してください。20080513時点のバージョンは ext-2.1 です。解凍したら、以下のパスのファイルを開いて見ましょう。
【パス】
ext-2.1\examples\view\data-view.html
開いてみると、何も見えませんね。これはサーバサイトスクリプトを参照しに行っていてその参照先がローカルのget-images.phpにあるためです。ですので直接ExtJSのDataViewサンプルを見てみます。
このウィジェットがDataViewと呼ばれるものです。サンプルではサムネイル画像がならんでいて、マウスをドラッグするか、CTRLまたはSHIFTキーを押しながら選択すると複数のアイテムが選択できるようになっています。今日はこのDataViewの基本的な実装を解説してみたいと思います。あと、いきなりDataViewとか言われても・・と言う方にはここにExtJSのチュートリアルを簡単にまとめてみました。
まず、以下に今回解説するDataViewのソースを全て載せてみましたので、この実装方法とコンフィグを解説します。
動作サンプルとサンプルソース
Ext.onReady( function(){
    var lookup = {};

    var siteData = [
        ['http://mojalog.com','http://capture.heartrails.com/small?http://mojalog.com','mojalog'],
        ['http://google.co.jp','http://capture.heartrails.com/small?http://google.co.jp','google'],
        ['http://yahoo.co.jp','http://capture.heartrails.com/small?http://yahoo.co.jp','yahoo'],
        ['http://extjs.com','http://capture.heartrails.com/small?http://extjs.com','extjs'],
        ['http://capture.heartrails.com','http://capture.heartrails.com/small?http://capture.heartrails.com','heartrails' ],
        ['http://youtube.com','http://capture.heartrails.com/small?http://youtube.com','youtube' ]
    ];

    var store = new Ext.data.SimpleStore({
        fields: [
           { name: 'siteurl'},
           { name: 'imgurl' },
           { name: 'name'   }
        ],
        data : siteData
    });

    var formatData = function(data){
        lookup[data.name] = data;
        return data;
    };

    var view = new Ext.DataView({
        tpl: new Ext.XTemplate(
            '<tpl for=".">',
                '<div class="thumb-wrap" id="{name}">',
                '<div class="thumb"><img src="{imgurl}" title="{name}"></div>',
                '<span>{name}</span>',
                '</div>',
            '</tpl>'
        ),
        singleSelect: true,
        overClass:'x-view-over',
        itemSelector: 'div.thumb-wrap',
        store: store,
        listeners: {
            'dblclick':{
                fn:function(){
                    var selNode = view.getSelectedNodes()[0];
                    var data = lookup[selNode.id];
                    location.href=data.siteurl;
                }
            }
        },
        prepareData: formatData.createDelegate( this )
    });

    var panel = new Ext.Panel({
        id: 'img-chooser-view',
        title: 'DataView',
        renderTo: 'container',
        width:320,
        autoScroll: true,
        items:view,
        collapsible:true
    });
});

【Ext.DataViewの解説】

それではDataViewを見ていきたいと思います。
    var view = new Ext.DataView({
という箇所がデータビューそのものになります。前回のgridと同様にstoreというデータストアを保持していてこのstoreの内容がデータの実体になります。
DataViewのコンフィグオプションで必須となるのはitemSelectorと言うもののようです。
itemSelector : String
This is a required setting. A simple CSS selector (e.g. div.some-class or span:first-child) that will be used to determine what nodes this DataView will be working with.
とあり、これはDataViewがどのノードで動いているかを決定するために使われる、CSSセレクタというものらしいです。今回は値に'div.thumb-wrap'を持たせてあります。このノードを「データビューのデータとして扱います」ということになるんだと思います。
ちなみにdiv.thumb-wrapは、次のtplというコンフィグオプションで定義します。

tplは、以下のように定義してあります。

        tpl: new Ext.XTemplate(
            '<tpl for=".">',
                '<div class="thumb-wrap" id="{name}">',
                '<div class="thumb"><img src="{imgurl}" title="{name}"></div>',
                '<span>{name}</span>',
                '</div>',
            '</tpl>'
        ),
このtplはExt.XTemplateを使ってテンプレートとして用いているのですが、このXTemplateが非常に強力で、tplノードのアトリビュートを使って演算を行い、実データをオートフィリングしてくれます。上記ではforという演算式を用いて、store内の複数データをスコープ内のタグに埋めていくようになっていますが、if演算式や内臓テンプレート変数、インラインコードの実行なんかも出来るようです。使いこなせればデータのデータのフィルタなんかも出来そうですね。XTemplateのAPIDocを貼っておきます。
上記は、{}で括られた name / imgurl をforで展開しています。このnameとimgurlはstoreのfieldsで定義した名前です。
DataViewの基本的なコンフィグオプションはこのくらいで、後はオプションみたいなものです。

overClassはマウスオーバー時のclassを値として持たせています。singleSelectはアイテムを複数選択状態に出来ないようにするものです。これに対してmultiSelectと言うものがあり、このコンフィグオプションを使用してtrueにしておくと、CTRLやSHIFTを押しながら複数選択することが出来ます。
    overClass:'x-view-over',
    singleSelect: true,
'x-view-over'はスタイルシート内に定義していて、マウスオーバーしたときに表示が変わると言うものです。無くてもいいと思います。

最後にlistenersとprepareDataを解説します。
    listeners: {
        'dblclick':{
            fn:function(){
                var selNode = view.getSelectedNodes()[0];
                var data = lookup[selNode.id];
                location.href=data.siteurl;
            }
        }
    },
    prepareData: formatData.createDelegate( this )
listenersはイベントリスナーのことです。今回はダブルクリックした際のイベントを拾って画面遷移を行っています。DataViewのgetSelectedNodes()で選択されたノードを返しますので、その先頭を拾ってstoreに格納したデータのsiteurlを解決しています。
prepareDataはメソッドなのですが、ロード時にキックされてデータの準備を行うもののようです。今回はformatDataメソッドにその処理を委譲していてlookupオブジェクトに、各データを突っ込んでいっています。lookupオブジェクトは、選択されたデータを探すために利用しています。
    var selNode = view.getSelectedNodes()[0];
    var data = lookup[selNode.id];
この2行はまず、DataViewで選択されたノードを取り出します。次に、selNode.idをlookupの連想配列のkeyとして指定して、該当のデータを特定します。これで、data.siteurlとか、data.nameとか、data.imgurlで参照が出来るようになっています。
selNode.idのidは前述のテンプレート定義の中の
    '<div class="thumb-wrap" id="{name}">',
にあるように、ノードのidを指しているのですが、この値はstoreのfieldsの{name}が置かれています。
ロード時に、prepareDataで委譲したformatDataメソッドが呼ばれてlookupオブジェクトのkeyであるdata.nameに対してdataがドカドカと格納されていきます。
    var formatData = function(data){
        lookup[data.name] = data;
        return data;
    };
これでlookupのkeyはnameで解決できると言うことです。(firebugで分かりました。)

というわけで、DataViewの解説をしてみました。ワタシの理解を多分に含めておりますので、誤った情報である可能性がありますのでご注意ください。

[ 最近のエントリーとその関連エントリー ]