JSR-377 Desktop|Embedded Application APIなんてのが始まっているようです

最近知ったのですが、 JSR-377 Desktop|Embedded Application API というものがスタートしているそうです。
英語圏でもごく狭い範囲でしか話題になっていないようで、もちろん日本語でこの情報について触れている人は自分の観測範囲では見当たりませんでしたので、ちょっと紹介してみたいと思います。

JSR-377 の Web ページから引用すると、次の API を定めようとしているようです。

* dependency injection via JSR330.
* common application structure.
* application life-cycle.
* localized resources.
* resource injection.
* localized configuration.
* decouple state from UI (binding).
* persistence session state (preferences).
* action management.
* component life-cycle.
* light-weight event bus.
* honor threading concerns (specific to UI toolkit).
* application extensibility via plugins (implies modularity).

要は比較的大規模な GUI アプリケーションを開発する際に、大体いつも作られる機能を共通化してしまおうというものです。アプリケーションフレームワークを作ろうとしているのですね。

実は過去にも JSR-296 Swing Application Framework というものがありました。これは Swing 開発のためのアプリケーションフレームワークを作ろうというもので、確か Java SE 7 に含めることを目標としていたように記憶しています。
ですがその後、Sun が JavaGUI 開発プラットフォームの主軸を Swing から JavaFX に移すという方針転換を行った影響で、この JSR はお蔵入りになってしまいました。
なので、JSR-377 は Swing App Framework のリブート版のように見受けられます。そういう意味でも個人的にとても注目しています。

Spec Lead は Groovy の GUI フレームワークである Griffon の開発者 Andres Almiray さんです。 Expart Group には Hendrik Ebbers さんや Johan Vos さんなど JavaFX 界で有名な方々が名を連ねています。

この JSR で目を引くのが、Swing、JavaFXSWT といった UI ツールキットを特に限定していない点です。特定のツールキットに依存しない、抽象的な API にすることを目指しているようです。
こういう変に抽象化した API を作ろうとするとうまく行かないことが多いので、個人的には少し引っ掛かります。
ただ、メンバーには JavaFX 系の人が多い (JavaFX でのデータ取得を抽象化するフレームワークである DataFX の開発メンバーが多い) ので、実際には JavaFX 中心で話が進むと見ています。

とは言え、こういうアプリケーションフレームワークができてくると、大規模開発における敷居も低くなりますし、今後に注目していきたいと思っています。

はてなブログに移行しました

まあ、タイトルの通りです。

リリースされた当初は色々言われていたはてなブログですが、そろそろ枯れてきたでしょうし、新機能はこちらの方にしか追加されないだろうから、移行することにしました。

Markdown が使えるのが嬉しいですね。はてな記法は結局最後まで覚えられなかった...。

はてダのエントリは全てインポート済みで、はてダのエントリにアクセスするとリダイレクトされるようになっているはずです。RSS についても引き続き配信されるはずです。

しばらくは設定とかテーマとかちょこちょこいじる可能性があると思いますが、ご了承ください。

そんなわけでこれからも引き続きよろしくです。

JavaFX の WebView に文字列検索機能を付けてみる

このエントリは JavaFX Advent Calendar 2014 の 19 日目のエントリです。前日は id:yumix_h さんによる、「WebView(JavaFX)のズーム機能を使ってみました」でした。

はじめに

JavaFX には Web ブラウザコンポーネントである WebView が付いているのは皆さんよくご存じかと思います。
DOM へのアクセス、JavaScript 実行、ヒストリ情報へのアクセス、JavaScript イベントのフック、など様々な機能が提供されており、他の GUI ツールキットが提供するブラウザコンポーネントと比較しても遜色がないと思っています。

ただ、残念なことに WebView 上に表示されているコンテンツに対してテキスト検索を行うための API が用意されていないんですよね。
もちろん表示されているコンテンツの DOM にアクセス可能なので、その DOM を頑張ってパースするという手もあるのですが、中々辛い。

