mirror of
https://gitlab.com/2009scape/rt4-client.git
synced 2025-12-09 16:45:46 -07:00
Little vibe session with Qwen3-coder for a more 'runelite' settings manager
This commit is contained in:
parent
ae7723b0d2
commit
ac2478d10f
1 changed files with 313 additions and 88 deletions
|
|
@ -2,6 +2,7 @@ package KondoKit
|
||||||
|
|
||||||
import KondoKit.Helpers.convertValue
|
import KondoKit.Helpers.convertValue
|
||||||
import KondoKit.Helpers.showToast
|
import KondoKit.Helpers.showToast
|
||||||
|
import KondoKit.ScrollablePanel
|
||||||
import KondoKit.plugin.Companion.TITLE_BAR_COLOR
|
import KondoKit.plugin.Companion.TITLE_BAR_COLOR
|
||||||
import KondoKit.plugin.Companion.TOOLTIP_BACKGROUND
|
import KondoKit.plugin.Companion.TOOLTIP_BACKGROUND
|
||||||
import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR
|
import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR
|
||||||
|
|
@ -18,6 +19,7 @@ import java.awt.event.MouseEvent
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.Timer
|
import java.util.Timer
|
||||||
import javax.swing.*
|
import javax.swing.*
|
||||||
|
import javax.swing.border.AbstractBorder
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -32,85 +34,275 @@ object ReflectiveEditorView {
|
||||||
var reflectiveEditorView: JPanel? = null
|
var reflectiveEditorView: JPanel? = null
|
||||||
private val loadedPlugins: MutableList<String> = mutableListOf()
|
private val loadedPlugins: MutableList<String> = mutableListOf()
|
||||||
const val VIEW_NAME = "REFLECTIVE_EDITOR_VIEW"
|
const val VIEW_NAME = "REFLECTIVE_EDITOR_VIEW"
|
||||||
|
const val PLUGIN_LIST_VIEW = "PLUGIN_LIST"
|
||||||
|
const val PLUGIN_DETAIL_VIEW = "PLUGIN_DETAIL"
|
||||||
|
|
||||||
|
// Card layout for switching between views within the reflective editor view
|
||||||
|
private lateinit var cardLayout: CardLayout
|
||||||
|
private lateinit var mainPanel: JPanel
|
||||||
|
private var currentPluginInfo: PluginInfo? = null
|
||||||
|
private var currentPlugin: Plugin? = null
|
||||||
|
|
||||||
fun createReflectiveEditorView() {
|
fun createReflectiveEditorView() {
|
||||||
val reflectiveEditorPanel = JPanel(BorderLayout())
|
// Create the main panel with card layout
|
||||||
reflectiveEditorPanel.background = VIEW_BACKGROUND_COLOR
|
cardLayout = CardLayout()
|
||||||
reflectiveEditorPanel.add(Box.createVerticalStrut(5))
|
mainPanel = JPanel(cardLayout)
|
||||||
reflectiveEditorPanel.border = BorderFactory.createEmptyBorder(10, 10, 10, 10)
|
mainPanel.background = VIEW_BACKGROUND_COLOR
|
||||||
reflectiveEditorView = reflectiveEditorPanel
|
mainPanel.border = BorderFactory.createEmptyBorder(0, 0, 0, 0)
|
||||||
addPlugins(reflectiveEditorView!!)
|
|
||||||
|
// Create the plugin list view
|
||||||
|
val pluginListView = createPluginListView()
|
||||||
|
pluginListView.name = PLUGIN_LIST_VIEW
|
||||||
|
mainPanel.add(pluginListView, PLUGIN_LIST_VIEW)
|
||||||
|
|
||||||
|
// Create a placeholder for the plugin detail view
|
||||||
|
val pluginDetailView = JPanel(BorderLayout())
|
||||||
|
pluginDetailView.name = PLUGIN_DETAIL_VIEW
|
||||||
|
pluginDetailView.background = VIEW_BACKGROUND_COLOR
|
||||||
|
mainPanel.add(pluginDetailView, PLUGIN_DETAIL_VIEW)
|
||||||
|
|
||||||
|
// Set the reflectiveEditorView to our main panel
|
||||||
|
reflectiveEditorView = mainPanel
|
||||||
|
|
||||||
|
// Show the plugin list view by default
|
||||||
|
cardLayout.show(mainPanel, PLUGIN_LIST_VIEW)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addPlugins(reflectiveEditorView: JPanel) {
|
private fun createPluginListView(): JPanel {
|
||||||
reflectiveEditorView.removeAll() // clear previous
|
val panel = JPanel()
|
||||||
loadedPlugins.clear()
|
panel.layout = BoxLayout(panel, BoxLayout.Y_AXIS)
|
||||||
|
panel.background = VIEW_BACKGROUND_COLOR
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val loadedPluginsField = PluginRepository::class.java.getDeclaredField("loadedPlugins")
|
val loadedPluginsField = PluginRepository::class.java.getDeclaredField("loadedPlugins")
|
||||||
loadedPluginsField.isAccessible = true
|
loadedPluginsField.isAccessible = true
|
||||||
val loadedPlugins = loadedPluginsField.get(null) as HashMap<*, *>
|
val loadedPlugins = loadedPluginsField.get(null) as HashMap<*, *>
|
||||||
|
|
||||||
for ((pluginInfo, plugin) in loadedPlugins) {
|
for ((pluginInfo, plugin) in loadedPlugins) {
|
||||||
addPluginToEditor(reflectiveEditorView, pluginInfo as PluginInfo, plugin as Plugin)
|
val pluginPanel = createPluginItemPanel(pluginInfo as PluginInfo, plugin as Plugin)
|
||||||
|
panel.add(pluginPanel)
|
||||||
|
panel.add(Box.createVerticalStrut(5))
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a centered box for plugins that have no exposed fields
|
// Wrap the panel in a ScrollablePanel for custom scrolling
|
||||||
if (loadedPlugins.isNotEmpty()) {
|
val scrollablePanel = ScrollablePanel(panel)
|
||||||
val noExposedPanel = JPanel(BorderLayout())
|
|
||||||
noExposedPanel.background = VIEW_BACKGROUND_COLOR
|
|
||||||
noExposedPanel.border = BorderFactory.createEmptyBorder(10, 10, 10, 10)
|
|
||||||
|
|
||||||
val label = JLabel("Loaded Plugins without Exposed Fields", SwingConstants.CENTER)
|
// Reset scroll position to top
|
||||||
label.font = Font("RuneScape Small", Font.PLAIN, 16)
|
SwingUtilities.invokeLater {
|
||||||
label.foreground = primaryColor
|
// For ScrollablePanel, we need to reset the internal offset
|
||||||
noExposedPanel.add(label, BorderLayout.NORTH)
|
resetScrollablePanel(scrollablePanel)
|
||||||
|
|
||||||
val pluginsList = JList(loadedPlugins.toTypedArray())
|
|
||||||
pluginsList.background = WIDGET_COLOR
|
|
||||||
pluginsList.foreground = secondaryColor
|
|
||||||
pluginsList.font = Font("RuneScape Small", Font.PLAIN, 16)
|
|
||||||
|
|
||||||
// Wrap the JList in a JScrollPane with a fixed height
|
|
||||||
val maxScrollPaneHeight = 200
|
|
||||||
val scrollPane = JScrollPane(pluginsList).apply {
|
|
||||||
verticalScrollBarPolicy = JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
|
|
||||||
horizontalScrollBarPolicy = JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a wrapper panel with BoxLayout to constrain the scroll pane
|
val container = JPanel(BorderLayout())
|
||||||
val scrollPaneWrapper = JPanel().apply {
|
container.background = VIEW_BACKGROUND_COLOR
|
||||||
layout = BoxLayout(this, BoxLayout.Y_AXIS)
|
container.border = BorderFactory.createEmptyBorder(10, 5, 10, 5)
|
||||||
add(scrollPane)
|
container.add(scrollablePanel, BorderLayout.CENTER)
|
||||||
|
|
||||||
|
return container
|
||||||
}
|
}
|
||||||
|
|
||||||
noExposedPanel.add(scrollPaneWrapper, BorderLayout.CENTER)
|
private fun createPluginItemPanel(pluginInfo: PluginInfo, plugin: Plugin): JPanel {
|
||||||
|
val panel = JPanel(BorderLayout())
|
||||||
|
panel.background = WIDGET_COLOR
|
||||||
|
panel.border = BorderFactory.createEmptyBorder(10, 10, 10, 10)
|
||||||
|
panel.maximumSize = Dimension(Int.MAX_VALUE, 60)
|
||||||
|
// Remove fixed preferredSize to allow flexible width
|
||||||
|
// panel.preferredSize = Dimension(220, 60)
|
||||||
|
|
||||||
// Center the panel within the reflectiveEditorView
|
// Plugin name and version (using package name as in original implementation)
|
||||||
val centeredPanel = JPanel().apply {
|
val packageName = plugin.javaClass.`package`.name
|
||||||
preferredSize = Dimension(240, maxScrollPaneHeight)
|
val nameLabel = JLabel("$packageName v${pluginInfo.version}")
|
||||||
maximumSize = preferredSize
|
nameLabel.foreground = secondaryColor
|
||||||
minimumSize = preferredSize
|
nameLabel.font = Font("RuneScape Small", Font.BOLD, 16)
|
||||||
}
|
|
||||||
centeredPanel.layout = BoxLayout(centeredPanel, BoxLayout.Y_AXIS)
|
|
||||||
centeredPanel.add(Box.createVerticalGlue())
|
|
||||||
centeredPanel.add(noExposedPanel)
|
|
||||||
centeredPanel.add(Box.createVerticalGlue())
|
|
||||||
|
|
||||||
reflectiveEditorView.add(Box.createVerticalStrut(10))
|
// Plugin toggle switch (iOS style)
|
||||||
reflectiveEditorView.add(centeredPanel)
|
val toggleSwitch = createToggleSwitch(plugin, pluginInfo)
|
||||||
|
|
||||||
|
// Edit button
|
||||||
|
val editButton = JButton("Edit")
|
||||||
|
editButton.background = TITLE_BAR_COLOR
|
||||||
|
editButton.foreground = secondaryColor
|
||||||
|
editButton.font = Font("RuneScape Small", Font.PLAIN, 14)
|
||||||
|
editButton.addActionListener {
|
||||||
|
showPluginDetails(pluginInfo, plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Layout
|
||||||
|
val infoPanel = JPanel(BorderLayout())
|
||||||
|
infoPanel.background = WIDGET_COLOR
|
||||||
|
infoPanel.add(nameLabel, BorderLayout.WEST)
|
||||||
|
|
||||||
reflectiveEditorView.revalidate()
|
val controlsPanel = JPanel(FlowLayout(FlowLayout.RIGHT, 5, 0))
|
||||||
if(focusedView == VIEW_NAME)
|
controlsPanel.background = WIDGET_COLOR
|
||||||
reflectiveEditorView.repaint()
|
controlsPanel.add(toggleSwitch)
|
||||||
|
controlsPanel.add(editButton)
|
||||||
|
|
||||||
|
panel.add(infoPanel, BorderLayout.CENTER)
|
||||||
|
panel.add(controlsPanel, BorderLayout.EAST)
|
||||||
|
|
||||||
|
return panel
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addPluginToEditor(reflectiveEditorView: JPanel, pluginInfo : PluginInfo, plugin: Plugin) {
|
private fun createToggleSwitch(plugin: Plugin, pluginInfo: PluginInfo): JPanel {
|
||||||
reflectiveEditorView.layout = BoxLayout(reflectiveEditorView, BoxLayout.Y_AXIS)
|
val switchPanel = JPanel(null) // null layout for precise positioning
|
||||||
|
switchPanel.background = WIDGET_COLOR
|
||||||
|
switchPanel.preferredSize = Dimension(50, 25)
|
||||||
|
switchPanel.maximumSize = Dimension(50, 25)
|
||||||
|
switchPanel.minimumSize = Dimension(50, 25)
|
||||||
|
|
||||||
|
// Track (background)
|
||||||
|
val track = JPanel()
|
||||||
|
track.background = if (isPluginEnabled(pluginInfo)) Color(0, 122, 255) else Color(142, 142, 147)
|
||||||
|
track.setBounds(0, 0, 50, 25)
|
||||||
|
track.border = RoundedBorder(12)
|
||||||
|
|
||||||
|
// Thumb (slider)
|
||||||
|
val thumb = JPanel()
|
||||||
|
thumb.background = Color.WHITE
|
||||||
|
thumb.setBounds(if (isPluginEnabled(pluginInfo)) 27 else 3, 3, 20, 20)
|
||||||
|
thumb.border = RoundedBorder(10)
|
||||||
|
|
||||||
|
switchPanel.add(track)
|
||||||
|
switchPanel.add(thumb)
|
||||||
|
|
||||||
|
// Add click handler to toggle
|
||||||
|
switchPanel.addMouseListener(object : MouseAdapter() {
|
||||||
|
override fun mouseClicked(e: MouseEvent) {
|
||||||
|
togglePlugin(pluginInfo, plugin, track, thumb)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return switchPanel
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isPluginEnabled(pluginInfo: PluginInfo): Boolean {
|
||||||
|
// For now, we'll assume all loaded plugins are enabled
|
||||||
|
// In a more complete implementation, you might track enabled/disabled state
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun togglePlugin(pluginInfo: PluginInfo, plugin: Plugin, track: JPanel, thumb: JPanel) {
|
||||||
|
// Simple toggle animation
|
||||||
|
val isEnabled = track.background == Color(0, 122, 255)
|
||||||
|
|
||||||
|
if (isEnabled) {
|
||||||
|
// Toggle off
|
||||||
|
track.background = Color(142, 142, 147)
|
||||||
|
thumb.setLocation(3, 3)
|
||||||
|
} else {
|
||||||
|
// Toggle on
|
||||||
|
track.background = Color(0, 122, 255)
|
||||||
|
thumb.setLocation(27, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
track.repaint()
|
||||||
|
thumb.repaint()
|
||||||
|
|
||||||
|
// In a full implementation, you would disable/enable the plugin here
|
||||||
|
showToast(mainPanel, if (isEnabled) "Plugin disabled" else "Plugin enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showPluginDetails(pluginInfo: PluginInfo, plugin: Plugin) {
|
||||||
|
currentPluginInfo = pluginInfo
|
||||||
|
currentPlugin = plugin
|
||||||
|
|
||||||
|
// Remove the existing detail view if it exists
|
||||||
|
val existingDetailView = mainPanel.components.find { it.name == PLUGIN_DETAIL_VIEW }
|
||||||
|
if (existingDetailView != null) {
|
||||||
|
mainPanel.remove(existingDetailView)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new detail view
|
||||||
|
val detailView = JPanel(BorderLayout())
|
||||||
|
detailView.name = PLUGIN_DETAIL_VIEW
|
||||||
|
detailView.background = VIEW_BACKGROUND_COLOR
|
||||||
|
|
||||||
|
// Header with back button
|
||||||
|
val headerPanel = JPanel(BorderLayout())
|
||||||
|
headerPanel.background = TITLE_BAR_COLOR
|
||||||
|
headerPanel.preferredSize = Dimension(Int.MAX_VALUE, 40)
|
||||||
|
headerPanel.border = BorderFactory.createEmptyBorder(5, 10, 5, 10)
|
||||||
|
|
||||||
|
val backButton = JButton("◀ Back")
|
||||||
|
backButton.background = TITLE_BAR_COLOR
|
||||||
|
backButton.foreground = secondaryColor
|
||||||
|
backButton.font = Font("RuneScape Small", Font.PLAIN, 14)
|
||||||
|
backButton.addActionListener {
|
||||||
|
// Reset scroll position to top when returning to the list view
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
// Find the ScrollablePanel in the plugin list view and reset its scroll position
|
||||||
|
val listView = mainPanel.components.find { it.name == PLUGIN_LIST_VIEW }
|
||||||
|
if (listView != null && listView is Container) {
|
||||||
|
findAndResetScrollablePanel(listView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cardLayout.show(mainPanel, PLUGIN_LIST_VIEW)
|
||||||
|
}
|
||||||
|
|
||||||
|
val packageName = plugin.javaClass.`package`.name
|
||||||
|
val titleLabel = JLabel("$packageName Settings")
|
||||||
|
titleLabel.foreground = secondaryColor
|
||||||
|
titleLabel.font = Font("RuneScape Small", Font.BOLD, 16)
|
||||||
|
titleLabel.horizontalAlignment = SwingConstants.CENTER
|
||||||
|
|
||||||
|
headerPanel.add(backButton, BorderLayout.WEST)
|
||||||
|
headerPanel.add(titleLabel, BorderLayout.CENTER)
|
||||||
|
|
||||||
|
// Content panel for settings
|
||||||
|
val contentPanel = JPanel()
|
||||||
|
contentPanel.layout = BoxLayout(contentPanel, BoxLayout.Y_AXIS)
|
||||||
|
contentPanel.background = VIEW_BACKGROUND_COLOR
|
||||||
|
contentPanel.border = BorderFactory.createEmptyBorder(10, 10, 10, 10)
|
||||||
|
|
||||||
|
// Add plugin info
|
||||||
|
val infoPanel = JPanel(BorderLayout())
|
||||||
|
infoPanel.background = WIDGET_COLOR
|
||||||
|
infoPanel.border = BorderFactory.createEmptyBorder(10, 10, 10, 10)
|
||||||
|
infoPanel.maximumSize = Dimension(Int.MAX_VALUE, 80)
|
||||||
|
|
||||||
|
val infoText = """
|
||||||
|
Version: ${pluginInfo.version}
|
||||||
|
Author: ${pluginInfo.author}
|
||||||
|
Description: ${pluginInfo.description}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val infoLabel = JLabel("<html>$infoText</html>")
|
||||||
|
infoLabel.foreground = secondaryColor
|
||||||
|
infoLabel.font = Font("RuneScape Small", Font.PLAIN, 14)
|
||||||
|
infoPanel.add(infoLabel, BorderLayout.CENTER)
|
||||||
|
|
||||||
|
contentPanel.add(infoPanel)
|
||||||
|
contentPanel.add(Box.createVerticalStrut(10))
|
||||||
|
|
||||||
|
// Add exposed fields
|
||||||
|
addPluginSettings(contentPanel, plugin)
|
||||||
|
|
||||||
|
// Wrap the content panel in a ScrollablePanel for custom scrolling
|
||||||
|
val scrollablePanel = ScrollablePanel(contentPanel)
|
||||||
|
|
||||||
|
// Reset scroll position to top when entering the edit page
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
resetScrollablePanel(scrollablePanel)
|
||||||
|
}
|
||||||
|
|
||||||
|
detailView.add(headerPanel, BorderLayout.NORTH)
|
||||||
|
detailView.add(scrollablePanel, BorderLayout.CENTER)
|
||||||
|
|
||||||
|
// Add the new detail view to the main panel
|
||||||
|
mainPanel.add(detailView, PLUGIN_DETAIL_VIEW)
|
||||||
|
|
||||||
|
// Revalidate and repaint the main panel
|
||||||
|
mainPanel.revalidate()
|
||||||
|
mainPanel.repaint()
|
||||||
|
|
||||||
|
// Show the detail view
|
||||||
|
cardLayout.show(mainPanel, PLUGIN_DETAIL_VIEW)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addPluginSettings(contentPanel: JPanel, plugin: Plugin) {
|
||||||
val fieldNotifier = Helpers.FieldNotifier(plugin)
|
val fieldNotifier = Helpers.FieldNotifier(plugin)
|
||||||
val exposedFields = plugin.javaClass.declaredFields.filter { field ->
|
val exposedFields = plugin.javaClass.declaredFields.filter { field ->
|
||||||
field.annotations.any { annotation ->
|
field.annotations.any { annotation ->
|
||||||
|
|
@ -119,22 +311,6 @@ object ReflectiveEditorView {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exposedFields.isNotEmpty()) {
|
if (exposedFields.isNotEmpty()) {
|
||||||
|
|
||||||
val packageName = plugin.javaClass.`package`.name
|
|
||||||
val version = pluginInfo.version
|
|
||||||
val labelPanel = JPanel(BorderLayout())
|
|
||||||
labelPanel.maximumSize = Dimension(Int.MAX_VALUE, 30)
|
|
||||||
labelPanel.background = VIEW_BACKGROUND_COLOR
|
|
||||||
labelPanel.border = BorderFactory.createEmptyBorder(5, 0, 0, 0)
|
|
||||||
|
|
||||||
val label = JLabel("$packageName v$version", SwingConstants.CENTER)
|
|
||||||
label.foreground = primaryColor
|
|
||||||
label.font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
|
|
||||||
labelPanel.add(label, BorderLayout.CENTER)
|
|
||||||
label.isOpaque = true
|
|
||||||
label.background = TITLE_BAR_COLOR
|
|
||||||
reflectiveEditorView.add(labelPanel)
|
|
||||||
|
|
||||||
for (field in exposedFields) {
|
for (field in exposedFields) {
|
||||||
field.isAccessible = true
|
field.isAccessible = true
|
||||||
|
|
||||||
|
|
@ -157,7 +333,7 @@ object ReflectiveEditorView {
|
||||||
fieldPanel.background = WIDGET_COLOR
|
fieldPanel.background = WIDGET_COLOR
|
||||||
fieldPanel.foreground = secondaryColor
|
fieldPanel.foreground = secondaryColor
|
||||||
fieldPanel.border = BorderFactory.createEmptyBorder(5, 0, 5, 0)
|
fieldPanel.border = BorderFactory.createEmptyBorder(5, 0, 5, 0)
|
||||||
fieldPanel.maximumSize = Dimension(Int.MAX_VALUE, 40)
|
fieldPanel.maximumSize = Dimension(Int.MAX_VALUE, 50)
|
||||||
|
|
||||||
val gbc = GridBagConstraints()
|
val gbc = GridBagConstraints()
|
||||||
gbc.insets = Insets(0, 5, 0, 5)
|
gbc.insets = Insets(0, 5, 0, 5)
|
||||||
|
|
@ -224,12 +400,12 @@ object ReflectiveEditorView {
|
||||||
}
|
}
|
||||||
fieldNotifier.setFieldValue(field, newValue)
|
fieldNotifier.setFieldValue(field, newValue)
|
||||||
showToast(
|
showToast(
|
||||||
reflectiveEditorView,
|
mainPanel,
|
||||||
"${field.name} updated successfully!"
|
"${field.name} updated successfully!"
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
showToast(
|
showToast(
|
||||||
reflectiveEditorView,
|
mainPanel,
|
||||||
"Failed to update ${field.name}: ${e.message}",
|
"Failed to update ${field.name}: ${e.message}",
|
||||||
JOptionPane.ERROR_MESSAGE
|
JOptionPane.ERROR_MESSAGE
|
||||||
)
|
)
|
||||||
|
|
@ -237,7 +413,7 @@ object ReflectiveEditorView {
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldPanel.add(applyButton, gbc)
|
fieldPanel.add(applyButton, gbc)
|
||||||
reflectiveEditorView.add(fieldPanel)
|
contentPanel.add(fieldPanel)
|
||||||
|
|
||||||
// Track field changes in real-time and update UI
|
// Track field changes in real-time and update UI
|
||||||
var previousValue = field.get(plugin)?.toString()
|
var previousValue = field.get(plugin)?.toString()
|
||||||
|
|
@ -262,12 +438,16 @@ object ReflectiveEditorView {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exposedFields.isNotEmpty()) {
|
if (exposedFields.isNotEmpty()) {
|
||||||
reflectiveEditorView.add(Box.createVerticalStrut(5))
|
contentPanel.add(Box.createVerticalStrut(5))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
loadedPlugins.add(plugin.javaClass.`package`.name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addPlugins(reflectiveEditorView: JPanel) {
|
||||||
|
// This function is now deprecated with the new view system
|
||||||
|
// but kept for compatibility
|
||||||
|
// In the new system, we don't need to do anything here
|
||||||
|
// as the views are managed by our internal card layout
|
||||||
}
|
}
|
||||||
|
|
||||||
var customToolTipWindow: JWindow? = null
|
var customToolTipWindow: JWindow? = null
|
||||||
|
|
@ -321,4 +501,49 @@ object ReflectiveEditorView {
|
||||||
customToolTipWindow!!.setLocation(locationOnScreen.x, locationOnScreen.y + 15)
|
customToolTipWindow!!.setLocation(locationOnScreen.x, locationOnScreen.y + 15)
|
||||||
customToolTipWindow!!.isVisible = true
|
customToolTipWindow!!.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper method to reset a ScrollablePanel to the top
|
||||||
|
private fun resetScrollablePanel(scrollablePanel: ScrollablePanel) {
|
||||||
|
// Access the content panel and reset its position
|
||||||
|
// Since we can't directly access the private fields, we'll use reflection
|
||||||
|
try {
|
||||||
|
val contentField = ScrollablePanel::class.java.getDeclaredField("content")
|
||||||
|
contentField.isAccessible = true
|
||||||
|
val contentPanel = contentField.get(scrollablePanel) as JPanel
|
||||||
|
|
||||||
|
// Reset the location to the top
|
||||||
|
contentPanel.setLocation(0, 0)
|
||||||
|
|
||||||
|
// Force a repaint
|
||||||
|
scrollablePanel.revalidate()
|
||||||
|
scrollablePanel.repaint()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// If reflection fails, at least try to repaint
|
||||||
|
scrollablePanel.revalidate()
|
||||||
|
scrollablePanel.repaint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to find and reset ScrollablePanel components within a container
|
||||||
|
private fun findAndResetScrollablePanel(container: Component) {
|
||||||
|
if (container is ScrollablePanel) {
|
||||||
|
resetScrollablePanel(container)
|
||||||
|
} else if (container is Container) {
|
||||||
|
for (child in container.components) {
|
||||||
|
findAndResetScrollablePanel(child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom border for rounded components
|
||||||
|
class RoundedBorder(radius: Int) : AbstractBorder() {
|
||||||
|
private val radius = radius
|
||||||
|
|
||||||
|
override fun paintBorder(c: Component, g: Graphics, x: Int, y: Int, width: Int, height: Int) {
|
||||||
|
val g2 = g as Graphics2D
|
||||||
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
|
||||||
|
g2.setColor(c.background)
|
||||||
|
g2.fillRoundRect(x, y, width - 1, height - 1, radius, radius)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue