IntelliJ Platform Pluginの開発にて、ToolWindow上で、DialogWrapperとPropertiesComponentを使って、設定の保存と読み込みを行ってみた

以前、TextFieldの入力値により、テーブルの値を絞り込むことをためしてみました。
IntelliJ Platform Pluginの開発にて、ToolWindow上で、TextFieldの入力値に従って絞り込み可能なテーブル(JBTable)を表示してみた - メモ的な思考的な

以前は部分一致のみの絞り込みを実装しました。

ただ、設定により

  • 部分一致
  • 前方一致

を切り替えたくなったため、ためしてみたときのメモを残します。

 
目次

 

環境

 
なお、ソースコードは前回の記事の続きに実装していきます。
IntelliJ Platform Pluginの開発にて、ToolWindow上で、CellRendererを使ってテーブル(JBTable)の列に画像を表示してみた - メモ的な思考的な

 

仕様について

今回は以下の仕様としました。

  • ToolWindow上のボタンをクリックすると、設定ダイアログが開き、絞り込み方法をコンボボックスで選択する
  • OKボタンを押すと、コンボボックスの選択値が保存される
  • その状態でTextFieldに入力すると、テーブルの絞り込み方法がコンボボックスの選択値により変化する

 
上記の仕様を実現するため、1つずつ段階を追って実装していきます。

 

ToolWindow上のボタンをクリックすると、設定ダイアログを開くようにする

IntelliJ Platform Pluginでは、 DialogWrapper を使うことでダイアログを表示できます。
Dialogs | IntelliJ Platform Plugin SDK

 

DialogWrapperを継承したダイアログクラスを用意する

設定用のダイアログを用意します。

まずは Hello とだけ表示するダイアログにします。

package com.github.thinkami.hellojetbrainsplugin.ui

import com.intellij.openapi.ui.DialogWrapper
import com.intellij.ui.dsl.builder.panel
import javax.swing.JComponent

class SettingsDialog: DialogWrapper(true) {
    init {
        title = "My Settings"
        init()
    }

    override fun createCenterPanel(): JComponent {
        return panel {
            row {
                label("Hello")
            }
        }
    }
}

 

ダイアログを開くActionを用意する

ダイアログを開くためのActionを用意します。
Actions | IntelliJ Platform Plugin SDK

dialog.showAndGet() でダイアログでOKを押したときの挙動も定義できます。

今回はコンソールへHelloと出力してみます。

package com.github.thinkami.hellojetbrainsplugin.actions

import com.github.thinkami.hellojetbrainsplugin.ui.SettingsDialog
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent

class SettingsAction: AnAction() {
    override fun actionPerformed(e: AnActionEvent) {
        val dialog = SettingsDialog()
        if (dialog.showAndGet()) {
            // OKボタンをクリックした場合に、コンソールへHelloを出力する
            println("Hello")
        }
    }
}

 

ToolWindow上にボタンを用意し、クリックするとActionを起動する

今までの記事で作ってきているので、説明は省略します。

row {
    button("Settings", SettingsAction())
}

 

動作確認

ToolWindowを開くと、設定ダイアログを開くボタンが表示されます。

 
クリックすると、ダイアログが表示されます。

 

ここでの実装

以下のコミットです。
https://github.com/thinkAmi-sandbox/hello_jetbrains_plugin/pull/16/commits/7b616431a27f632f1a31fd39ac27242ae73fccf0

 

ダイアログにコンボボックスを表示する

続いて、ダイアログにコンボボックスを表示してみます。

 

Swingでコンボボックスを表示する方法を調査

調べてみたところ、以下の記事がありました。
コンボボックス JComboBox の使い方 - Swing のコンポーネント - Java 入門

IntelliJ Platform PluginのToolWindowでも使えそうです。

 

ダイアログにコンボボックスを表示する

Swingの実装とほぼ同じです。

プロパパティ comboBox を用意し、ダイアログを利用する側でも参照できるようにします。

また、 init の中でコンボボックスの選択肢などの設定を行い、 createContentPanel の中でコンボボックスを定義します。

class SettingsDialog: DialogWrapper(true) {
    val comboBox: JComboBox<String>

    init {
        title = "My Settings"

        // 追加
        comboBox = JComboBox<String>()
        comboBox.addItem("Preamble match") // 前方一致
        comboBox.addItem("Partial match")  // 部分一致
        comboBox.name = "matchType"

        init()
    }

    override fun createCenterPanel(): JComponent {
        return panel {
            row {
                label("Hello")
            }
            // 追加
            row {
                cell(comboBox)
            }
        }
    }
}

 

Actionでコンボボックスの選択値を確認する

