layout fixes

This commit is contained in:
downthecrop 2025-09-15 22:09:07 -07:00
parent ef87ae24c1
commit ea724777ae

View file

@ -6,7 +6,6 @@ import KondoKit.Helpers.formatHtmlLabelText
import KondoKit.Helpers.formatNumber
import KondoKit.Helpers.getProgressBarColor
import KondoKit.Helpers.getSpriteId
import KondoKit.ImageCanvas
import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite
import KondoKit.XPTable
import KondoKit.components.PopupMenuComponent
@ -26,9 +25,11 @@ import KondoKit.plugin.Companion.secondaryColor
import KondoKit.plugin.StateManager.focusedView
import plugin.api.API
import java.awt.*
import java.awt.image.BufferedImage
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import javax.swing.*
import javax.swing.SwingConstants
object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
private val COMBAT_SKILLS = intArrayOf(0,1,2,3,4)
@ -39,7 +40,7 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
const val VIEW_NAME = "XP_TRACKER_VIEW"
override val name: String = VIEW_NAME
override val iconSpriteId: Int = LVL_ICON
private val skillIconCache: MutableMap<Int, java.awt.image.BufferedImage> = HashMap()
private val skillIconCache: MutableMap<Int, BufferedImage> = HashMap()
val npcHitpointsMap: Map<Int, Int> = try {
@ -63,6 +64,84 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
emptyMap()
}
private val widgetFont = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
private fun createPopupListener(popupMenu: JPopupMenu) = object : MouseAdapter() {
override fun mousePressed(e: MouseEvent) {
if (e.isPopupTrigger) popupMenu.show(e.component, e.x, e.y)
}
override fun mouseReleased(e: MouseEvent) {
if (e.isPopupTrigger) popupMenu.show(e.component, e.x, e.y)
}
}
private fun attachPopup(component: Container, popupMenu: JPopupMenu) {
val listener = createPopupListener(popupMenu)
addMouseListenerToAll(component, listener)
component.addMouseListener(listener)
}
private fun BufferedImage.ensureOpaque(): BufferedImage {
for (y in 0 until height) {
for (x in 0 until width) {
val color = getRGB(x, y)
if (color != 0) {
setRGB(x, y, color or (0xFF shl 24))
}
}
}
return this
}
private fun createIconContainer(image: BufferedImage): JPanel {
val processed = image.ensureOpaque()
val icon = ImageIcon(processed)
val label = JLabel(icon).apply {
horizontalAlignment = SwingConstants.CENTER
verticalAlignment = SwingConstants.CENTER
isOpaque = false
}
return JPanel(BorderLayout()).apply {
background = WIDGET_COLOR
val wrapperSize = Dimension(IMAGE_SIZE)
preferredSize = wrapperSize
minimumSize = wrapperSize
maximumSize = wrapperSize
add(label, BorderLayout.CENTER)
}
}
private fun createMetricLabel(title: String, initialValue: String = "0", topPadding: Int = 0): JLabel {
return JLabel(formatHtmlLabelText("$title ", primaryColor, initialValue, secondaryColor)).apply {
horizontalAlignment = JLabel.LEFT
font = widgetFont
if (topPadding > 0) {
border = BorderFactory.createEmptyBorder(topPadding, 0, 0, 0)
} else {
border = BorderFactory.createEmptyBorder(0, 0, 0, 0)
}
}
}
private fun createMenuItem(text: String): JMenuItem = JMenuItem(text).apply {
font = widgetFont
background = POPUP_BACKGROUND
foreground = POPUP_FOREGROUND
}
private fun getSkillIcon(skillId: Int): BufferedImage {
return skillIconCache[skillId] ?: getBufferedImageFromSprite(API.GetSprite(getSpriteId(skillId))).also {
skillIconCache[skillId] = it
}
}
private fun createTotalWidgetContainer(popupMenu: JPopupMenu): Container {
totalXPWidget = createTotalXPWidget()
return wrappedWidget(totalXPWidget!!.container).also { attachPopup(it, popupMenu) }
}
override val panel: JPanel
get() = xpTrackerView ?: JPanel()
@ -116,18 +195,8 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
xpWidgets[skillId] = xpWidget
val wrapped = wrappedWidget(xpWidget.container)
// Attach per-widget remove menu
val popupMenu = removeXPWidgetMenu(wrapped, skillId)
val rightClickListener = object : MouseAdapter() {
override fun mousePressed(e: MouseEvent) {
if (e.isPopupTrigger) popupMenu.show(e.component, e.x, e.y)
}
override fun mouseReleased(e: MouseEvent) {
if (e.isPopupTrigger) popupMenu.show(e.component, e.x, e.y)
}
}
addMouseListenerToAll(wrapped, rightClickListener)
wrapped.addMouseListener(rightClickListener)
attachPopup(wrapped, popupMenu)
xpTrackerView?.add(wrapped)
xpTrackerView?.add(Box.createVerticalStrut(5))
@ -206,146 +275,63 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
}
fun resetXPTracker(xpTrackerView : JPanel){
// Redo logic here
fun resetXPTracker(xpTrackerView: JPanel) {
xpTrackerView.removeAll()
val popupMenu = createResetMenu()
// Create a custom MouseListener
val rightClickListener = object : MouseAdapter() {
override fun mousePressed(e: MouseEvent) {
if (e.isPopupTrigger) {
popupMenu.show(e.component, e.x, e.y)
}
}
override fun mouseReleased(e: MouseEvent) {
if (e.isPopupTrigger) {
popupMenu.show(e.component, e.x, e.y)
}
}
}
// Create the XP widget
totalXPWidget = createTotalXPWidget()
val wrapped = wrappedWidget(totalXPWidget!!.container)
addMouseListenerToAll(wrapped,rightClickListener)
wrapped.addMouseListener(rightClickListener)
xpTrackerView.add(Box.createVerticalStrut(5))
xpTrackerView.add(wrapped)
xpTrackerView.add(createTotalWidgetContainer(popupMenu))
xpTrackerView.add(Box.createVerticalStrut(5))
initialXP.clear()
xpWidgets.clear()
xpTrackerView.revalidate()
if (focusedView == VIEW_NAME)
if (focusedView == VIEW_NAME) {
xpTrackerView.repaint()
}
}
fun createTotalXPWidget(): XPWidget {
val widgetPanel = WidgetPanel(TOTAL_XP_WIDGET_SIZE.width, TOTAL_XP_WIDGET_SIZE.height).apply {
border = BorderFactory.createEmptyBorder(5, 5, 5, 5)
fun createTotalXPWidget(): XPWidget {
val widgetPanel = WidgetPanel(TOTAL_XP_WIDGET_SIZE.width, TOTAL_XP_WIDGET_SIZE.height, addDefaultPadding = false)
val iconContainer = createIconContainer(getBufferedImageFromSprite(API.GetSprite(LVL_ICON)))
val textPanel = JPanel(GridLayout(2, 1, 5, 0)).apply {
background = WIDGET_COLOR
}
val bufferedImageSprite = getBufferedImageFromSprite(API.GetSprite(LVL_ICON))
val imageContainer = Panel(FlowLayout()).apply {
preferredSize = Dimension(bufferedImageSprite.width, bufferedImageSprite.height)
maximumSize = preferredSize
minimumSize = preferredSize
size = preferredSize
}
bufferedImageSprite.let { image ->
val imageCanvas = ImageCanvas(image).apply {
preferredSize = Dimension(bufferedImageSprite.width, bufferedImageSprite.height)
maximumSize = preferredSize
minimumSize = preferredSize
size = preferredSize
}
imageContainer.add(imageCanvas)
imageContainer.size = Dimension(bufferedImageSprite.width, bufferedImageSprite.height)
imageContainer.revalidate()
if(focusedView == VIEW_NAME)
imageContainer.repaint()
}
val textPanel = Panel().apply {
layout = GridLayout(2, 1, 5, 0)
}
val font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
val xpGainedLabel = JLabel(
formatHtmlLabelText("Gained: ", primaryColor, "0", secondaryColor)
).apply {
this.horizontalAlignment = JLabel.LEFT
this.font = font
}
val xpPerHourLabel = JLabel(
formatHtmlLabelText("XP /hr: ", primaryColor, "0", secondaryColor)
).apply {
this.horizontalAlignment = JLabel.LEFT
this.font = font
}
val xpGainedLabel = createMetricLabel("Gained:")
val xpPerHourLabel = createMetricLabel("XP /hr:")
textPanel.add(xpGainedLabel)
textPanel.add(xpPerHourLabel)
widgetPanel.add(imageContainer, BorderLayout.WEST)
widgetPanel.add(iconContainer, BorderLayout.WEST)
widgetPanel.add(textPanel, BorderLayout.CENTER)
return XPWidget(
skillId = -1,
container = widgetPanel,
xpGainedLabel = xpGainedLabel,
xpLeftLabel = JLabel(formatHtmlLabelText("XP Left: ", primaryColor, "0", secondaryColor)).apply {
this.horizontalAlignment = JLabel.LEFT
this.font = font
},
xpLeftLabel = createMetricLabel("XP Left:"),
xpPerHourLabel = xpPerHourLabel,
progressBar = ProgressBar(0.0, Color.BLACK), // Unused
totalXpGained = 0,
startTime = System.currentTimeMillis(),
previousXp = 0,
actionsRemainingLabel = JLabel(),
actionsRemainingLabel = JLabel().apply { font = widgetFont },
)
}
fun createXPTrackerView(){
fun createXPTrackerView() {
val widgetViewPanel = BaseView(VIEW_NAME, addDefaultSpacing = false).apply {
add(Box.createVerticalStrut(5))
}
val popupMenu = createResetMenu()
// Create a custom MouseListener
val rightClickListener = object : MouseAdapter() {
override fun mousePressed(e: MouseEvent) {
if (e.isPopupTrigger) {
popupMenu.show(e.component, e.x, e.y)
}
}
override fun mouseReleased(e: MouseEvent) {
if (e.isPopupTrigger) {
popupMenu.show(e.component, e.x, e.y)
}
}
}
// Create the XP widget
totalXPWidget = createTotalXPWidget()
val wrapped = wrappedWidget(totalXPWidget!!.container)
addMouseListenerToAll(wrapped,rightClickListener)
wrapped.addMouseListener(rightClickListener)
widgetViewPanel.add(wrapped)
widgetViewPanel.add(createTotalWidgetContainer(popupMenu))
widgetViewPanel.add(Box.createVerticalStrut(5))
xpTrackerView = widgetViewPanel
@ -353,10 +339,7 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
// Preload skill icons to avoid first-drop lag
try {
for (i in 0 until 24) {
if (!skillIconCache.containsKey(i)) {
val img = getBufferedImageFromSprite(API.GetSprite(getSpriteId(i)))
skillIconCache[i] = img
}
getSkillIcon(i)
}
} catch (_: Exception) {
// Ignore preload errors; fallback at use time
@ -365,39 +348,22 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
fun createResetMenu(): JPopupMenu {
// Create a popup menu
val popupMenu = PopupMenuComponent()
// Create menu items with custom font and colors
val menuItem1 = JMenuItem("Reset Tracker").apply {
font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
background = POPUP_BACKGROUND
foreground = POPUP_FOREGROUND
}
val resetItem = createMenuItem("Reset Tracker")
popupMenu.add(resetItem)
// Add menu items to the popup menu
popupMenu.add(menuItem1)
// Add action listeners to each menu item (optional)
menuItem1.addActionListener { plugin.registerDrawAction { resetXPTracker(xpTrackerView!!) } }
resetItem.addActionListener { plugin.registerDrawAction { resetXPTracker(xpTrackerView!!) } }
return popupMenu
}
fun removeXPWidgetMenu(toRemove: Container, skillId: Int): JPopupMenu {
val popupMenu = PopupMenuComponent()
val resetItem = JMenuItem("Reset").apply {
font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
background = POPUP_BACKGROUND
foreground = POPUP_FOREGROUND
}
val resetItem = createMenuItem("Reset")
popupMenu.add(resetItem)
val removeItem = JMenuItem("Remove").apply {
font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
background = POPUP_BACKGROUND
foreground = POPUP_FOREGROUND
}
val removeItem = createMenuItem("Remove")
popupMenu.add(removeItem)
resetItem.addActionListener {
@ -438,95 +404,39 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
fun createXPWidget(skillId: Int, previousXp: Int): XPWidget {
val widgetPanel = WidgetPanel(WIDGET_SIZE.width, WIDGET_SIZE.height).apply {
border = BorderFactory.createEmptyBorder(5, 5, 5, 5)
}
val widgetPanel = WidgetPanel(WIDGET_SIZE.width, WIDGET_SIZE.height, addDefaultPadding = false)
val bufferedImageSprite = skillIconCache[skillId]
?: run {
val img = getBufferedImageFromSprite(API.GetSprite(getSpriteId(skillId)))
skillIconCache[skillId] = img
img
}
val imageContainer = Panel(FlowLayout()).apply {
background = WIDGET_COLOR
preferredSize = IMAGE_SIZE
maximumSize = IMAGE_SIZE
minimumSize = IMAGE_SIZE
size = IMAGE_SIZE
}
val iconContainer = createIconContainer(getSkillIcon(skillId))
bufferedImageSprite.let { image ->
val imageCanvas = ImageCanvas(image).apply {
background = WIDGET_COLOR
preferredSize = Dimension(image.width, image.height)
maximumSize = Dimension(image.width, image.height)
minimumSize = Dimension(image.width, image.height)
size = Dimension(image.width, image.height) // Explicitly set the size
}
imageContainer.add(imageCanvas)
imageContainer.size = Dimension(image.width, image.height) // Ensure container respects the image size
imageContainer.revalidate()
if(focusedView == VIEW_NAME)
imageContainer.repaint()
}
val textPanel = Panel().apply {
layout = GridLayout(2, 2, 5, 0)
val textPanel = JPanel(GridLayout(2, 2, 5, 0)).apply {
background = WIDGET_COLOR
}
val font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
val xpGainedLabel = createMetricLabel("XP Gained:")
val xpLeftLabel = createMetricLabel("XP Left:", "0K")
val xpPerHourLabel = createMetricLabel("XP /hr:")
val actionsTitle = if (COMBAT_SKILLS.contains(skillId)) "Kills:" else "Actions:"
val actionsLabel = createMetricLabel(actionsTitle)
val xpGainedLabel = JLabel(
formatHtmlLabelText("XP Gained: ", primaryColor, "0", secondaryColor)
).apply {
this.horizontalAlignment = JLabel.LEFT
this.font = font
}
val xpLeftLabel = JLabel(
formatHtmlLabelText("XP Left: ", primaryColor, "0K", secondaryColor)
).apply {
this.horizontalAlignment = JLabel.LEFT
this.font = font
}
val xpPerHourLabel = JLabel(
formatHtmlLabelText("XP /hr: ", primaryColor, "0", secondaryColor)
).apply {
this.horizontalAlignment = JLabel.LEFT
this.font = font
}
val killsLabel = JLabel(
formatHtmlLabelText("Kills: ", primaryColor, "0", secondaryColor)
).apply {
this.horizontalAlignment = JLabel.LEFT
this.font = font
}
val levelPanel = Panel().apply {
layout = BorderLayout(5, 0)
background = WIDGET_COLOR
}
val progressBarPanel = ProgressBar(0.0, getProgressBarColor(skillId)).apply {
val progressBar = ProgressBar(0.0, getProgressBarColor(skillId)).apply {
preferredSize = Dimension(160, 22)
minimumSize = preferredSize
maximumSize = preferredSize
}
levelPanel.add(progressBarPanel, BorderLayout.CENTER)
val progressPanel = JPanel(BorderLayout()).apply {
background = WIDGET_COLOR
add(progressBar, BorderLayout.CENTER)
}
textPanel.add(xpGainedLabel)
textPanel.add(xpLeftLabel)
textPanel.add(xpPerHourLabel)
textPanel.add(killsLabel)
textPanel.add(actionsLabel)
widgetPanel.add(imageContainer, BorderLayout.WEST)
widgetPanel.add(iconContainer, BorderLayout.WEST)
widgetPanel.add(textPanel, BorderLayout.CENTER)
widgetPanel.add(levelPanel, BorderLayout.SOUTH)
widgetPanel.add(progressPanel, BorderLayout.SOUTH)
widgetPanel.revalidate()
if(focusedView == VIEW_NAME)
@ -538,9 +448,9 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
xpGainedLabel = xpGainedLabel,
xpLeftLabel = xpLeftLabel,
xpPerHourLabel = xpPerHourLabel,
progressBar = progressBarPanel,
progressBar = progressBar,
totalXpGained = 0,
actionsRemainingLabel = killsLabel,
actionsRemainingLabel = actionsLabel,
startTime = System.currentTimeMillis(),
previousXp = previousXp
)
@ -584,4 +494,4 @@ data class XPWidget(
var totalXpGained: Int = 0,
var startTime: Long = System.currentTimeMillis(),
var previousXp: Int = 0
)
)