Skip to content

Commit

Permalink
Improve restart routine & add more options to PluginOutput
Browse files Browse the repository at this point in the history
  • Loading branch information
serivesmejia committed Oct 29, 2024
1 parent 1386768 commit 57942a4
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 42 deletions.
40 changes: 28 additions & 12 deletions EOCV-Sim/src/main/java/com/github/serivesmejia/eocvsim/EOCVSim.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@ import org.opencv.core.Size
import org.openftc.easyopencv.TimestampedPipelineHandler
import java.awt.Dimension
import java.io.File
import java.lang.Thread.sleep
import javax.swing.SwingUtilities
import javax.swing.filechooser.FileFilter
import javax.swing.filechooser.FileNameExtensionFilter
import kotlin.jvm.Throws
import kotlin.system.exitProcess

/**
Expand Down Expand Up @@ -361,7 +363,30 @@ class EOCVSim(val params: Parameters = Parameters()) {

pluginManager.enablePlugins()

start()
try {
start()
} catch (e: InterruptedException) {
logger.warn("Main thread interrupted ($hexCode)", e)
}

if(!destroying) {
destroy(DestroyReason.THREAD_EXIT)
}

if (isRestarting) {
Thread.interrupted() //clear interrupted flag
EOCVSimFolder.lock?.lock?.close()

JavaProcess.killSubprocessesOnExit = false
Thread {
JavaProcess.exec(Main::class.java, null, null)
}.start()

sleep(1000)
}

logger.info("-- End of EasyOpenCV Simulator v$VERSION ($hexCode) --")
exitProcess(0)
}

/**
Expand All @@ -375,6 +400,7 @@ class EOCVSim(val params: Parameters = Parameters()) {
* are explicitly updated within this method
* @see init
*/
@Throws(InterruptedException::class)
private fun start() {
if(Thread.currentThread() != eocvSimThread) {
throw IllegalStateException("start() must be called from the EOCVSim thread")
Expand All @@ -397,7 +423,7 @@ class EOCVSim(val params: Parameters = Parameters()) {
} else null
)

//limit FPG
//limit FPS
fpsLimiter.maxFPS = config.pipelineMaxFps.fps.toDouble()
try {
fpsLimiter.sync()
Expand All @@ -407,16 +433,6 @@ class EOCVSim(val params: Parameters = Parameters()) {
}

logger.warn("Main thread interrupted ($hexCode)")

if(!destroying) {
destroy(DestroyReason.THREAD_EXIT)
}

if (isRestarting) {
Thread.interrupted() //clear interrupted flag
EOCVSimFolder.lock?.lock?.close()
JavaProcess.exec(Main::class.java, null, null)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import com.github.serivesmejia.eocvsim.gui.dialog.component.BottomButtonsPanel
import com.github.serivesmejia.eocvsim.gui.dialog.component.OutputPanel
import io.github.deltacv.eocvsim.plugin.loader.PluginManager
import io.github.deltacv.eocvsim.plugin.loader.PluginSource
import io.github.deltacv.eocvsim.plugin.repository.PluginRepositoryManager
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
Expand All @@ -36,10 +37,11 @@ import kotlinx.coroutines.swing.Swing
import java.awt.Dimension
import java.awt.GridBagConstraints
import java.awt.GridBagLayout
import java.awt.GridLayout
import java.awt.Toolkit
import java.awt.Color
import java.awt.datatransfer.StringSelection
import javax.swing.*
import java.awt.Desktop
import javax.swing.event.ChangeEvent
import javax.swing.event.ChangeListener

Expand Down Expand Up @@ -135,7 +137,7 @@ class PluginOutput(
registerListeners()

output.pack()
output.setSize(500, 350)
output.setSize(500, 365)

appendDelegate.subscribe(this)

Expand Down Expand Up @@ -182,6 +184,7 @@ class PluginOutput(
)

if(dialogResult == JOptionPane.YES_OPTION) {
output.isVisible = false
eocvSim.restart()
}

Expand All @@ -190,8 +193,8 @@ class PluginOutput(
}

private fun makePluginManagerPanel(): JPanel {
val panel = JPanel()
panel.layout = GridBagLayout()
val pluginsPanel = JPanel()
pluginsPanel.layout = GridBagLayout()

if(pluginManager.loaders.isEmpty()) {
// center vertically and horizontally
Expand All @@ -209,7 +212,7 @@ class PluginOutput(
}

// Add the label to the panel with the constraints
panel.add(noPluginsLabel, constraints)
pluginsPanel.add(noPluginsLabel, constraints)
} else {
val tabbedPane = JTabbedPane(JTabbedPane.LEFT)

Expand Down Expand Up @@ -291,7 +294,6 @@ class PluginOutput(
fun refreshButtons() {
disableButton.isEnabled = loader.shouldEnable
enableButton.isEnabled = !loader.shouldEnable

}

refreshButtons()
Expand Down Expand Up @@ -336,7 +338,7 @@ class PluginOutput(
tabbedPane.addTab(loader.pluginName, pluginPanel)
}

panel.add(tabbedPane, GridBagConstraints().apply {
pluginsPanel.add(tabbedPane, GridBagConstraints().apply {
gridx = 0
gridy = 0
weightx = 1.0
Expand All @@ -345,6 +347,93 @@ class PluginOutput(
})
}

val panel = JPanel()

panel.layout = GridBagLayout()
panel.add(pluginsPanel, GridBagConstraints().apply {
gridx = 0
gridy = 0
weightx = 1.0
weighty = 1.0
fill = GridBagConstraints.BOTH
})

val bottomButtonsPanel = JPanel()
bottomButtonsPanel.layout = BoxLayout(bottomButtonsPanel, BoxLayout.PAGE_AXIS)

val openPluginsFolderButton = JButton("Open plugins folder")

openPluginsFolderButton.addActionListener {
val pluginsFolder = PluginManager.PLUGIN_FOLDER

if(pluginsFolder.exists() && Desktop.isDesktopSupported()) {
Desktop.getDesktop().open(pluginsFolder)
} else {
JOptionPane.showMessageDialog(
output,
"Unable to open plugins folder, the folder does not exist or the operation is unsupported.",
"Operation failed",
JOptionPane.ERROR_MESSAGE
)
}
}

val startFreshButton = JButton("Start fresh")

startFreshButton.addActionListener {
val dialogResult = JOptionPane.showConfirmDialog(
output,
"Are you sure you want to start fresh? This will remove all plugins from all sources.",
"Start fresh",
JOptionPane.YES_NO_OPTION
)

if(dialogResult == JOptionPane.YES_OPTION) {
eocvSim?.config?.flags?.set("startFresh", true)

PluginRepositoryManager.REPOSITORY_FILE.delete()
PluginRepositoryManager.CACHE_FILE.delete()

shouldAskForRestart = true
checkShouldAskForRestart()
}
}

val closeButton = JButton("Close")

closeButton.addActionListener {
close()
}

val buttonsPanel = JPanel()
buttonsPanel.layout = BoxLayout(buttonsPanel, BoxLayout.LINE_AXIS)
buttonsPanel.border = BorderFactory.createEmptyBorder(5, 0, 5, 0)

buttonsPanel.add(Box.createHorizontalGlue())

buttonsPanel.add(openPluginsFolderButton)
buttonsPanel.add(Box.createRigidArea(Dimension(5, 0)))
buttonsPanel.add(startFreshButton)
buttonsPanel.add(Box.createRigidArea(Dimension(5, 0)))
buttonsPanel.add(closeButton)

buttonsPanel.add(Box.createHorizontalGlue())

bottomButtonsPanel.add(buttonsPanel)

// Set a thin light gray line border with padding
bottomButtonsPanel.border = BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10, 10, 10, 10), // Padding inside the border
JScrollPane().border
)

panel.add(bottomButtonsPanel, GridBagConstraints().apply {
gridx = 0
gridy = 2
weightx = 1.0
fill = GridBagConstraints.HORIZONTAL
})

return panel
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

package com.github.serivesmejia.eocvsim.gui.dialog.component

import com.formdev.flatlaf.FlatLaf
import java.awt.Dimension
import java.awt.GridBagConstraints
import java.awt.GridBagLayout
Expand All @@ -31,6 +32,7 @@ import java.awt.datatransfer.StringSelection
import java.awt.Font
import java.io.InputStream
import javax.swing.*
import kotlin.math.roundToInt


class OutputPanel(
Expand Down Expand Up @@ -60,7 +62,16 @@ class OutputPanel(
outputArea.highlighter = null

// set the background color to a darker tone
outputArea.background = outputArea.background.darker()
outputArea.background = if(FlatLaf.isLafDark()) {
outputArea.background.darker()
} else {
java.awt.Color(
(outputArea.background.red * 0.95).roundToInt(),
(outputArea.background.green * 0.95).roundToInt(),
(outputArea.background.blue * 0.95).roundToInt(),
255
)
}

val outputScroll = JScrollPane(outputArea)
outputScroll.verticalScrollBarPolicy = JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ private JavaProcess() {}

private static int count;

public static boolean killSubprocessesOnExit = true;

private static final Logger logger = LoggerFactory.getLogger(JavaProcess.class);

/**
Expand Down Expand Up @@ -143,6 +145,7 @@ public static int execClasspath(Class klass, ProcessIOReceiver ioReceiver, Strin
}

private static void killOnExit(Process process) {
if(!killSubprocessesOnExit) return;
Runtime.getRuntime().addShutdownHook(new Thread(process::destroy));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import io.github.deltacv.eocvsim.sandbox.restrictions.dynamicLoadingMethodBlackl
import io.github.deltacv.eocvsim.sandbox.restrictions.dynamicLoadingPackageBlacklist
import io.github.deltacv.eocvsim.sandbox.restrictions.dynamicLoadingPackageWhitelist
import java.io.ByteArrayOutputStream
import java.lang.ref.WeakReference
import java.io.File
import java.io.IOException
import java.io.InputStream
Expand All @@ -50,6 +51,8 @@ class PluginClassLoader(
val pluginContextProvider: () -> PluginContext
) : ClassLoader() {

private var additionalZipFiles = mutableListOf<WeakReference<ZipFile>>()

private val zipFile = try {
ZipFile(pluginJar)
} catch (e: Exception) {
Expand Down Expand Up @@ -172,11 +175,8 @@ class PluginClassLoader(
val entry = zipFile.getEntry(name)

if (entry != null) {
try {
// Construct a URL for the resource inside the plugin JAR
return URL("jar:file:${pluginJar.absolutePath}!/$name")
} catch (e: Exception) {
}
// Construct a URL for the resource inside the plugin JAR
return URL("jar:file:${pluginJar.absolutePath}!/$name")
} else {
resourceFromClasspath(name)?.let { return it }
}
Expand All @@ -198,9 +198,13 @@ class PluginClassLoader(

if (entry != null) {
try {
additionalZipFiles.add(WeakReference(zipFile))
return zipFile.getInputStream(entry)
} catch (e: Exception) {
zipFile.close()
}
} else {
zipFile.close()
}
}

Expand Down Expand Up @@ -256,6 +260,13 @@ class PluginClassLoader(
return null
}

fun close() {
zipFile.close()
for(ref in additionalZipFiles) {
ref.get()?.close()
}
}

override fun toString() = "PluginClassLoader@\"${pluginJar.name}\""

}
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ class PluginLoader(
fileSystem.close()
enabled = false
EventHandler.banClassLoader(pluginClassLoader)

pluginClassLoader.close()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,23 @@ class PluginManager(val eocvSim: EOCVSim) {

repositoryManager.init()

val pluginFiles = mutableListOf<File>()
pluginFiles.addAll(repositoryManager.resolveAll())
val pluginFilesInFolder = PLUGIN_FOLDER.listFiles()?.let {
it.filter { file -> file.extension == "jar" }
} ?: emptyList()

PLUGIN_FOLDER.listFiles()?.let {
pluginFiles.addAll(it.filter { it.extension == "jar" })
_pluginFiles.addAll(repositoryManager.resolveAll())

if(eocvSim.config.flags.getOrDefault("startFresh", false)) {
logger.warn("startFresh = true, deleting all plugins in the plugins folder")

for (file in pluginFilesInFolder) {
file.delete()
}

eocvSim.config.flags["startFresh"] = false
eocvSim.configManager.saveToFile()
} else {
_pluginFiles.addAll(pluginFilesInFolder)
}

for (file in pluginFiles) {
Expand Down
Loading

0 comments on commit 57942a4

Please sign in to comment.