というわけで、既存の JavaScript ライブラリを使って手っ取り早く実装する方法を考えてみました。

作ってみたもの

次の図のように、WebView を使ったブラウザアプリケーションに検索ボックスを取り付け、検索ボックスに文字列を入力するとマッチする部分をハイライトするようにしました。

マッチした部分をハイライトするだけで、ハイライトした箇所にスクロールする機能はありません。

ちなみに、このスクリーンショットは、自分が作った Social Bookmark Viewer FX という、Diigo というソーシャルブックマークサービスのビューアアプリケーションの一部です。 *1

利用した JavaScript ライブラリ

この機能を実現するために次のライブラリを利用してみました。

JavaScript text higlighting jQuery plugin
http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html

jQueryプラグインとして提供されているライブラリです。
使い方としては、予め以下の CSS クラスを定義しておき、

.highlight { background-color: yellow }

あとは次のようにこのプラグインjQuery オブジェクトに生える highlight() メソッドを、ハイライトしたい文字列を引数に渡して呼べば OK です。

$('body').highlight('foo');

WebView に検索機能を追加する

それではこれを WebView で使えるようにします。まず、WebView 上のドキュメントのロードに成功したら、jQuery 及び上で紹介した検索ライブラリをドキュメントに追加します。

final WebEngine webEngine = webView.getEngine();
final Worker<Void> loadWorker = webEngine.getLoadWorker();
loadWorker.stateProperty().addListener((observable, oldValue, newValue) -> {
    if (newValue == Worker.State.SUCCEEDED) {
        // 読み込みが成功した場合、検索用プラグインを読み込む
        Optional.ofNullable(webEngine.getDocument()).ifPresent(document -> {
            addScriptElement(document, "//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"); // (1)
            addScriptElement(document, "http://johannburkard.de/resources/Johann/jquery.highlight-4.closure.js"); // (2)
            addStyleElement(document, ".highlight { background-color: yellow; }"); // (3)
        });
    }
});

WebEngine の読み込み状態を観察し、成功した場合にのみ検索用プラグインを読み込むようにしています。
(1) で jQuery を、(2) で検索ライブラリを、(3) で検索ライブラリが要求するスタイルクラスを DOM に追加しています。
JavaScript ライブラリはどちらもネットワークから直接読み込んでいます。

addScriptElement() メソッド及び addStyleElement() の実装は次のようになっています。

private void addScriptElement(Document document, String url) {
    final Element scriptElm = document.createElement("script");
    scriptElm.setAttribute("type", "text/javascript");
    scriptElm.setAttribute("src", url);
    NodeList bodys = document.getElementsByTagName("body");
    if (bodys != null && bodys.getLength() > 0) {
        bodys.item(0).appendChild(scriptElm);
    }
}

private void addStyleElement(Document document, String styleContent) {
    final Element styleElm = document.createElement("style");
    styleElm.setAttribute("type", "text/css");
    styleElm.setTextContent(styleContent);
    NodeList bodys = document.getElementsByTagName("body");
    if (bodys != null && bodys.getLength() > 0) {
        bodys.item(0).appendChild(styleElm);
    }
}

普通に DOM API を用いて、script 要素や style 要素を作ってドキュメントに追加しているのが分かりますね。

続いて検索テキストボックスに入力があったら、ハイライトする処理です。

final TextField pageSearchBox = new TextField();
pageSearchBox.textProperty().addListener(
        (observable, oldValue, newValue) -> highlightpage(Optional.ofNullable(newValue)));

TextField の text プロパティの変化時に highlightpage() メソッドを呼び出しています。
highlightpage() メソッドの実装は次のようになっています。

private void highlightpage(Optional<String> word) {
    Optional.ofNullable(webEngine.getDocument()).ifPresent(document -> {
        final String keyword = word.orElse("");
        webEngine.executeScript("$('body').removeHighlight()");
        if (!keyword.isEmpty()) {
            webEngine.executeScript("$('body').removeHighlight().highlight('" + keyword + "')");
        }
    });
}

