Nashorn スクリプトで作る
ace.js
として以下のスクリプトを作成します。
#!/usr/bin/jjs -fx var html = "<!DOCTYPE html>" + "<html><head>" + "<style type='text/css' media='screen'>" + " #editor { position: absolute; top: 0; right: 0; bottom: 0; left: 0; }" + "</style>" + "</head>" + "<body>" + "<div id='editor'></div>" + "<script src='https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/ace.js'></script>" + "<script>" + " var editor = ace.edit('editor');" + " editor.setTheme('ace/theme/monokai');" + " editor.getSession().setMode('ace/mode/javascript');" + "</script>" + "</body></html>"; var webView = new javafx.scene.web.WebView(); webView.engine.loadContent(html); var pane = new javafx.scene.layout.BorderPane(webView); $STAGE.scene = new javafx.scene.Scene(pane, 500, 400); $STAGE.show();
実行権限付けて実行すれば
$ ./ace.js
こんな感じのテキストエディタになります。
シンタックスハイライトなども。
WebView
で Ace Editor を使ってるだけです。
Ace Editor とは
Cloud9 IDE で使われているエディタコンポーネントです。
この間 AWS でも、AWS Cloud9 – クラウド開発環境 としてサービスが開始されたやつですね。
Ace Editor は JS なのでブラウザで簡単に実行できますし、ローカルのアプリケーションに組み込みたい場合でも JavaFX で WebView の中で動かしたりできます。
50行ぐらいでファイル処理
もう少しだけ加工してみます。
最初に html ファイルを外に出します。ace.html
として以下を作成しましょう。
<!DOCTYPE html> <html> <head> <style type="text/css" media="screen"> #editor { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } </style> </head> <body> <div id="editor"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/ace.js"></script> <script> var editor = ace.edit("editor"); editor.setTheme("ace/theme/monokai"); editor.getSession().setMode("ace/mode/javascript"); </script> </body> </html>
外出した html ファイルは以下のように WebView で読み込むことができます。
webView.engine.javaScriptEnabled = true; webView.engine.load(new java.io.File("ace.html").toURI().toURL().toString());
後に executeScript()
するので javaScriptEnabled = true
としておきます。
メニューを作ります。Open と Save だけの簡単なものにします。
var menuBar = new javafx.scene.control.MenuBar(), menuFile = new javafx.scene.control.Menu("File"), itemOpen = new javafx.scene.control.MenuItem("Open"), itemSave = new javafx.scene.control.MenuItem("Save"); menuFile.items.addAll(itemOpen, itemSave); menuBar.menus.addAll(menuFile); if (java.lang.System.getProperty("os.name").startsWith("Mac")) { menuBar.useSystemMenuBarProperty().set(true); } // ... var pane = new javafx.scene.layout.BorderPane(webView, menuBar, null, null, null);
Mac の場合はシステムメニューバーのプロパティを設定します。
最後にメニュー選択時のアクションを追加します。
Open 選択時のアクションです。
itemOpen.setOnAction(function(e) { var selected = new javafx.stage.FileChooser().showOpenDialog($STAGE); if (selected) { file = selected; var text = new java.lang.String(Files.readAllBytes(file.toPath()), "UTF-8"); var editor = webView.engine.executeScript("editor"); editor.call("setValue", text); } });
webView.engine.executeScript("editor")
とすると WebView 内の Ace editor のJSオブジェクトが JSObject として得られるので、call()
により Ace editor のテキスト内容を設定します。
Sava 選択時のアクションです。
itemSave.setOnAction(function(e) { file = file || new javafx.stage.FileChooser().showSaveDialog($STAGE); if (file) { var text = webView.engine.executeScript("editor.getValue()"); Files.write(file.toPath(), text.getBytes("UTF-8")); } });
最終的には以下のようになりました。
#!/usr/bin/jjs -fx var Files = Java.type("java.nio.file.Files"); var webView = new javafx.scene.web.WebView(), file; var menuBar = new javafx.scene.control.MenuBar(), menuFile = new javafx.scene.control.Menu("File"), itemOpen = new javafx.scene.control.MenuItem("Open"), itemSave = new javafx.scene.control.MenuItem("Save"); webView.engine.javaScriptEnabled = true; webView.engine.load(new java.io.File("ace.html").toURI().toURL().toString()); itemOpen.setOnAction(function(e) { var selected = new javafx.stage.FileChooser().showOpenDialog($STAGE); if (selected) { file = selected; var text = new java.lang.String(Files.readAllBytes(file.toPath()), "UTF-8"); var editor = webView.engine.executeScript("editor"); editor.call("setValue", text); } }); itemSave.setOnAction(function(e) { file = file || new javafx.stage.FileChooser().showSaveDialog($STAGE); if (file) { var text = webView.engine.executeScript("editor.getValue()"); Files.write(file.toPath(), text.getBytes("UTF-8")); } }); menuFile.items.addAll(itemOpen, itemSave); menuBar.menus.addAll(menuFile); if (java.lang.System.getProperty("os.name").startsWith("Mac")) { menuBar.useSystemMenuBarProperty().set(true); } $STAGE.scene = new javafx.scene.Scene( new javafx.scene.layout.BorderPane(webView, menuBar, null, null, null), 500, 400); $STAGE.show();
実行
実行してみます。
$ ./ace.js
ace.js
を開くと以下のようになりました。
簡単ですね!
Ace editor は110を超える言語のシンタックスハイライトがあり、テーマも20を超える数が用意されています。 アプリケーションでエディタコンポーネントが必要な場合の良い選択肢になると思います。