Skip to content

Commit

Permalink
Merge pull request #40 from Jozott00/fix/ui-freeze-startup
Browse files Browse the repository at this point in the history
Fix/UI freeze startup
  • Loading branch information
Jozott00 committed Mar 6, 2024
2 parents 33b91cf + 1142fb1 commit 5ee7909
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 90 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,27 @@

## [Unreleased]

### Bugfix

- UI Freezes on startup (when debug config selected)

### Added

- Support for Intellij platform 2024.1

## [0.10.0] - 2024-03-04

This update switches from the custom run toolwindow
to a headless run configuration, which is more familiar for
most Intellij users.

### Added

- Run configuration for simulator instance
- Automatic GDB port selection

### Removed

- WokwiDebugStart configuration
- Wokwi Run toolwindow

Expand All @@ -28,5 +38,7 @@ most Intellij users.
- Wokwi simulation debugging support

[Unreleased]: https://github.com/Jozott00/wokwi-intellij/compare/v0.10.0...HEAD

[0.10.0]: https://github.com/Jozott00/wokwi-intellij/commits/v0.10.0

[0.9.0]: https://github.com/Jozott00/wokwi-intellij/commits/v0.9.0
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ pluginGroup=com.github.jozott00.wokwiintellij
pluginName=wokwi-intellij
pluginRepositoryUrl=https://github.com/Jozott00/wokwi-intellij
# SemVer format -> https://semver.org
pluginVersion=0.10.0
pluginVersion=0.10.1
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild=232
pluginUntilBuild=233.*
pluginUntilBuild=241.*
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType=CL
platformVersion=2023.2
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
package com.github.jozott00.wokwiintellij.execution.macros

import com.github.jozott00.wokwiintellij.extensions.wokwiCoroutineChildScope
import com.github.jozott00.wokwiintellij.toml.WokwiConfigProcessor
import com.intellij.ide.macro.Macro
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking

