マップに画像を貼り付ける事ができます。画像はノード・オブジェクトの内側に表示されます。つまり、画像を貼り付けたノード・オブジェクトをマップに置く形になります。画像の種類は、JPEG, PNG, GIF, SVGです。
画像の貼り付け手順は、画像をマップに取り込む処理と、シェイプに設定する処理に分かれます。マップには任意のファイルを埋め込む機能があります。画像を貼り付ける場合、まずマップに画像ファイルを埋め込みます。埋め込まれた画像ファイルは、jp.carabiner.inkpod.pi.model.EmbeddedResourceオブジェクトとして、取り扱うことができるようになります。矩形シェイプなどのノード・シェイプには、imageResourceプロパティがあり、ここに設定された画像ファイルを表示します。imageResourceプロパティに、画像ファイルのEmbeddedResourceオブジェクトを設定することで、画像を表示できます。
「オブジェクト」メニューに、「画像の貼り付け」が追加されます。貼り付け先のノード・オブジェクトを選択し、「画像の貼り付け」を選ぶと、画像ファイルを選択するダイアログが表示されます。画像を選ぶと、ノード・オブジェクトに貼り付けられます。
function extendUI(event) { inkpod.ui.actions.addAction({ id : "SAMPLE_PASTE_IMAGE", text : "画像の貼り付け", action : function(frame, event) { var model = frame.model; var object = model.singleSelectedObject; if(!object) { frame.alert("オブジェクトを選択してください"); return; } if(!(object.shape instanceof Packages.jp.carabiner.inkpod.pi.shape.PAbstractRectangleShape)) { frame.alert("このオブジェクトには画像は貼り付けられません"); return; } // ファイル選択ダイアログを表示 var chooser = Packages.javax.swing.JFileChooser(); chooser.multiSelectionEnabled = false; chooser.addChoosableFileFilter(new Packages.javax.swing.filechooser.FileFilter() { accept : function(f) { var name = f.getName().toLowerCase(); return name.endsWith(".jpg") || name.endsWith(".png") || name.endsWith(".gif"); }, getDescription : function() { return "Image Files"; } }); var result = chooser.showOpenDialog(frame.getJFrame()); if(result == Packages.javax.swing.JFileChooser.APPROVE_OPTION) { // 選択されたファイルをソースとして、埋め込みリソースを作成 var resource = model.createResource(chooser.selectedFile); // 画像を読み込む frame.loadResource(resource, new Packages.jp.carabiner.inkpod.pi.TaskObserver() { taskSucceeded : function(resource) { // 読み込みに成功したらshapeに設定する object.shape.imageResource = resource; }, taskFailed : function(throwable) { } }); } } }); inkpod.ui.menuBar.objectMenu.addMenuItem("SAMPLE_PASTE_IMAGE"); } function init() { inkpod.ui.addUIExtensionListener(extendUI); } function dispose() { } plugin = { init : init, dispose : dispose }
ユーザーが画像ファイルを選択した後の以下の部分が、画像の貼り付けの主な処理です。
// 選択されたファイルをソースとして、埋め込みリソースを作成 var resource = model.createResource(chooser.selectedFile); // 画像を読み込む frame.loadResource(resource, new Packages.jp.carabiner.inkpod.pi.TaskObserver() { taskSucceeded : function(resource) { // 読み込みに成功したらshapeに設定する object.shape.imageResource = resource; }, taskFailed : function(throwable) { } });
まず、PMapModelのcreateResource() メソッドで、ユーザーが選択した画像ファイルと結びつけられた、EmbeddedResourceオブジェクトを作成します。この段階では、EmbeddedResourceオブジェクトは、ローカルファイルを指しているだけで、まだ画像ファイルは読み込まれていません。
次の段階として画像ファイルを読み込みますが、画像ファイルは一般的にサイズが大きく、読み込みには時間がかかります。アクションの処理は、Swingのイベントディスパッチスレッドで処理されているため、ここで画像の読み込みを行うと、イベントディスパッチスレッドを占有して、読み込みの間、Inkpod全体が操作できない状態になります。そのため、Inkpodには、非同期に画像の読み込みを処理する方法が用意されています。
画像の非同期読み込みはフレーム(PInkpodFrame)のloadResource() メソッドで、実現できます。loadResource() メソッドは、まだ読み込んでいないEmbeddedResourceオブジェクトを渡すと、バックグラウンドのスレッドでファイルの読み込みを開始し、すぐに制御を戻します。ファイルの読み込みが成功した場合は、第2引数で渡した、jp.carabiner.inkpod.pi.TaskObserverオブジェクトの、taskSucceeded メソッドを呼び出します。読み込み完了後に処理したいことは、このメソッドに記述します。この呼び出しはイベントディスパッチスレッドで行われます。読み込みに失敗した場合は、taskFailed メソッドが呼ばれます。このサンプルでは、taskSucceededメソッドで、選択されたマップ・オブジェクトのシェイプのimageResourceプロパティに、読み込みが完了した画像ファイルを設定し、画像を貼り付けています。
imageResoruceプロパティは、jp.carabiner.inkpod.pi.PAbstractRectangleShapeインターフェースを持つ全てのシェイプに存在します。現在のところ、すべてのノード・シェイプはこのインターフェースを持ちます。
なお、読み込みに時間がかからない事がわかっているなどの場合に、同期的に画像を読み込むことも可能です。EmbeddedResourceのloadResource() メソッドを直接呼び出すことで、読み込むことができます。