モードレスダイアログからモーダルダイアログを表示してのブロッキング

モードレスダイアログからモーダルダイアログをブロッキングして出すことを許すと、イベントループの扱いで期待通りには動かないことが判明。

たとえば、以下のような場合に問題となる。

  1. ウィンドウAをモーダルで表示(イベントループはAを基点に廻る)
  2. AからBをモードレスで表示(イベントループはA基点のままで、A、Bともに操作可能)
  3. BからCをモーダルで表示(イベントループがC基点となり、A、Cが操作可能)
  4. AからDをモーダルで表示(イベントループがD基点となり、C、Dが操作可能)
  5. Cを閉じる

BからCを開く部分を擬似コード化するときっとこんな感じ。

@EventListener(id="openButton")
public void openCWindow() {
  int result = windowManager.openModal("CWindow.xml");
  if (result == SWT.OK) {
    // Cの結果を受けた処理を行う
  }
}

これが、Cを閉じてもopenModalの処理は返ってこない。イベントループの基点がDになってしまっているからだ。Dを閉じた時に初めてCを表示するopenModalも返ってくる。

この問題に対処するため、モードレスダイアログからはモーダルダイアログを出せないようにしようかと思う。


モーダルダイアログからモーダルダイアログを開く場合は、親のダイアログは操作できないので問題にはならない。実は、モードレスからモーダルを出す場合でも、ブロッキングする必要がなければ(つまりダイアログからの戻りによって何か処理を行う必要というのがなければ)問題にはならない。でもそのパターンを許すと複雑になってしまいそうなので今は許さないようにしようかと思っている。

どうしてもモードレスなウィンドウからモーダルなダイアログを出したい場合は、OSのウィンドウ(SWTで言うところのDisplay)を複数もつアプリを作ってもらうことになると思う。これをS2JFaceでサポートするのは面倒そうだなぁ。使う人もマルチスレッドになるから気をつけてねってなりそうだし。。。