アウトラインビューを表示させようとしてみた。

GEFでHelloWorld:第11回 コンテンツ・アウトライナーの使用とコンテンツのサムネイル表示

上記サイトを参考にさせて頂きました。しかし、サムネイルの方は文句なしなんですが、GEFのTreeViewerの使い方がイマイチ理解できませんでした。Entityモデル(Jiemamyではテーブル等)をアウトラインに並べるところまでは上手く行ったんですが、「テーブルの子に、Columnモデルを並べたい…」となった時に、手段が分からない。

ちなみに、GEFを使っている場合。ContentOutlinePage というクラスは2つあります。

  • org.eclipse.ui.views.contentoutline.ContentOutlinePage
  • org.eclipse.gef.ui.parts.ContentOutlinePage

そしてさらに、TreeViewerクラスも2つあります…。ややこしい…。

  • org.eclipse.jface.viewers.TreeViewer
  • org.eclipse.gef.ui.parts.TreeViewer

上記サイトの例は、それぞれの後者を使う方で解説がされています。GEFのアウトラインビューを実装する場合は、通常後者を使う方が楽なんですよね? 多分。前者が、一般実装方法、後者はGEFに特化した特殊実装方法、という認識でいます。しかし使い方が分からない。

うーん、と悩みながら、前者での実装も試みて見ました。けど、色々難しいですねー。以下、参考サイトのコードの修正部分。

private class DiagramOutlinePage extends org.eclipse.ui.views.contentoutline.ContentOutlinePage {
  // ...
  @Override
  public void createControl(Composite parent) {
    sash = new SashForm(parent, SWT.VERTICAL);
    super.createControl(sash);
    org.eclipse.jface.viewers.TreeViewer viewer = getTreeViewer();
    viewer.setContentProvider(new MyContentProvider());
    viewer.addSelectionChangedListener(new ISelectionChangedListener() {
      public void selectionChanged(SelectionChangedEvent event) {
        IStructuredSelection sel = (IStructuredSelection) event.getSelection();
        Object element = sel.getFirstElement();
        if (element instanceof AbstractModel) {
          EditPart ep = (EditPart) getGraphicalViewer().getEditPartRegistry().get(element);
          ep.setSelected(EditPart.SELECTED_PRIMARY);
        }
      }
    });
    viewer.setInput(dbModel);

    Canvas canvas = new Canvas(sash, SWT.BORDER);
    // ...
  }
  // ...
}

あー、なんかダサくないですか? アウトラインの要素をクリックすると、該当figureが選択されます。されるんですが、元から選択されていたfigureの選択は解除されず、まるでfigureをSHIFT+クリックした時のように…。

また、セットしたContentProviderもダサい…。ITreeContentProvider#getParent(Object element) って、elementの親モデルを返すメソッドですよね。現在のデータモデルは大まかに以下の様な感じになっています。

  • DatabaseModel (ルート)
    • TableModel
      • ColumnModel
    • ViewModel
    • ForeignKeyModel
      • ForeignKeyMapping
    • InheritanceModel

で、下位モデルは上位モデルに依存しない、具体的にはColumnModelはTableModelに依存しない、つまり、ColumnModel自身は、どのTableModelに保持されているのかを知らない構造になっています。

つーまーりー。getParentにelementとしてColumnModelが入って来ても、親(TableModel)を探せないのであります。

  1. この設計のまま、エレガントに親モデルを探す術が、実はある。(私が気づいていないだけで…)
  2. ルートモデルはいつでも取得できるので、そこからシラミ潰しに親を探す。(超ダサくないですか?)
  3. もうこうなったら、子モデルも親モデルに依存させる。(相互依存ですか…。)

現実は、どうなんでしょう。なんか、久々に濃いぃエントリーを投稿(笑)