Groovyistからのステキなクリスマスプレセントだ #advent2011

みなさんクリスマスプレゼントはもらえた?
もらえた人も、もらえなかった人も、ここにいいモノがあるよ。


アイディアと情熱をもったGroovyistからのステキなクリスマスプレゼント。
ブログを読んだら、Groovyを読試したくなること間違いなし。


【Day 01】プログラミングGROOVYに書いてないけど、便利なGroovyプロダクト
【Day 02】G*と言えば猫、ということで子猫Tube作りました
【Day 03】LupinFX
【Day 04】Groovyを野良ビルドしてみよう
【Day 05】Spockでデータドリブンなテスト
【Day 06】GrailsのプラグインリポジトリとしてGithubを使う
【Day 07】Handy Gradle startup script
【Day 08】Groovy Eclipse Pluginのあれこれ
【Day 09】Gradleビルドランゲージリファレンス
【Day 10】GroovyでVert.x
【Day 11】resolveStrategy の基礎
【Day 12】私がGroovyを好きな9つの理由 2011年版
【Day 13】G5、それはGroovy使いの為のスライドショーツール
【Day 14】grailsでwebアプリをつくってみる(つくってみた(手直しした))。
【Day 15】Grailsをインタラクティブに使う!
【Day 16】GroovyとQuartzとTwitter APIとTwitter4Jの甘い関係
【Day 17】自分のPCにある写真をPicasa webに丸ごとアップ
【Day 18】G*アドベンドカレンダー JGRの文法比較
【Day 19】ドメインを取得しました
【Day 20】groovyコマンドオプション一巡り
【Day 21】恥ずかしくて今さら聞けない、GMongo講座 2
【Day 22】Groovyの疑似デバッガgdb
【Day 23】Grettyで割り勘計算機
【Day 24】MerryChristmas!!
【Day 25】groovyでTestNGのテストコードを書いてみよう



Groovyのイベントでは恒例(?)のイラストも

画:[twitter:@amamidokoro]



画:[twitter:@torazuka ]
うわっ、本家からも出た。





たぶん、明日も勝手に延長戦が始まったりするだろうけど、一旦まとめ。


JavaFXは、webkitベースの内蔵ブラウザがあるので、Greziを使って表示してみた。
来年の技評のAdvent Calendarの例に載るような綺麗な「まとめ」は、
Grails、Griffon、GwebGebとかを使って、きっとあの人たちから出るだろう。(/ω・\)チラッ [twitter:@jggug]
epub化はきっとあの人だな。

動画

注意事項

  • 音声はなし。(クリスマスソングでも流せばよかった・・・)
  • 全体的に長い。(全文表示じゃなくて、さわりだけにしておけばよかった・・・)
  • 遅い(動作が遅いのは、6年前のPCで、録画までしてるので・・・)

「【Day 02】G*と言えば猫、ということで子猫Tube作りました」でGistのソースを表示するのに30秒ぐらいかかる。



最大化状態でズームアウトすると、ぬるぽで操作不能になるので、
Day 25 の表示後を、サイズを変えて撮り直した。。。




ソース

Greziに添付されてるサンプルの「Slideshows.grezi.groovy」ベースに作成した。

import javafx.scene.web.WebView


showGreziLogo = false