WebEngine#executeScript() メソッドを使って、ハイライトを行う JavaScript ライブラリのメソッドをコールしています。

実装は以上です。これで上のスクリーンショットのような機能を実現できます。
JavaScript ライブラリの手助けで割と簡単にできましたね。これも JavaFX の WebView/WebEngine が DOM へのアクセスや JavaScript の実行を行える仕組みを提供してくれているからです。
ただし、この方法だと script 要素を追加して余計な JavaScript ライブラリを読み込ませたり、新たなスタイル定義を追加したりしているので、元々コンテンツがロードしている JavaScript コードやスタイル定義とバッティングする危険性があることに注意してください。 *2
重要度の高いアプリケーションでは JavaScript のスコープなどをより慎重に設計する必要があります。

明日は id:kikutaro777 さんの予定です。

*1:そのうちこれ自身の紹介エントリも書きたいと思っています。

*2:実際いくつかのサイトで不具合を起こしているのを確認しました

結婚しました (事後報告)

既に TwitterFacebook では報告していましたが。先日 11/10 に結婚しました。
完全事後報告ですみません。

遂に所帯持ちになったという自覚を持ってこれからもよりいっそう努力していきたいと思いますので、これからもよろしくお願いします。m(__)m

Yosemiteで動かなかったソフトウェア

昨日のエントリの続きです。Yosemite にすると、案の定動かなくなったソフトウェアも出てきました。
以下のソフトウェアです。

いずれも最新バージョン (Kaspersky は 15、VMWare は 7) に更新することで動作しました。Kaspersky はライセンス保持者に対してはアップグレードが無料ですが、VMWare Fusion の方は有料です (ライセンス保持者は優待価格で購入できますが) 。 *1

流石にセキュリティソフトウェアや仮想化ソフトウェアのようなシステムの深いところに触りそうなものは影響受けますね。
今までの経験からすると大体 2 バージョンくらいしか持ちません。OS が無料でもこういうところで結局金が掛かるんですよね。
このようにしてサードパーティーソフトウェアに対しても最新版の購入を強要させる辺り、Apple はホンマ ISV 思いですねえ......クソが。

*1:最近 VMWare 製品の購入経路は VMWare の直販のみになりました。なので、VMWare の Web サイトから購入することになりますが、購入手順が非常に分かり辛かったですよ...。

Yosemiteで遭遇した問題

Mac OSX の最新版、Yosemite が登場しましたが、Time Machine でバックアップも取っていることもあり、早速突撃してみました。
Yosemite は一新されたデザインが結構自分の好みに合っているんですよねー。

これまで Apple 系 OS でアップグレードとかしてもトラブルに巻き込まれることはそれほど無かったのですが (一度 iPhone のアップグレードでバックアップからの復帰に失敗するというバグを踏んだことあり) 、今回は色々地雷を踏んでしまいました。
ということで以下に参考までに列挙しておきます。
なお、使用しているマシンは MacBook Pro 15inch の Mid2010 モデルです。LED Cinema Display につないでデュアルディスプレイにして使っています。

Google Drive が起動しない (対応策あり)

Google Driveツールバーアイコンがグレーアウトし、クリックにも反応しないという現象が起きました。マウスカーソルをホバーさせると、「ログインしていません」というメッセージが出ます。
最新バージョンをダウンロードして再インストールしても状況は同じでした。

こちらについては調べてみると以下のサイトに解決策が記載されており、その手順に従うと解決しました。
http://ralfrottmann.net/fix-google-drive-mac-app-on-yosemite

IM を起動しての文字入力が遅くなる (Safari がトリガ?)

IM を起動しての日本語の入力が遅いという問題です。文字を入力する際に頻繁にツールバーがちらつき、レスポンスが遅くなるという現象で、これはかなりイラつきます。
私は普段 ATOK を使っていますが、Yosemiteことえりに代わって新たに導入された JapaneseIM でも現象は同じです。
この現象は常に起きるわけではなく、どうも Safari を起動し、そこでテキストを入力することがトリガとなって発生するように見えます。
なぜ Safari なのか、なぜ Safari で問題が起きると、それ以降はどのアプリケーションでも入力が遅くなるのか、非常に謎な事象です。