class ElfPathMacro : Macro() {
override fun getName() = "WokwiElfPath"

override fun getDescription() = "Resolves to the ELF file path specified in the Wokwi configuration."

override fun expand(dataContext: DataContext): String? {
val project = CommonDataKeys.PROJECT.getData(dataContext) ?: return null
val config = runBlocking(Dispatchers.IO) { WokwiConfigProcessor.findElfFile(project) } ?: return null
override fun expand(dataContext: DataContext): String {
val project = CommonDataKeys.PROJECT.getData(dataContext) ?: throw ExecutionCancelledException()

val config = runBlocking {
project.wokwiCoroutineChildScope("ElfPathMacro").async(Dispatchers.IO) {
WokwiConfigProcessor.findElfFile(project)
}.await()
}
?: throw ExecutionCancelledException()
return config.path
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
package com.github.jozott00.wokwiintellij.execution.macros

import com.github.jozott00.wokwiintellij.services.WokwiSimulatorService
import com.github.jozott00.wokwiintellij.toml.WokwiConfigProcessor
import com.intellij.ide.macro.Macro
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.components.service
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking

class GdbServerMacro : Macro() {
override fun getName() = "WokwiGdbServer"

override fun getDescription() = "Resolves to the Wokwi's GDB Server address"

override fun expand(dataContext: DataContext): String? {
val project = CommonDataKeys.PROJECT.getData(dataContext) ?: return null
val config = runBlocking(Dispatchers.IO) { WokwiConfigProcessor.readConfig(project) } ?: return null
val wokwiService = project.service<WokwiSimulatorService>()
override fun expand(dataContext: DataContext): String {
val project = CommonDataKeys.PROJECT.getData(dataContext) ?: throw ExecutionCancelledException()
val simulatorService = project.service<WokwiSimulatorService>()

val port = wokwiService.getRunningGDBPort() ?: config.gdbServerPort ?: return "localhost:<unknown-port>"
// only get config file if simulator currently running.
// prevents ui freezing on startup
if (!simulatorService.isSimulatorRunning()) return "<requires simulator startup>"

// val config = runBlocking(Dispatchers.IO) { WokwiConfigProcessor.readConfig(project) }
// ?: throw ExecutionCancelledException()
// val port = simulatorService.getRunningGDBPort() ?: config.gdbServerPort ?: return "localhost:<unknown-port>"
val port = simulatorService.getRunningGDBPort() ?: return "localhost:<unknown-port>"

return "localhost:$port"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import arrow.core.Either
import com.github.jozott00.wokwiintellij.simulator.WokwiConfig
import com.github.jozott00.wokwiintellij.simulator.args.WokwiArgs
import com.github.jozott00.wokwiintellij.simulator.args.WokwiArgsFirmware
import com.github.jozott00.wokwiintellij.simulator.args.WokwiProjectType
import com.github.jozott00.wokwiintellij.utils.WokwiNotifier.notifyBalloonAsync
import com.github.jozott00.wokwiintellij.utils.simulation.FirmwareUtils
import com.intellij.notification.NotificationType
Expand All @@ -30,9 +29,6 @@ class WokwiArgsLoader(val project: Project) {
val diagram = readAction { config.diagram.readText() }
val firmware = loadFirmware(config.firmware) ?: return null

val projectType = detectProject()
// TODO: Check for esp image

val args = WokwiArgs(license, diagram, firmware)
return args

Expand All @@ -54,14 +50,15 @@ class WokwiArgsLoader(val project: Project) {
val binaryPaths = mutableListOf(firmwareFile.path)

val buffer = if (isFlasherArgsFile) {
val packedResult=
val packedResult =
when (val result = FirmwareUtils.packEspIdfFirmware(firmwareFile)) {
is Either.Left -> {
notifyBalloonAsync(result.value)
return@withContext null
is Either.Left -> {
notifyBalloonAsync(result.value)
return@withContext null
}

is Either.Right -> result.value
}
is Either.Right -> result.value
}

binaryPaths.addAll(packedResult.binaryPaths)
packedResult.img
Expand All @@ -81,11 +78,6 @@ class WokwiArgsLoader(val project: Project) {
)
}

@Suppress("SameReturnValue")
private fun detectProject(): WokwiProjectType {
return WokwiProjectType.RUST
}

private suspend fun loadLicense() = licensingService.loadAndCheckLicense()
.onLeft {
notifyBalloonAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,52 +136,63 @@ object WokwiConfigProcessor {
FileEditorManager.getInstance(project).openTextEditor(descriptor, true)
}

private suspend fun findWokwiConfigPath(wokwiConfigPath: String, project: Project): VirtualFile? = withContext(Dispatchers.IO) { readAction { project
.findRelativeFiles(wokwiConfigPath)}.run {
if (isEmpty()) {
WokwiNotifier.notifyBalloon(
"Failed to load Wokwi config",
"Configuration file `$wokwiConfigPath` not found in project.",
type = NotificationType.ERROR
)
return@run null
}
if (size > 1) {
notifyError("Found multiple configuration files: \n${joinToString("\n")}. \nSpecify the concrete one in the Settings.")
return@run null
private suspend fun findWokwiConfigPath(wokwiConfigPath: String, project: Project): VirtualFile? =
withContext(Dispatchers.IO) {
readAction {
project
.findRelativeFiles(wokwiConfigPath)
}
}.run {
if (isEmpty()) {
WokwiNotifier.notifyBalloon(
"Failed to load Wokwi config",
"Configuration file `$wokwiConfigPath` not found in project.",
type = NotificationType.ERROR
)
return@run null
}
if (size > 1) {
notifyError("Found multiple configuration files: \n${joinToString("\n")}. \nSpecify the concrete one in the Settings.")
return@run null
}

return@run first()
}

return@run first()
}}

private suspend fun findWokwiDiagramPath(wokwiDiagramPath: String, project: Project): VirtualFile? = withContext(Dispatchers.IO) {readAction { project
.findRelativeFiles(wokwiDiagramPath) }.run {
if (isEmpty()) {
notifyError(
"Diagram file `$wokwiDiagramPath` not found in project.",
NotifyAction("Create diagram.json") { _, _ ->
val psiManager = PsiManager.getInstance(project)
val virtualFile = project.guessProjectDir() ?: return@NotifyAction
val psiDir = psiManager.findDirectory(virtualFile)
WriteCommandAction.runWriteCommandAction(project) {
val diagramFile =
psiDir?.createFile(WokwiConstants.WOKWI_DIAGRAM_FILE) ?: return@runWriteCommandAction
val document = diagramFile.viewProvider.document
document.setText(WokwiTemplates.defaultDiagramJson())
val descriptor =
OpenFileDescriptor(project, diagramFile.virtualFile)
FileEditorManager.getInstance(project).openTextEditor(descriptor, true)
}
private suspend fun findWokwiDiagramPath(wokwiDiagramPath: String, project: Project): VirtualFile? =
withContext(Dispatchers.IO) {
readAction {
project
.findRelativeFiles(wokwiDiagramPath)
}.run {
if (isEmpty()) {
notifyError(
"Diagram file `$wokwiDiagramPath` not found in project.",
NotifyAction("Create diagram.json") { _, _ ->
val psiManager = PsiManager.getInstance(project)
val virtualFile = project.guessProjectDir() ?: return@NotifyAction
val psiDir = psiManager.findDirectory(virtualFile)
WriteCommandAction.runWriteCommandAction(project) {
val diagramFile =
psiDir?.createFile(WokwiConstants.WOKWI_DIAGRAM_FILE)
?: return@runWriteCommandAction
val document = diagramFile.viewProvider.document
document.setText(WokwiTemplates.defaultDiagramJson())
val descriptor =
OpenFileDescriptor(project, diagramFile.virtualFile)
FileEditorManager.getInstance(project).openTextEditor(descriptor, true)
}
}
)
return@run null
}
)
return@run null
}
if (size > 1) {
notifyError("Found multiple diagram files: \n${joinToString("\n")}. \nSpecify the concrete one in the Settings.")
return@run null
if (size > 1) {
notifyError("Found multiple diagram files: \n${joinToString("\n")}. \nSpecify the concrete one in the Settings.")
return@run null
}
return@run first()
}
}
return@run first()
}}


}
Original file line number Diff line number Diff line change
Expand Up @@ -62,30 +62,32 @@ class LicensingPanel : ComponentContainer {
}

@Suppress("SameParameterValue")
private fun checkLicenseAvailability(recentlyChanged: Boolean = false) = runInBackground{ runBlocking(Dispatchers.IO) {
if (recentlyChanged) {
invokeLater { statusCardLayout.show(statusCard, "LOADING") }
delay(500)
}

val raw = licensingService.getLicense()
?: return@runBlocking invokeLater {
statusCardLayout.show(statusCard, "LICENSE_MISSING")
private fun checkLicenseAvailability(recentlyChanged: Boolean = false) = runInBackground {
runBlocking(Dispatchers.IO) {
if (recentlyChanged) {
invokeLater { statusCardLayout.show(statusCard, "LOADING") }
delay(500)
}

invokeLater {
val parsed = licensingService.parseLicense(raw)
val statusPanel = when {
val raw = licensingService.getLicense()
?: return@runBlocking invokeLater {
statusCardLayout.show(statusCard, "LICENSE_MISSING")
}

invokeLater {
val parsed = licensingService.parseLicense(raw)
val statusPanel = when {
parsed == null -> "LICENSE_INVALID"
!parsed.isValid() -> "LICENSE_EXPIRED"
else -> {
licensePlanPanel.text = "(${parsed.plan ?: "Community"})"
"LICENSE_SET"
}
}
statusCardLayout.show(statusCard, statusPanel)
statusCardLayout.show(statusCard, statusPanel)
}
}
} }
}

private fun buildStatus(valid: Boolean, message: String, plan: JLabel? = null) = panel {
row {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import com.intellij.ui.dsl.builder.Align
import com.intellij.ui.dsl.builder.BottomGap
import com.intellij.ui.dsl.builder.bindText
import com.intellij.ui.dsl.builder.panel
import com.intellij.ui.util.preferredWidth
import java.awt.Dimension
import kotlin.io.path.pathString
import kotlin.io.path.relativeTo

Expand Down Expand Up @@ -53,7 +53,7 @@ class WokwiConfigPanelBuilder(val project: Project, private val model: WokwiSett
group("Settings") {
row("wokwi.toml path: ") {
textFieldWithBrowseButton { getRootRelativePathOf(it) }.apply {
component.preferredWidth = 400
component.preferredSize = Dimension(400, component.preferredSize.height)
}
.validationOnInput {
ValidationInfo("Hello world", it)
Expand All @@ -76,7 +76,7 @@ class WokwiConfigPanelBuilder(val project: Project, private val model: WokwiSett

row("diagram.json path: ") {
textFieldWithBrowseButton { getRootRelativePathOf(it) }.apply {
component.preferredWidth = 400
component.preferredSize = Dimension(400, component.preferredSize.height)
}
.onChanged { _ -> onChange() }
.bindText(model::wokwiDiagramPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import com.intellij.ui.dsl.builder.BottomGap
import com.intellij.ui.dsl.builder.TopGap
import com.intellij.ui.dsl.builder.panel
import com.intellij.ui.jcef.JCEFHtmlPanel
import com.intellij.ui.util.preferredWidth
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
Expand All @@ -23,6 +22,7 @@ import org.cef.browser.CefFrame
import org.cef.handler.CefLoadHandler
import org.cef.handler.CefLoadHandlerAdapter
import java.awt.CardLayout
import java.awt.Dimension
import javax.swing.JComponent
import javax.swing.JPanel
import javax.swing.JProgressBar
Expand Down Expand Up @@ -72,7 +72,7 @@ class SimulatorJCEFHtmlPanel(parentDisposable: Disposable) : ComponentContainer
row {
cell(JProgressBar().also {
it.isIndeterminate = true
it.preferredWidth = 300
it.preferredSize = Dimension(300, it.preferredSize.height)
})
}
.topGap(TopGap.NONE)
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<notificationGroup id="Wokwi Simulator"
displayType="BALLOON"/>

<configurationType implementation="com.github.jozott00.wokwiintellij.execution.configs.WokwiRunConfigType"/>
<!-- <configurationType implementation="com.github.jozott00.wokwiintellij.execution.configs.WokwiRunConfigType"/>-->

<stepsBeforeRunProvider
implementation="com.github.jozott00.wokwiintellij.execution.runBefore.WokwiStartDebugBeforeRunTaskProvider"/>
Expand Down

0 comments on commit 5ee7909

Please sign in to comment.