gAdeventCalednar = [
    'day01':['url':'http://d.hatena.ne.jp/kyon_mm/20111201/1322745407'
             ,'title':'【Day 01】\nプログラミングGROOVYに書いてないけど、\n便利なGroovyプロダクト'
             ,'twitterId':'@kyon_mm'
             ,'x':1600
             ,'y':400
             ]
             
   ,'day02':['url':'http://d.hatena.ne.jp/nobusue/20111201/1322755210'
            ,'title':'【Day 02】\nG*と言えば猫、\nということで子猫Tube作りました'
            ,'twitterId':'@nobusue'
            ,'x':1400
            ,'y':200
            ]
             
   ,'day03':['url':'http://d.hatena.ne.jp/ksky/20111203'
            ,'title':'【Day 03】\nLupinFX'
            ,'twitterId':'@kazuchika'
            ,'x':1000
            ,'y':200
            ]
            
   ,'day04':['url':'http://d.hatena.ne.jp/nobeans/20111204/1322990018'
             ,'title':'【Day 04】\nGroovyを野良ビルドしてみよう'
             ,'twitterId':'@nobeans'
             ,'x':400
             ,'y':400
             ]
             
   ,'day05':['url':'http://d.hatena.ne.jp/kiy0taka/20111205/1323096586'
             ,'title':'【Day 05】\nSpockでデータドリブンなテスト'
             ,'twitterId':'@kiy0taka'
             ,'x':200
             ,'y':600
             ]
             
   ,'day06':['url':'http://monochromeroad.blogspot.com/2011/12/grailsgithub.html'
             ,'title':'【Day 06】\nGrailsのプラグインリポジトリ\nとしてGithubを使う'
             ,'twitterId':'@literalice'
             ,'x':200
             ,'y':800
             ]
             
   ,'day07':['url':'http://d.hatena.ne.jp/masanobuimai/20111207#1323184521'
             ,'title':'【Day 07】\nHandy Gradle startup script'
             ,'twitterId':'@masanobuimai'
             ,'x':400
             ,'y':1000
             ]
             
   ,'day08':['url':'http://d.hatena.ne.jp/ikikko/20111208/1323355440'
             ,'title':'【Day 08】\nGroovy Eclipse \nPluginのあれこれ'
             ,'twitterId':'@ikikko'
             ,'x':600
             ,'y':1200
             ]
             
   ,'day09':['url':'http://d.hatena.ne.jp/nightmare_tim/20111208/1323377316'
             ,'title':'【Day 09】\nGradleビルド\nランゲージリファレンス'
             ,'twitterId':'@nightmare_tim'
             ,'x':1000
             ,'y':1200
             ]
             
   ,'day10':['url':'http://d.hatena.ne.jp/touchez_du_bois/20111210/1323514015'
             ,'title':'【Day 10】\nGroovyでVert.x'
             ,'twitterId':'@touchez_du_bois'
             ,'x':1400
             ,'y':1200
             ]
             
   ,'day11':['url':'http://d.hatena.ne.jp/bikisuke/20111211/1323615558'
             ,'title':'【Day 11】\nresolveStrategy の基礎'
             ,'twitterId':'@bikisuke'
             ,'x':1400
             ,'y':1000
             ]
             
   ,'day12':['url':'http://d.hatena.ne.jp/fumokmm/20111212/1323641207'
             ,'title':'【Day 12】\n私がGroovyを\n好きな9つの理由 2011年版'
             ,'twitterId':'@fumokmm'
             ,'x':1000
             ,'y':800
             ]
             
   ,'day13':['url':'http://nagaimasato-ja.blogspot.com/2011/12/g-advent-calendar121313-groovyg5-new-g5.html'
             ,'title':'【Day 13】\nG5、それはGroovy使いの為の\nスライドショーツール'
             ,'twitterId':'@nagai_masato'
             ,'x':1400
             ,'y':800
             ]
             
   ,'day14':['url':'http://tamata.xmldo.com/2011/12/214.html'
             ,'title':'【Day 14】\ngrailsでwebアプリを\nつくってみる(つくってみた(手直しした))。'
             ,'twitterId':'@tamatamatamata'
             ,'x':1800
             ,'y':800
             ]
             
   ,'day15':['url':'http://d.hatena.ne.jp/mottsnite/20111215/1323924066'
             ,'title':'【Day 15】\nGrailsを\nインタラクティブに使う!'
             ,'twitterId':'@tyama'
             ,'x':3400
             ,'y':400
             ]
             
   ,'day16':['url':'http://samuraism.jp/diary/2011/12/16/1323962040000.html'
             ,'title':'【Day 16】\nGroovyとQuartzと\nTwitter APIと\nTwitter4Jの甘い関係'
             ,'twitterId':'@yusukey'
             ,'x':2600
             ,'y':600
             ]
             
   ,'day17':['url':'http://d.hatena.ne.jp/nemo_kaz/20111216'
             ,'title':'【Day 17】\n自分のPCにある写真を\nPicasa webに丸ごとアップ'
             ,'twitterId':'@nemo_kaz'
             ,'x':3400
             ,'y':600
             ]
             
   ,'day18':['url':'http://blog.livedoor.jp/bbcafe_yuja/archives/1184436.html'
             ,'title':'【Day 18】\nJGRの文法比較'
             ,'twitterId':'@Boc963proguram'
             ,'x':4200
             ,'y':600
             ]
             
   ,'day19':['url':'http://d.hatena.ne.jp/ko1kun/20111219/1324306744'
             ,'title':'【Day 19】\nドメインを取得しました'
             ,'twitterId':'@ko1kun'
             ,'x':2800
             ,'y':800
             ]
             
   ,'day20':['url':'http://d.hatena.ne.jp/irof/20111220/p1'
             ,'title':'【Day 20】\ngroovyコマンドオプション一巡り'
             ,'twitterId':'@irof'
             ,'x':3400
             ,'y':800
             ]
             
   ,'day21':['url':'http://mikeneck.blogspot.com/2011/12/gmongo-2_21.html'
             ,'title':'【Day 21】\n恥ずかしくて\n今さら聞けない、GMongo講座 2'
             ,'twitterId':'@mike_neck'
             ,'x':4000
             ,'y':800
             ]
             
   ,'day22':['url':'http://d.hatena.ne.jp/uehaj/20111222'
             ,'title':'【Day 22】\nGroovyの疑似デバッガgdb'
             ,'twitterId':'@uehaj'
             ,'x':2600
             ,'y':1000
             ]
             
   ,'day23':['url':'http://d.hatena.ne.jp/toby55kij/20111223/1324568112'
             ,'title':'【Day 23】\nGrettyで割り勘計算機'
             ,'twitterId':'@toby55kij'
             ,'x':3400
             ,'y':1000
             ]
             
   ,'day24':['url':'http://d.hatena.ne.jp/orangeclover/20111224/1324715531'
             ,'title':'【Day 24】\nMerryChristmas!!'
             ,'twitterId':'@orange_clover'
             ,'x':4200
             ,'y':1000
             ]
             
   ,'day25':['url':'http://d.hatena.ne.jp/kimukou_26/20111225'
             ,'title':'【Day 25】\ngroovyでTestNGの\nテストコードを書いてみよう'
             ,'twitterId':'@kimukou_26'
             ,'x':3400
             ,'y':1200
             ]
]

