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 {
|
class ZigNewProjectPanel(private var handleGit: Boolean): Disposable {
|
||||||
private val git = JBCheckBox()
|
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 {
|
private val templateList = JBList(JBList.createDefaultListModel(defaultTemplates)).apply {
|
||||||
selectionMode = ListSelectionModel.SINGLE_SELECTION
|
selectionMode = ListSelectionModel.SINGLE_SELECTION
|
||||||
selectedIndex = 0
|
selectedIndex = 0
|
||||||
|
|
|
@ -22,23 +22,15 @@
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.settings
|
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.falsepattern.zigbrains.shared.SubConfigurable
|
||||||
import com.intellij.openapi.options.Configurable
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.NlsContexts
|
||||||
|
|
||||||
class ZigCoreProjectConfigurationProvider: ZigProjectConfigurationProvider {
|
class ZigConfigurable(override val context: Project) : SubConfigurable.Adapter<Project>() {
|
||||||
override fun handleMainConfigChanged(project: Project) {
|
override fun instantiate(): List<SubConfigurable<Project>> {
|
||||||
|
return ZigProjectConfigurationProvider.createPanels(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createConfigurable(project: Project): Configurable {
|
override fun getDisplayName() = ZigBrainsBundle.message("settings.project.display-name")
|
||||||
return ZigToolchainEditor.Adapter(project)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createNewProjectSettingsPanel(): SubConfigurable<Project> {
|
|
||||||
return ZigToolchainEditor().also { it.reset(null) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override val priority: Int
|
|
||||||
get() = 0
|
|
||||||
}
|
}
|
|
@ -24,24 +24,15 @@ package com.falsepattern.zigbrains.project.settings
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.shared.SubConfigurable
|
import com.falsepattern.zigbrains.shared.SubConfigurable
|
||||||
import com.intellij.openapi.extensions.ExtensionPointName
|
import com.intellij.openapi.extensions.ExtensionPointName
|
||||||
import com.intellij.openapi.options.Configurable
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
|
||||||
interface ZigProjectConfigurationProvider {
|
interface ZigProjectConfigurationProvider {
|
||||||
fun handleMainConfigChanged(project: Project)
|
fun create(project: Project?): SubConfigurable<Project>?
|
||||||
fun createConfigurable(project: Project): Configurable
|
val index: Int
|
||||||
fun createNewProjectSettingsPanel(): SubConfigurable<Project>?
|
|
||||||
val priority: Int
|
|
||||||
companion object {
|
companion object {
|
||||||
private val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigProjectConfigurationProvider>("com.falsepattern.zigbrains.projectConfigProvider")
|
private val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigProjectConfigurationProvider>("com.falsepattern.zigbrains.projectConfigProvider")
|
||||||
fun mainConfigChanged(project: Project) {
|
fun createPanels(project: Project?): List<SubConfigurable<Project>> {
|
||||||
EXTENSION_POINT_NAME.extensionList.forEach { it.handleMainConfigChanged(project) }
|
return EXTENSION_POINT_NAME.extensionList.sortedBy { it.index }.mapNotNull { it.create(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() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -150,6 +150,20 @@ fun getSuggestedLocalToolchainPath(): Path? {
|
||||||
return getWellKnown().getOrNull(0)
|
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> {
|
private fun getWellKnown(): List<Path> {
|
||||||
val home = System.getProperty("user.home")?.toNioPathOrNull() ?: return emptyList()
|
val home = System.getProperty("user.home")?.toNioPathOrNull() ?: return emptyList()
|
||||||
val xdgDataHome = when(OS.CURRENT) {
|
val xdgDataHome = when(OS.CURRENT) {
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
package com.falsepattern.zigbrains.project.toolchain.ui
|
package com.falsepattern.zigbrains.project.toolchain.ui
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
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.ToolchainListChangeListener
|
||||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService
|
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService
|
||||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainService
|
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainService
|
||||||
|
@ -169,9 +170,13 @@ class ZigToolchainEditor(private val isForDefaultProject: Boolean = false): SubC
|
||||||
|
|
||||||
override val newProjectBeforeInitSelector get() = true
|
override val newProjectBeforeInitSelector get() = true
|
||||||
|
|
||||||
class Adapter(override val context: Project): SubConfigurable.Adapter<Project>() {
|
class Provider: ZigProjectConfigurationProvider {
|
||||||
override fun instantiate() = ZigToolchainEditor(context.isDefault)
|
override fun create(project: Project?): SubConfigurable<Project>? {
|
||||||
override fun getDisplayName() = ZigBrainsBundle.message("settings.toolchain.editor.display-name")
|
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
|
package com.falsepattern.zigbrains.project.toolchain.ui
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.Icons
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||||
import com.falsepattern.zigbrains.project.toolchain.ToolchainListChangeListener
|
import com.falsepattern.zigbrains.project.toolchain.ToolchainListChangeListener
|
||||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService
|
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.createNamedConfigurable
|
import com.falsepattern.zigbrains.project.toolchain.base.createNamedConfigurable
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.suggestZigToolchains
|
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.asContextElement
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
|
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
|
||||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
||||||
import com.intellij.icons.AllIcons
|
|
||||||
import com.intellij.openapi.actionSystem.AnAction
|
import com.intellij.openapi.actionSystem.AnAction
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
import com.intellij.openapi.actionSystem.Presentation
|
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.project.DumbAwareAction
|
||||||
import com.intellij.openapi.ui.DialogBuilder
|
|
||||||
import com.intellij.openapi.ui.MasterDetailsComponent
|
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.IconUtil
|
||||||
import com.intellij.util.asSafely
|
import com.intellij.util.asSafely
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.swing.JComponent
|
import javax.swing.JComponent
|
||||||
import javax.swing.event.DocumentEvent
|
|
||||||
import javax.swing.tree.DefaultTreeModel
|
import javax.swing.tree.DefaultTreeModel
|
||||||
|
|
||||||
class ZigToolchainListEditor : MasterDetailsComponent(), ToolchainListChangeListener {
|
class ZigToolchainListEditor : MasterDetailsComponent(), ToolchainListChangeListener {
|
||||||
private var isTreeInitialized = false
|
private var isTreeInitialized = false
|
||||||
private var registered: Boolean = 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 {
|
override fun createComponent(): JComponent {
|
||||||
if (!isTreeInitialized) {
|
if (!isTreeInitialized) {
|
||||||
|
@ -102,14 +75,6 @@ class ZigToolchainListEditor : MasterDetailsComponent(), ToolchainListChangeList
|
||||||
return listOf(add, MyDeleteAction())
|
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?) {
|
override fun onItemDeleted(item: Any?) {
|
||||||
if (item is UUID) {
|
if (item is UUID) {
|
||||||
ZigToolchainListService.getInstance().removeToolchain(item)
|
ZigToolchainListService.getInstance().removeToolchain(item)
|
||||||
|
|
|
@ -27,6 +27,7 @@ import com.intellij.openapi.options.Configurable
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import com.intellij.ui.dsl.builder.Panel
|
import com.intellij.ui.dsl.builder.Panel
|
||||||
import com.intellij.ui.dsl.builder.panel
|
import com.intellij.ui.dsl.builder.panel
|
||||||
|
import java.util.ArrayList
|
||||||
import javax.swing.JComponent
|
import javax.swing.JComponent
|
||||||
|
|
||||||
interface SubConfigurable<T>: Disposable {
|
interface SubConfigurable<T>: Disposable {
|
||||||
|
@ -38,40 +39,56 @@ interface SubConfigurable<T>: Disposable {
|
||||||
val newProjectBeforeInitSelector: Boolean get() = false
|
val newProjectBeforeInitSelector: Boolean get() = false
|
||||||
|
|
||||||
abstract class Adapter<T>: Configurable {
|
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
|
protected abstract val context: T
|
||||||
|
|
||||||
override fun createComponent(): JComponent? {
|
override fun createComponent(): JComponent? {
|
||||||
if (myConfigurable != null) {
|
val configurables: List<SubConfigurable<T>>
|
||||||
disposeUIResources()
|
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 {
|
return panel {
|
||||||
configurable.attach(this)
|
configurables.forEach { it.attach(this) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isModified(): Boolean {
|
override fun isModified(): Boolean {
|
||||||
return myConfigurable?.isModified(context) == true
|
synchronized(myConfigurables) {
|
||||||
|
return myConfigurables.any { it.isModified(context) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun apply() {
|
override fun apply() {
|
||||||
myConfigurable?.apply(context)
|
synchronized(myConfigurables) {
|
||||||
|
myConfigurables.forEach { it.apply(context) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset() {
|
override fun reset() {
|
||||||
myConfigurable?.reset(context)
|
synchronized(myConfigurables) {
|
||||||
|
myConfigurables.forEach { it.reset(context) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun disposeUIResources() {
|
override fun disposeUIResources() {
|
||||||
val configurable = myConfigurable
|
synchronized(myConfigurables) {
|
||||||
myConfigurable = null
|
disposeConfigurables()
|
||||||
configurable?.let { Disposer.dispose(it) }
|
}
|
||||||
super.disposeUIResources()
|
super.disposeUIResources()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun disposeConfigurables() {
|
||||||
|
val configurables = ArrayList(myConfigurables)
|
||||||
|
myConfigurables.clear()
|
||||||
|
configurables.forEach { Disposer.dispose(it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -140,15 +140,17 @@
|
||||||
/>
|
/>
|
||||||
<projectConfigurable
|
<projectConfigurable
|
||||||
parentId="language"
|
parentId="language"
|
||||||
instance="com.falsepattern.zigbrains.project.toolchain.ui.ZigToolchainEditor$Adapter"
|
instance="com.falsepattern.zigbrains.project.settings.ZigConfigurable"
|
||||||
id="ZigConfigurable"
|
id="ZigConfigurable"
|
||||||
displayName="Zig"
|
bundle="zigbrains.Bundle"
|
||||||
|
key="settings.project.display-name"
|
||||||
/>
|
/>
|
||||||
<applicationConfigurable
|
<applicationConfigurable
|
||||||
parentId="ZigConfigurable"
|
parentId="ZigConfigurable"
|
||||||
instance="com.falsepattern.zigbrains.project.toolchain.ui.ZigToolchainListEditor"
|
instance="com.falsepattern.zigbrains.project.toolchain.ui.ZigToolchainListEditor"
|
||||||
id="ZigToolchainConfigurable"
|
id="ZigToolchainConfigurable"
|
||||||
displayName="Toolchain"
|
bundle="zigbrains.Bundle"
|
||||||
|
key="settings.toolchain.list.title"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<programRunner
|
<programRunner
|
||||||
|
@ -186,7 +188,7 @@
|
||||||
implementation="com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchainProvider"
|
implementation="com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchainProvider"
|
||||||
/>
|
/>
|
||||||
<projectConfigProvider
|
<projectConfigProvider
|
||||||
implementation="com.falsepattern.zigbrains.project.settings.ZigCoreProjectConfigurationProvider"
|
implementation="com.falsepattern.zigbrains.project.toolchain.ui.ZigToolchainEditor$Provider"
|
||||||
/>
|
/>
|
||||||
</extensions>
|
</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.no-builds=No builds currently in progress
|
||||||
build.tool.window.status.timeout=zig build -l timed out after {0} seconds.
|
build.tool.window.status.timeout=zig build -l timed out after {0} seconds.
|
||||||
zig=Zig
|
zig=Zig
|
||||||
|
settings.project.display-name=Zig
|
||||||
settings.toolchain.base.name.label=Name
|
settings.toolchain.base.name.label=Name
|
||||||
settings.toolchain.local.path.label=Toolchain location
|
settings.toolchain.local.path.label=Toolchain location
|
||||||
settings.toolchain.local.version.label=Detected zig version
|
settings.toolchain.local.version.label=Detected zig version
|
||||||
|
|
Loading…
Add table
Reference in a new issue