-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: make our usage of Kotlin UI DSL compatible with 2022.1+
- Loading branch information
Showing
4 changed files
with
98 additions
and
17 deletions.
There are no files selected for viewing
17 changes: 10 additions & 7 deletions
17
plugin-core/src/main/kotlin/appland/remote/StartRemoteRecordingForm.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,58 @@ | ||
package appland.remote | ||
|
||
import com.intellij.ui.TextAccessor | ||
import com.intellij.ui.TextFieldWithHistory | ||
import com.intellij.ui.dsl.builder.COLUMNS_LARGE | ||
import com.intellij.ui.dsl.builder.Cell | ||
import com.intellij.ui.dsl.builder.Row | ||
import com.intellij.ui.dsl.builder.columns | ||
import com.intellij.util.ui.SwingHelper | ||
import javax.swing.JComponent | ||
import javax.swing.text.JTextComponent | ||
|
||
@Suppress("UnstableApiUsage") | ||
internal fun Row.textFieldWithHistory(history: List<String>): Cell<TextFieldWithHistory> { | ||
internal fun Row.textFieldWithHistory(history: List<String>): Pair<Cell<JComponent>, TextAccessor> { | ||
val component = TextFieldWithHistory() | ||
component.setHistorySize(-1) | ||
component.setMinimumAndPreferredWidth(0) | ||
SwingHelper.addHistoryOnExpansion(component) { history } | ||
|
||
val result = cell(component) | ||
result.columns(COLUMNS_LARGE) | ||
return result | ||
return try { | ||
cell(component).columns(COLUMNS_LARGE) to TextComponentAccessor(component.textEditor) | ||
} catch (e: NoSuchMethodException) { | ||
addCellReflective(component) | ||
} catch (e: NoSuchMethodError) { | ||
addCellReflective(component) | ||
} | ||
} | ||
|
||
/** | ||
* 2021.3 has `fun <T : JComponent> cell(component: T, viewComponent: JComponent = component): Cell<T>`. | ||
* 2022.1 and later have `fun <T : JComponent> cell(component: T): Cell<T>`, i.e., with only one parameter. | ||
* Compiling against 2021.3 and executing with 2022.1 will throw a `NoSuchMethodError` at runtime, | ||
* in this case we're trying to perform a fallback with reflection here. | ||
* | ||
* If the reflective call didn't work, there's still a fallback to a plain text field without history. | ||
*/ | ||
@Suppress("UNCHECKED_CAST") | ||
internal fun Row.addCellReflective(component: TextFieldWithHistory): Pair<Cell<JComponent>, TextComponentAccessor> { | ||
try { | ||
val addCellMethod = this.javaClass.getDeclaredMethod("cell", JComponent::class.java) | ||
val cell = addCellMethod.invoke(this, component) as Cell<TextFieldWithHistory> | ||
cell.columns(COLUMNS_LARGE) | ||
return cell to TextComponentAccessor(component.textEditor) | ||
} catch (e: NoSuchMethodException) { | ||
// fallback to editor without history | ||
val fallbackCell = textField() | ||
return fallbackCell to TextComponentAccessor(fallbackCell.component) | ||
} | ||
} | ||
|
||
class TextComponentAccessor(val component: JTextComponent) : TextAccessor { | ||
override fun setText(text: String?) { | ||
component.text = text ?: "" | ||
} | ||
|
||
override fun getText(): String { | ||
return component.text | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
plugin-core/src/test/kotlin/appland/remote/ComponentsKtTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package appland.remote | ||
|
||
import appland.AppMapBaseTest | ||
import com.intellij.openapi.application.ApplicationInfo | ||
import com.intellij.ui.TextFieldWithHistory | ||
import com.intellij.ui.dsl.builder.Cell | ||
import com.intellij.ui.dsl.builder.panel | ||
import org.junit.Assume | ||
import org.junit.Test | ||
import java.util.concurrent.atomic.AtomicReference | ||
import javax.swing.JComponent | ||
|
||
class ComponentsKtTest : AppMapBaseTest() { | ||
@Test | ||
fun textFieldWithHistoryReflective() { | ||
Assume.assumeTrue(ApplicationInfo.getInstance().build.baselineVersion >= 221) | ||
|
||
val component = TextFieldWithHistory() | ||
val componentAccessorPair = AtomicReference<Pair<Cell<JComponent>, TextComponentAccessor>>() | ||
|
||
panel { | ||
row { | ||
componentAccessorPair.set(addCellReflective(component)) | ||
} | ||
} | ||
|
||
val (cell, textAccessor) = componentAccessorPair.get() | ||
assertEquals("Component of the cell must match the input", component, cell.component) | ||
|
||
textAccessor.text = "updated text" | ||
assertEquals("Text accessor must modify input component", component.text, "updated text") | ||
} | ||
} |