modular project configurables
This commit is contained in:
parent
12e5ffdea1
commit
c7e33ea8de
9 changed files with 71 additions and 84 deletions
|
@ -41,7 +41,7 @@ import javax.swing.ListSelectionModel
|
|||
|
||||
class ZigNewProjectPanel(private var handleGit: Boolean): Disposable {
|
||||
private val git = JBCheckBox()
|
||||
val panels = ZigProjectConfigurationProvider.createNewProjectSettingsPanels().onEach { Disposer.register(this, it) }
|
||||
val panels = ZigProjectConfigurationProvider.createPanels(null).onEach { Disposer.register(this, it) }
|
||||
private val templateList = JBList(JBList.createDefaultListModel(defaultTemplates)).apply {
|
||||
selectionMode = ListSelectionModel.SINGLE_SELECTION
|
||||
selectedIndex = 0
|
||||
|
|
|
@ -22,23 +22,15 @@
|
|||
|
||||
package com.falsepattern.zigbrains.project.settings
|
||||
|
||||
import com.falsepattern.zigbrains.project.toolchain.ui.ZigToolchainEditor
|
||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||
import com.falsepattern.zigbrains.shared.SubConfigurable
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.NlsContexts
|
||||
|
||||
class ZigCoreProjectConfigurationProvider: ZigProjectConfigurationProvider {
|
||||
override fun handleMainConfigChanged(project: Project) {
|
||||
class ZigConfigurable(override val context: Project) : SubConfigurable.Adapter<Project>() {
|
||||
override fun instantiate(): List<SubConfigurable<Project>> {
|
||||
return ZigProjectConfigurationProvider.createPanels(context)
|
||||
}
|
||||
|
||||
override fun createConfigurable(project: Project): Configurable {
|
||||
return ZigToolchainEditor.Adapter(project)
|
||||
}
|
||||
|
||||
override fun createNewProjectSettingsPanel(): SubConfigurable<Project> {
|
||||
return ZigToolchainEditor().also { it.reset(null) }
|
||||
}
|
||||
|
||||
override val priority: Int
|
||||
get() = 0
|
||||
override fun getDisplayName() = ZigBrainsBundle.message("settings.project.display-name")
|
||||
}
|
|
@ -24,24 +24,15 @@ package com.falsepattern.zigbrains.project.settings
|
|||
|
||||
import com.falsepattern.zigbrains.shared.SubConfigurable
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
interface ZigProjectConfigurationProvider {
|
||||
fun handleMainConfigChanged(project: Project)
|
||||
fun createConfigurable(project: Project): Configurable
|
||||
fun createNewProjectSettingsPanel(): SubConfigurable<Project>?
|
||||
val priority: Int
|
||||
fun create(project: Project?): SubConfigurable<Project>?
|
||||
val index: Int
|
||||
companion object {
|
||||
private val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigProjectConfigurationProvider>("com.falsepattern.zigbrains.projectConfigProvider")
|
||||
fun mainConfigChanged(project: Project) {
|
||||
EXTENSION_POINT_NAME.extensionList.forEach { it.handleMainConfigChanged(project) }
|
||||
}
|
||||
fun createConfigurables(project: Project): List<Configurable> {
|
||||
return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.map { it.createConfigurable(project) }
|
||||
}
|
||||
fun createNewProjectSettingsPanels(): List<SubConfigurable<Project>> {
|
||||
return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.mapNotNull { it.createNewProjectSettingsPanel() }
|
||||
fun createPanels(project: Project?): List<SubConfigurable<Project>> {
|
||||
return EXTENSION_POINT_NAME.extensionList.sortedBy { it.index }.mapNotNull { it.create(project) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -150,6 +150,20 @@ fun getSuggestedLocalToolchainPath(): Path? {
|
|||
return getWellKnown().getOrNull(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the paths to the following list of folders:
|
||||
*
|
||||
* 1. DATA/zig
|
||||
* 2. DATA/zigup
|
||||
* 3. HOME/.zig
|
||||
*
|
||||
* Where DATA is:
|
||||
* - ~/Library on macOS
|
||||
* - %LOCALAPPDATA% on Windows
|
||||
* - $XDG_DATA_HOME (or ~/.local/share if not set) on other OSes
|
||||
*
|
||||
* and HOME is the user home path
|
||||
*/
|
||||
private fun getWellKnown(): List<Path> {
|
||||
val home = System.getProperty("user.home")?.toNioPathOrNull() ?: return emptyList()
|
||||
val xdgDataHome = when(OS.CURRENT) {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
package com.falsepattern.zigbrains.project.toolchain.ui
|
||||
|
||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
|
||||
import com.falsepattern.zigbrains.project.toolchain.ToolchainListChangeListener
|
||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService
|
||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainService
|
||||
|
@ -169,9 +170,13 @@ class ZigToolchainEditor(private val isForDefaultProject: Boolean = false): SubC
|
|||
|
||||
override val newProjectBeforeInitSelector get() = true
|
||||
|
||||
class Adapter(override val context: Project): SubConfigurable.Adapter<Project>() {
|
||||
override fun instantiate() = ZigToolchainEditor(context.isDefault)
|
||||
override fun getDisplayName() = ZigBrainsBundle.message("settings.toolchain.editor.display-name")
|
||||
class Provider: ZigProjectConfigurationProvider {
|
||||
override fun create(project: Project?): SubConfigurable<Project>? {
|
||||
return ZigToolchainEditor(project?.isDefault ?: false).also { it.reset(project) }
|
||||
}
|
||||
|
||||
override val index: Int get() = 0
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,57 +22,30 @@
|
|||
|
||||
package com.falsepattern.zigbrains.project.toolchain.ui
|
||||
|
||||
import com.falsepattern.zigbrains.Icons
|
||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||
import com.falsepattern.zigbrains.project.toolchain.ToolchainListChangeListener
|
||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService
|
||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
||||
import com.falsepattern.zigbrains.project.toolchain.base.createNamedConfigurable
|
||||
import com.falsepattern.zigbrains.project.toolchain.base.suggestZigToolchains
|
||||
import com.falsepattern.zigbrains.project.toolchain.downloader.Downloader
|
||||
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
|
||||
import com.falsepattern.zigbrains.shared.coroutine.asContextElement
|
||||
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
|
||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.Presentation
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.openapi.ui.DialogBuilder
|
||||
import com.intellij.openapi.ui.MasterDetailsComponent
|
||||
import com.intellij.openapi.ui.NamedConfigurable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
||||
import com.intellij.ui.DocumentAdapter
|
||||
import com.intellij.ui.components.JBLabel
|
||||
import com.intellij.ui.components.textFieldWithBrowseButton
|
||||
import com.intellij.ui.dsl.builder.AlignX
|
||||
import com.intellij.ui.dsl.builder.panel
|
||||
import com.intellij.util.Consumer
|
||||
import com.intellij.util.IconUtil
|
||||
import com.intellij.util.asSafely
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.UUID
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.event.DocumentEvent
|
||||
import javax.swing.tree.DefaultTreeModel
|
||||
|
||||
class ZigToolchainListEditor : MasterDetailsComponent(), ToolchainListChangeListener {
|
||||
private var isTreeInitialized = false
|
||||
private var registered: Boolean = false
|
||||
private var itemSelectedListeners = ArrayList<Consumer<UUID?>>()
|
||||
|
||||
fun addItemSelectedListener(c: Consumer<UUID?>) {
|
||||
synchronized(itemSelectedListeners) {
|
||||
itemSelectedListeners.add(c)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
if (!isTreeInitialized) {
|
||||
|
@ -102,14 +75,6 @@ class ZigToolchainListEditor : MasterDetailsComponent(), ToolchainListChangeList
|
|||
return listOf(add, MyDeleteAction())
|
||||
}
|
||||
|
||||
override fun updateSelection(configurable: NamedConfigurable<*>?) {
|
||||
super.updateSelection(configurable)
|
||||
val uuid = configurable?.editableObject as? UUID
|
||||
synchronized(itemSelectedListeners) {
|
||||
itemSelectedListeners.forEach { it.consume(uuid) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemDeleted(item: Any?) {
|
||||
if (item is UUID) {
|
||||
ZigToolchainListService.getInstance().removeToolchain(item)
|
||||
|
|
|
@ -27,6 +27,7 @@ import com.intellij.openapi.options.Configurable
|
|||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.ui.dsl.builder.Panel
|
||||
import com.intellij.ui.dsl.builder.panel
|
||||
import java.util.ArrayList
|
||||
import javax.swing.JComponent
|
||||
|
||||
interface SubConfigurable<T>: Disposable {
|
||||
|
@ -38,40 +39,56 @@ interface SubConfigurable<T>: Disposable {
|
|||
val newProjectBeforeInitSelector: Boolean get() = false
|
||||
|
||||
abstract class Adapter<T>: Configurable {
|
||||
private var myConfigurable: SubConfigurable<T>? = null
|
||||
private val myConfigurables: MutableList<SubConfigurable<T>> = ArrayList()
|
||||
|
||||
abstract fun instantiate(): SubConfigurable<T>
|
||||
abstract fun instantiate(): List<SubConfigurable<T>>
|
||||
protected abstract val context: T
|
||||
|
||||
override fun createComponent(): JComponent? {
|
||||
if (myConfigurable != null) {
|
||||
disposeUIResources()
|
||||
val configurables: List<SubConfigurable<T>>
|
||||
synchronized(myConfigurables) {
|
||||
if (myConfigurables.isEmpty()) {
|
||||
disposeConfigurables()
|
||||
}
|
||||
configurables = instantiate()
|
||||
configurables.forEach { it.reset(context) }
|
||||
myConfigurables.clear()
|
||||
myConfigurables.addAll(configurables)
|
||||
}
|
||||
val configurable = instantiate()
|
||||
configurable.reset(context)
|
||||
myConfigurable = configurable
|
||||
return panel {
|
||||
configurable.attach(this)
|
||||
configurables.forEach { it.attach(this) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return myConfigurable?.isModified(context) == true
|
||||
synchronized(myConfigurables) {
|
||||
return myConfigurables.any { it.isModified(context) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
myConfigurable?.apply(context)
|
||||
synchronized(myConfigurables) {
|
||||
myConfigurables.forEach { it.apply(context) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
myConfigurable?.reset(context)
|
||||
synchronized(myConfigurables) {
|
||||
myConfigurables.forEach { it.reset(context) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun disposeUIResources() {
|
||||
val configurable = myConfigurable
|
||||
myConfigurable = null
|
||||
configurable?.let { Disposer.dispose(it) }
|
||||
synchronized(myConfigurables) {
|
||||
disposeConfigurables()
|
||||
}
|
||||
super.disposeUIResources()
|
||||
}
|
||||
|
||||
private fun disposeConfigurables() {
|
||||
val configurables = ArrayList(myConfigurables)
|
||||
myConfigurables.clear()
|
||||
configurables.forEach { Disposer.dispose(it) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -140,15 +140,17 @@
|
|||
/>
|
||||
<projectConfigurable
|
||||
parentId="language"
|
||||
instance="com.falsepattern.zigbrains.project.toolchain.ui.ZigToolchainEditor$Adapter"
|
||||
instance="com.falsepattern.zigbrains.project.settings.ZigConfigurable"
|
||||
id="ZigConfigurable"
|
||||
displayName="Zig"
|
||||
bundle="zigbrains.Bundle"
|
||||
key="settings.project.display-name"
|
||||
/>
|
||||
<applicationConfigurable
|
||||
parentId="ZigConfigurable"
|
||||
instance="com.falsepattern.zigbrains.project.toolchain.ui.ZigToolchainListEditor"
|
||||
id="ZigToolchainConfigurable"
|
||||
displayName="Toolchain"
|
||||
bundle="zigbrains.Bundle"
|
||||
key="settings.toolchain.list.title"
|
||||
/>
|
||||
|
||||
<programRunner
|
||||
|
@ -186,7 +188,7 @@
|
|||
implementation="com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchainProvider"
|
||||
/>
|
||||
<projectConfigProvider
|
||||
implementation="com.falsepattern.zigbrains.project.settings.ZigCoreProjectConfigurationProvider"
|
||||
implementation="com.falsepattern.zigbrains.project.toolchain.ui.ZigToolchainEditor$Provider"
|
||||
/>
|
||||
</extensions>
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ build.tool.window.status.error.general=Error while running zig build -l
|
|||
build.tool.window.status.no-builds=No builds currently in progress
|
||||
build.tool.window.status.timeout=zig build -l timed out after {0} seconds.
|
||||
zig=Zig
|
||||
settings.project.display-name=Zig
|
||||
settings.toolchain.base.name.label=Name
|
||||
settings.toolchain.local.path.label=Toolchain location
|
||||
settings.toolchain.local.version.label=Detected zig version
|
||||
|
|
Loading…
Add table
Reference in a new issue