デュアルディスプレイだとサブディスプレイ側の描画が乱れる

上にも書きましたが、MBP に LED Cinema Display をつないでデュアルディスプレイにしていますが (LED Cinema Display 側をプライマリにしている) 、サブディスプレイの描画が乱れることがあります。
再現条件がはっきりしていませんが、これも Safari の実行がトリガとなって発生するように見えます。

こんな感じで、ちょっと触っただけでも結構色々ありました。仕事用など、大事なマシンに入れるのはまだ様子を見た方がいいように思えます。
どうも新しい Safari が困ったちゃんな感じに見えますねえ。操作も少し重たいし (Web ページのレンダリング自体は速いのですが) 。

Mac の不具合報告は以下のフォームから行えるようなので、これからフィードバックします。
https://www.apple.com/jp/feedback/macosx.html

(2014/12/08追記)

本エントリで報告した問題のうち、後ろ 2 つの「IM を起動しての文字入力が遅くなる (Safari がトリガ?)」「デュアルディスプレイだとサブディスプレイ側の描画が乱れる」については解決策がありました。
次のようにアクセシビリティの設定で「コントラストを上げる」「透明度を下げる」の設定をONにすると解決しました。

やはり半透明のエフェクトが非常に高負荷だったようです。

Asakusa Framework 勉強会 2014真夏でLTを行ってきました

8/22 に実施された Asakusa Framework 勉強会 2014真夏 で LT を行ってきましたので、発表内容の補足と勉強会の感想について書きたいと思います。

当日の発表資料は以下の通りです。

AsakusaのドキュメントをDashで見たい from Takashi Aoe

直前に発表することを決めたので、内容は完全に小ネタです。
Mac 用の API ドキュメント閲覧ツールである Dash の紹介と、その Dash に Asakusa Framework の公式ドキュメントAPI ドキュメントを組み込めるようにする方法について紹介しました。
その説明を通して、Asakusa の公式ドキュメント自身も GitHub 上で公開されていること、ドキュメントも OSS として公開されている以上、みんながその内容を充実させるための貢献ができることを伝えることも狙いでした。
図らずも今回の LT 大会では公式ドキュメントに対する指摘が色々ありました。OSS への参加で一番貢献しやすいものの一つがドキュメントだと思っています。中の人的にはドキュメントに対して貢献してもらうことはとても有り難いことなので、どしどし指摘なりパッチなりを送って欲しいと思います。
現在 Issue がみんな英語で記述されているので、躊躇されている方もいらっしゃるかも知れませんが、日本語で全然おっけーですので、どんどん寄せてください。

LT で紹介した Dash はとても良いツールなので、Mac を使っている開発者の皆様は是非試してみてください。
様々な言語やライブラリの API ドキュメントを 1 つのツールで一元的に閲覧できるのは便利です。
それに、第 3 者がコントリビュートできるようになっているため、かなりマニアックなものまでカバーしています。
以下に Dash の Web ページで紹介されている、サポートしている言語やライブラリの一覧のスクリーンショットを貼っておきますが (これでも上半分です) 、実に様々なものをカバーしていることが分かりますね。 *1

さて、他の方の発表を聴いていての感想ですが、皆さんかなり Asakusa をガッツリと使い出しているなあと驚きました。
非構造化データの取り扱いへのチャレンジがあったり、演算子の使い方に対する深い考察をした発表があったり、テストドライバの実装を調査した発表もあったりと、こちらも聴いていて「そういう視点があったか」と何度か気付かされることがありました。
土佐さんの演算子チートシートはとてもいいですね!私も可能ならば内容の充実に貢献したいと思っています。 *2

*1:個人的にはちゃんと JavaFX もカバーされていたことがポイント大 :-)

*2:プロジェクトページは https://github.com/ironpeace/asakusa_operators_cheetsheet のようですね