def view = new WebView(layoutX: 30, layoutY: 30, visible: false, opacity: 0.0)

def switchWebWiew

map = {
    switchWebWiew = { event ->
        if (view.opacity == 0) {
            mapGroup.effect = boxBlur(width: 10, height: 10, iterations: 3)
            

            view.engine.load(gAdeventCalednar[event.source.id].url)

            view.visible = true
            view.requestFocus()
            
            timeline {
                at(900.ms) {
                    change(view, 'opacity') { to 0.8 }
                }
            }.play()
        } else {
            map.effect = null
            view.opacity = 0.0
            view.visible = false
            mapGroup.effect = boxBlur(width: 0, height:0, iterations: 0)
        }
    }

    gAdeventCalednar.each { k, v ->
        path << hbox(layoutX: v.x, layoutY: v.y, onMousePressed: focusOnNode) {
            label(font: '30pt', v.title + '\n' + v.twitterId)
            label(id: k, styleClass: 'start-label', 'ブログ', onMousePressed: switchWebWiew)
        }
    }


}

withScene = { scene ->
    scene.stylesheets.add("file:///${System.getProperty('user.dir')}/presentations/Slideshows/style.css".toString())

    scene.root.children.add(view)
    view.prefWidthProperty().bind(scene.widthProperty().subtract(60))
    view.prefHeightProperty().bind(scene.heightProperty().subtract(60))

    def label = label(styleClass: 'exit-label', 'exit', visible: bind { view.visible }, onMousePressed: switchWebWiew)
    scene.root.children.add(label)
}

