かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

ちょっと戻ってLookup

Lookupの結果に変化があったら処理をするってことが出来るみたいだ。
LookupListenerを使うといいぞと書いてある。

早速お試し。
Lookupなので、普通のJavaアプリにorg-openide-util.jarを追加すればOK。
まずは、自分で任意のLookupを追加出来るMyLookupを作る。
これは、ProxyLookupの持ってるprotectedメソッドのsetLookupsを使って実現してる。

class MyLookup extends ProxyLookup {
    public MyLookup(Lookup... lookups) {
        super(lookups);
    }
    
    public void addLookups(Lookup... lookups) {
        List<Lookup> list = new ArrayList<Lookup>();
        Collections.addAll(list, super.getLookups());
        Collections.addAll(list, lookups);
        super.setLookups(list.toArray(new Lookup[0]));
    }
}

LookupListenerだけど、これはLookup.Resultに対して追加できる。
Lookup.ResultはLookup.lookup(Lookup.Template template)メソッドで取得する。
コード的にはこんな感じ。

Lookup.Template<String> template = new Lookup.Template(String.class);
Lookup.Result<String> results = someLookup.lookup(template);

// 全インスタンスの入ったコレクションを取得
Collections<? extends String> col = results.allInstance();

このLookup.ResultにaddLookupListenerをしてやる。
コード的にはこんな感じになる。

package okazuki.lookuplistener;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.openide.util.Lookup;
import org.openide.util.lookup.ProxyLookup;
import org.openide.util.lookup.Lookups;
import org.openide.util.LookupListener;
import org.openide.util.LookupEvent;

public class Main {
    
    public static void main(String[] args) {
        MyLookup proxy = new MyLookup(Lookups.singleton("Hello"));
        Lookup.Template<String> template = new Lookup.Template(String.class);
        final Lookup.Result<String> results = proxy.lookup(template);
        results.addLookupListener(new LookupListener(){
            public void resultChanged(LookupEvent e) {
                print(results.allInstances());
            }
        });
        // なぜか一度はLookup.ResultからLookupの結果を取得しないと駄目らしい
        // この行をコメントアウトすると、resultChangedが発生しない
        print(results.allInstances());
        
        proxy.addLookups(Lookups.singleton("world")); // String型が追加されたのでresultChangedが発生
        proxy.addLookups(Lookups.singleton(1)); // ここではresultChangedが
        proxy.addLookups(Lookups.singleton(3)); // 発生しないよ!
        
    }
    
    private static void print(Collection<? extends String> strings) {
        for (String str : strings) {
            System.out.print(str);
            System.out.print(" ");
        }
        System.out.println();
    }
}

これを実行すると、こうなる。

Hello 
Hello world 

String型の何かが追加されたときのみ、resultChangedイベントが発生しているのがわかる。
これを使うと、ウィンドウが開いたときに監視対象のLookup.Resultを取得してリスナを追加する。
変更があるたびに表示を更新する。
ウィンドウが閉じられたときにリスナを消す。

こんな処理が可能になる。
本を見る限り一般的にガンガン使う方法みたいだ。