actionPerformed メソッドの中で、OKボタンをクリックしたときにコンソールへコンボボックスの選択値を出力してみます。

なお、コンボボックスの getItemsAtselectedIndex を組み合わせることで、コンボボックスの選択値を取得できます。

override fun actionPerformed(e: AnActionEvent) {
    val dialog = SettingsDialog()
    if (dialog.showAndGet()) {
        // OKボタンをクリックしたときに、コンソールへコンボボックスの選択値を出力する
        val combo = dialog.comboBox
        val selectedType = combo.getItemAt(combo.selectedIndex)
        println(selectedType)
    }
}

 

動作確認

ダイアログにコンボボックスが表示されました。

 
OKボタンをクリックすると、コンソールへ選択値が出力されました。

 

ここでの実装

以下のコミットです。
https://github.com/thinkAmi-sandbox/hello_jetbrains_plugin/pull/16/commits/626379719771a00324ac457e6ccc9efcbe2cb170

 

コンボボックスの選択肢を PropertiesComponent で永続化する

永続化する方法を調査

公式ドキュメントでは、以下のページに値の永続化について記載されていました。
Persisting State of Components | IntelliJ Platform Plugin SDK

今回はお手軽に値を永続化したかったため、 PropertiesComponent を使うことにしました。
Using PropertiesComponent for Simple Non-Roamable Persistence | Persisting State of Components | IntelliJ Platform Plugin SDK

 

ダイアログでOKボタンをクリック後、PropertiesComponent で永続化する

actionPerformed の中で PropertiesComponent を使ってコンボボックスの選択値を永続化します。

なお、必要かどうかは分かりませんが、UIコンポーネントを操作しているため、今回は ApplicationManager.getApplication().invokeLater で囲っておきました。

override fun actionPerformed(e: AnActionEvent) {
    ApplicationManager.getApplication().invokeLater {
        val dialog = SettingsDialog()
        if (dialog.showAndGet()) {
            // OKボタンをクリックしたときに、コンソールへコンボボックスの選択値を出力する
            val combo = dialog.comboBox
            val selectedType = combo.getItemAt(combo.selectedIndex)
            println(selectedType)

            // コンボボックスの選択値を永続化する
            val properties = PropertiesComponent.getInstance()
            properties.setValue("matchType", selectedType)
        }
    }
}

 

永続化した設定をコンボボックスのデフォルト選択値にする

init の中で PropertiesComponent を使い、永続化情報を取り出してコンボボックスのデフォルト選択値にします。

init {
    // ...
    val properties = PropertiesComponent.getInstance()
    val matchType = properties.getValue("matchType")
    if (!matchType.isNullOrBlank()) {
        comboBox.selectedItem = matchType
    }
}

 

動作確認

ダイアログのコンボボックスで、初期値から Partial match へと選択値を変更します。

 
再度ダイアログを開くと、初期値が Partial match へと変更となっています。

 

ここでの実装

以下のコミットです。
https://github.com/thinkAmi-sandbox/hello_jetbrains_plugin/pull/16/commits/b04092157dd3d4faef12696d929acab65fb5888f

 

コンボボックスの選択肢により、テーブルの絞り込み方法を変更する

最後の仕上げです。

 

実装

filterChanged メソッドにてテーブルの絞り込みを行う際、 PropertiesComponent から値を取り出して使用します。

fun filterChanged() {
    tableData = allData.filter {
        val name = it[1] // Nameで絞り込むため、列番号を指定

        // 絞り込み条件を設定から取得して使用する
        val matchType = PropertiesComponent.getInstance().getValue("matchType")
        if (matchType == "Partial match") {
            name.contains(this.tableFilter.filterText)
        } else {
            name.startsWith(this.tableFilter.filterText)
        }
    }.toList() // allDataとは別オブジェクトにするため toList する

    // filterが更新されたことを通知する
    this.fireTableDataChanged()
}

 

動作確認

絞り込みを行わない場合のテーブル状態です。

 
ダイアログで Preamble match を選択した場合の絞り込みです。

という文字を入力しても、前方一致で検索するため、該当行はありません。

 
続いて、ダイアログで Partial match を選択した場合です。

この場合は部分一致であるため、 を入力すると該当行が表示されます。

 

ここでの実装

以下のコミットです。
https://github.com/thinkAmi-sandbox/hello_jetbrains_plugin/pull/16/commits/99a4988dd4ba8f26b193accdd85de2a2a9a56042

 

ソースコード

Githubにあげました。
https://github.com/thinkAmi-sandbox/hello_jetbrains_plugin

今回のプルリクはこちら。
https://github.com/thinkAmi-sandbox/hello_jetbrains_plugin/pull/16