実行方法

C:\usr\opt\grezi>gradle grezi -Ppresentation=.\presentations\gadvent2011\present2you\Present2you.grezi.groovy

問題点

ブログを表示してから、戻ったときに、ピントが合わない。
どうすればいいんだろうか。
あと、Slidshareの埋め込みHTMLは表示できたけど、Youtubeの埋め込みHTMLは表示できないようだ。
goovyist.jpのドメインは、(録画したときには)HTMLにcharsetが指定されてないから文字化けしてた。(これはしゃーないな)



JavaFXもGroovyFXも分からないまま、すっ飛ばして、Greziをいじってるので、
ハマると対処のしようがなかったりする。
それでも、Greziを使うと、最小限のコードで遊べてしまうので楽しい。




本編よりも作るのに時間がかったのだが、自分のブログが鬼門だった。
ソースコードの箇所を表示しようとすると、ぬるぽ・・・><。

java.lang.NullPointerException
        at com.sun.prism.impl.BaseResourceFactory.createTexture(BaseResourceFactory.java:116)
        at com.sun.prism.impl.BaseResourceFactory.createTexture(BaseResourceFactory.java:103)
        at com.sun.webpane.sg.prism.WCImageImpl.getTexture(WCImageImpl.java:120)
        at com.sun.webpane.sg.prism.WCGraphicsPrismContext.drawImage(WCGraphicsPrismContext.java:621)
        at com.sun.webpane.platform.graphics.GraphicsDecoder.drawImage(GraphicsDecoder.java:428)
        at com.sun.webpane.platform.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:171)
        at com.sun.webpane.platform.graphics.WCRenderQueue.decode(WCRenderQueue.java:72)
        at com.sun.webpane.platform.WebPage.paint2GC(WebPage.java:678)
        at com.sun.webpane.platform.WebPage.paint(WebPage.java:658)
        at com.sun.javafx.sg.prism.NGWebView.renderContent(NGWebView.java:71)
        at com.sun.javafx.sg.prism.NGNode.renderOpacity(NGNode.java:439)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:182)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:42)
        at com.sun.javafx.sg.BaseNode.render(BaseNode.java:1131)
        at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:205)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:188)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:42)
        at com.sun.javafx.sg.BaseNode.render(BaseNode.java:1131)
        at com.sun.javafx.tk.quantum.PaintRunnable.doPaint(PaintRunnable.java:217)
        at com.sun.javafx.tk.quantum.PaintRunnable.paintImpl(PaintRunnable.java:148)
        at com.sun.javafx.tk.quantum.PaintRunnable.run(PaintRunnable.java:329)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)
        at com.sun.prism.render.RenderJob.run(RenderJob.java:29)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at com.sun.javafx.tk.quantum.QuantumRenderer$dRunnable.run(QuantumRenderer.java:67)
        at java.lang.Thread.run(Thread.java:722)

なんの設定がダメなんだろう。。。





添削歓迎

ここ間違ってるよ
こうした方がよくないか?
こういうことなんじゃないかな。
この環境だとこうなるよ
などなど
方法は、コメント、トラックバックはてブTwitter @orange_clover宛 で、お願いします。















関谷 和愛、上原 潤二、須江 信洋、中野 靖治
価格: ¥ 3,360
価格は記載時点のものです。購入前にAmazonでご確認ください。


「プログラミングGROOVY」正誤表