🔖

Lem Advent Calendar 2023 - SDL2 Frontend - Class browser 編

2023/12/04に公開

これは Lem Advent Calendar の記事です。

概要

前回紹介したグラフィックス機能を使うことによってバッファに図形やテキストを描画できるようになりました。
この機能を使って実現できることとして思いついたのがClass Browserでした。

Class Browserとは

Classの継承関係を図として表示し、ノードをクリックすることで、そのクラスの詳細を見れるという機能です。

gifではcl-ppcre内で定義されているクラスの継承関係を表示しています。

作った動機

古のInterLispや商用Common Lisp IDEのLispworksではおなじみの機能ですが、Lemでも同じことがしてみたかったからです。

https://journal.paoloamoroso.com/my-encounter-with-medley-interlisp


https://www.lispworks.com/documentation/lw71/IDE-U/html/ide-u-59.htm#pgfId-852729

実装詳細

木構造を描画するソースコードは frontends/sdl2/tree.lisp に置いてあります。

アルゴリズム

この機能の実装時に気の描画方法について調べたところ、アルゴリズムは色々あるようです。
https://www.slideshare.net/mfumi/drawing-tree-algorithms

上のスライドを参考に、左から右へ描画するときの注意点としては以下を守ると良いことが分かります。

  1. 親は子より手前に置く
  2. 辺を交差させない
  3. 同じ深さのノードのx座標は同じにする
  4. なるべく狭く描画する
  5. 親は子の中央に置く
  6. 任意のサブツリーは場所によらず同じように描画する

これを少ない計算量でやる方法としては次の記事が参考になります。
https://llimllib.github.io/pymag-trees/

ただしlemでは上記のアルゴリズムは使わず、簡単に実装できる方法にしました。
1の「なるべく狭く描画する」ことは諦めます、スクロールを付ければ実用上の問題は無さそうでした。
これに伴い6の「任意のサブツリーは場所によらず同じように描画する」もあまり気にせずとも綺麗に描画されるようになりました。

ノードの位置の計算についてのコードは次の通りです。
https://github.com/lem-project/lem/blob/99c347cd66bc4e5992a5395d44fd9fb55e96c656/frontends/sdl2/tree.lisp#L74-L90

右に伸びていく木のxはノードの深さと同じにします。
yはノードが葉の場合は一つ上の葉のy+1を設定し、親は子のyの合計/子の数を設定します。

改善点

実験的に付けてみた程度の機能なので、まだ色々痒い所に手が届かない点があります。

  • 右クリックによる操作の選択が出来ない
  • ノードをクリックしたときにインスペクタが出るが、これとの組み合わせた操作に一貫性がない
  • 選択したクラスがルートになるが、その親がある場合に確認する方法がない

などなど上げると色々出てきます。

参考にしたサイト

https://www.slideshare.net/mfumi/drawing-tree-algorithms
https://naokirin.hatenablog.com/entry/2016/02/13/225332
https://llimllib.github.io/pymag-trees/

Discussion