centralize all colors, begin themeing support

This commit is contained in:
downthecrop 2024-10-22 18:39:30 -07:00
parent 72bf9a8297
commit 2a059d1c02
9 changed files with 405 additions and 186 deletions

View file

@ -190,6 +190,10 @@ object Helpers {
} }
} }
fun showAlert(message: String, title: String, type: Int){
JOptionPane.showMessageDialog(null, message, title, type)
}
fun formatHtmlLabelText(text1: String, color1: Color, text2: String, color2: Color): String { fun formatHtmlLabelText(text1: String, color1: Color, text2: String, color2: Color): String {
return "<html><div style='white-space:nowrap;'>" + return "<html><div style='white-space:nowrap;'>" +
"<span style='color:rgb(${color1.red},${color1.green},${color1.blue});'>$text1</span>" + "<span style='color:rgb(${color1.red},${color1.green},${color1.blue});'>$text1</span>" +

View file

@ -7,10 +7,15 @@ import KondoKit.Helpers.formatHtmlLabelText
import KondoKit.Helpers.getSpriteId import KondoKit.Helpers.getSpriteId
import KondoKit.Helpers.showToast import KondoKit.Helpers.showToast
import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite
import KondoKit.plugin.Companion.POPUP_BACKGROUND
import KondoKit.plugin.Companion.POPUP_FOREGROUND
import KondoKit.plugin.Companion.TITLE_BAR_COLOR
import KondoKit.plugin.Companion.TOOLTIP_BACKGROUND
import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR
import KondoKit.plugin.Companion.WIDGET_COLOR import KondoKit.plugin.Companion.WIDGET_COLOR
import KondoKit.plugin.Companion.primaryColor import KondoKit.plugin.Companion.primaryColor
import KondoKit.plugin.Companion.secondaryColor import KondoKit.plugin.Companion.secondaryColor
import KondoKit.plugin.StateManager.focusedView
import com.google.gson.Gson import com.google.gson.Gson
import plugin.api.API import plugin.api.API
import rt4.Sprites import rt4.Sprites
@ -27,6 +32,7 @@ import java.net.SocketTimeoutException
import java.net.URL import java.net.URL
import javax.swing.* import javax.swing.*
import javax.swing.border.MatteBorder import javax.swing.border.MatteBorder
import kotlin.math.floor
object Constants { object Constants {
// Sprite IDs // Sprite IDs
@ -38,7 +44,6 @@ object Constants {
// Dimensions // Dimensions
val SEARCH_FIELD_DIMENSION = Dimension(230, 30) val SEARCH_FIELD_DIMENSION = Dimension(230, 30)
val ICON_DIMENSION_SMALL = Dimension(12, 12) val ICON_DIMENSION_SMALL = Dimension(12, 12)
val ICON_DIMENSION_MEDIUM = Dimension(18, 20)
val ICON_DIMENSION_LARGE = Dimension(30, 30) val ICON_DIMENSION_LARGE = Dimension(30, 30)
val HISCORE_PANEL_DIMENSION = Dimension(230, 500) val HISCORE_PANEL_DIMENSION = Dimension(230, 500)
val FILTER_PANEL_DIMENSION = Dimension(230, 30) val FILTER_PANEL_DIMENSION = Dimension(230, 30)
@ -50,11 +55,9 @@ object Constants {
val NUMBER_LABEL_DIMENSION = Dimension(20, 20) val NUMBER_LABEL_DIMENSION = Dimension(20, 20)
// Colors // Colors
val COLOR_BACKGROUND_DARK = Color(27, 27, 27) val COLOR_BACKGROUND_DARK = WIDGET_COLOR
val COLOR_BACKGROUND_MEDIUM = VIEW_BACKGROUND_COLOR val COLOR_BACKGROUND_MEDIUM = VIEW_BACKGROUND_COLOR
val COLOR_FOREGROUND_LIGHT = Color(200, 200, 200) val COLOR_FOREGROUND_LIGHT = POPUP_FOREGROUND
val COLOR_RED = Color.RED
val COLOR_SKILL_PANEL = Color(60, 60, 60)
// Fonts // Fonts
val FONT_ARIAL_PLAIN_14 = Font("Arial", Font.PLAIN, 14) val FONT_ARIAL_PLAIN_14 = Font("Arial", Font.PLAIN, 14)
@ -67,6 +70,7 @@ var text: String = ""
object HiscoresView { object HiscoresView {
const val VIEW_NAME = "HISCORE_SEARCH_VIEW"
var hiScoreView: JPanel? = null var hiScoreView: JPanel? = null
class CustomSearchField(private val hiscoresPanel: JPanel) : Canvas() { class CustomSearchField(private val hiscoresPanel: JPanel) : Canvas() {
@ -137,9 +141,9 @@ object HiscoresView {
} }
}) })
Timer(1000) { Timer(500) {
cursorVisible = !cursorVisible cursorVisible = !cursorVisible
if(plugin.StateManager.focusedView == "HISCORE_SEARCH_VIEW") if(focusedView == VIEW_NAME)
repaint() repaint()
}.start() }.start()
} }
@ -165,7 +169,7 @@ object HiscoresView {
} }
if (text.isNotEmpty()) { if (text.isNotEmpty()) {
g.color = Constants.COLOR_RED g.color = Color.RED
g.drawString("x", width - 20, 20) g.drawString("x", width - 20, 20)
} }
} }
@ -305,13 +309,13 @@ object HiscoresView {
summoning: Int, summoning: Int,
isMemberWorld: Boolean isMemberWorld: Boolean
): Double { ): Double {
val base = (defence + hitpoints + Math.floor(prayer.toDouble() / 2)) * 0.25 val base = (defence + hitpoints + floor(prayer.toDouble() / 2)) * 0.25
val melee = (attack + strength) * 0.325 val melee = (attack + strength) * 0.325
val range = Math.floor(ranged * 1.5) * 0.325 val range = floor(ranged * 1.5) * 0.325
val mage = Math.floor(magic * 1.5) * 0.325 val mage = floor(magic * 1.5) * 0.325
val maxCombatType = maxOf(melee, range, mage) val maxCombatType = maxOf(melee, range, mage)
val summoningFactor = if (isMemberWorld) Math.floor(summoning.toDouble() / 8) else 0.0 val summoningFactor = if (isMemberWorld) floor(summoning.toDouble() / 8) else 0.0
return Math.round((base + maxCombatType + summoningFactor) * 1000.0) / 1000.0 return Math.round((base + maxCombatType + summoningFactor) * 1000.0) / 1000.0
} }
@ -338,7 +342,7 @@ object HiscoresView {
fun createHiscoreSearchView() { fun createHiscoreSearchView() {
val hiscorePanel = JPanel().apply { val hiscorePanel = JPanel().apply {
layout = BoxLayout(this, BoxLayout.Y_AXIS) layout = BoxLayout(this, BoxLayout.Y_AXIS)
name = "HISCORE_SEARCH_VIEW" name = VIEW_NAME
background = Constants.COLOR_BACKGROUND_MEDIUM background = Constants.COLOR_BACKGROUND_MEDIUM
preferredSize = Constants.HISCORE_PANEL_DIMENSION preferredSize = Constants.HISCORE_PANEL_DIMENSION
maximumSize = preferredSize maximumSize = preferredSize
@ -369,7 +373,7 @@ object HiscoresView {
val playerNamePanel = JPanel().apply { val playerNamePanel = JPanel().apply {
layout = GridBagLayout() // This will center the JLabel both vertically and horizontally layout = GridBagLayout() // This will center the JLabel both vertically and horizontally
background = WIDGET_COLOR background = TOOLTIP_BACKGROUND.darker()
preferredSize = Constants.FILTER_PANEL_DIMENSION preferredSize = Constants.FILTER_PANEL_DIMENSION
maximumSize = preferredSize maximumSize = preferredSize
minimumSize = preferredSize minimumSize = preferredSize
@ -436,6 +440,7 @@ object HiscoresView {
val bufferedImageSprite = getBufferedImageFromSprite(API.GetSprite(Constants.LVL_BAR_SPRITE)); val bufferedImageSprite = getBufferedImageFromSprite(API.GetSprite(Constants.LVL_BAR_SPRITE));
val totalLevelIcon = ImageCanvas(bufferedImageSprite).apply { val totalLevelIcon = ImageCanvas(bufferedImageSprite).apply {
fillColor = COLOR_BACKGROUND_DARK
preferredSize = Constants.ICON_DIMENSION_LARGE preferredSize = Constants.ICON_DIMENSION_LARGE
size = Constants.ICON_DIMENSION_LARGE size = Constants.ICON_DIMENSION_LARGE
} }
@ -457,6 +462,7 @@ object HiscoresView {
val bufferedImageSprite2 = getBufferedImageFromSprite(API.GetSprite(Constants.COMBAT_LVL_SPRITE)) val bufferedImageSprite2 = getBufferedImageFromSprite(API.GetSprite(Constants.COMBAT_LVL_SPRITE))
val combatLevelIcon = ImageCanvas(bufferedImageSprite2).apply { val combatLevelIcon = ImageCanvas(bufferedImageSprite2).apply {
fillColor = COLOR_BACKGROUND_DARK
preferredSize = Constants.ICON_DIMENSION_LARGE preferredSize = Constants.ICON_DIMENSION_LARGE
size = Constants.ICON_DIMENSION_LARGE size = Constants.ICON_DIMENSION_LARGE
} }

View file

@ -4,11 +4,17 @@ import KondoKit.Helpers.addMouseListenerToAll
import KondoKit.Helpers.formatHtmlLabelText import KondoKit.Helpers.formatHtmlLabelText
import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite
import KondoKit.XPTrackerView.wrappedWidget import KondoKit.XPTrackerView.wrappedWidget
import KondoKit.plugin.Companion.IMAGE_SIZE
import KondoKit.plugin.Companion.POPUP_BACKGROUND
import KondoKit.plugin.Companion.POPUP_FOREGROUND
import KondoKit.plugin.Companion.TITLE_BAR_COLOR
import KondoKit.plugin.Companion.TOOLTIP_BACKGROUND
import KondoKit.plugin.Companion.TOTAL_XP_WIDGET_SIZE import KondoKit.plugin.Companion.TOTAL_XP_WIDGET_SIZE
import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR
import KondoKit.plugin.Companion.WIDGET_COLOR import KondoKit.plugin.Companion.WIDGET_COLOR
import KondoKit.plugin.Companion.primaryColor import KondoKit.plugin.Companion.primaryColor
import KondoKit.plugin.Companion.secondaryColor import KondoKit.plugin.Companion.secondaryColor
import KondoKit.plugin.StateManager.focusedView
import plugin.api.API import plugin.api.API
import rt4.* import rt4.*
import java.awt.* import java.awt.*
@ -30,6 +36,7 @@ object LootTrackerView {
const val BAG_ICON = 900; const val BAG_ICON = 900;
val npcDeathSnapshots = mutableMapOf<Int, GroundSnapshot>() val npcDeathSnapshots = mutableMapOf<Int, GroundSnapshot>()
var gePriceMap = loadGEPrices() var gePriceMap = loadGEPrices()
const val VIEW_NAME = "LOOT_TRACKER_VIEW";
private val lootItemPanels = mutableMapOf<String, MutableMap<Int, Int>>() private val lootItemPanels = mutableMapOf<String, MutableMap<Int, Int>>()
private val npcKillCounts = mutableMapOf<String, Int>() private val npcKillCounts = mutableMapOf<String, Int>()
private var totalTrackerWidget: XPWidget? = null private var totalTrackerWidget: XPWidget? = null
@ -125,8 +132,9 @@ object LootTrackerView {
addMouseListenerToAll(wrapped,rightClickListener) addMouseListenerToAll(wrapped,rightClickListener)
wrapped.addMouseListener(rightClickListener) wrapped.addMouseListener(rightClickListener)
add(wrapped) add(wrapped)
add(Box.createVerticalStrut(10)) add(Box.createVerticalStrut(8))
revalidate() revalidate()
if(focusedView == VIEW_NAME)
repaint() repaint()
} }
} }
@ -158,7 +166,7 @@ object LootTrackerView {
xpLeftLabel = JLabel(), xpLeftLabel = JLabel(),
actionsRemainingLabel = JLabel(), actionsRemainingLabel = JLabel(),
xpPerHourLabel = l1, xpPerHourLabel = l1,
progressBar = ProgressBar(0.0, Color(150, 50, 50)), progressBar = ProgressBar(0.0, Color(0,0,0)), // unused.
totalXpGained = 0, totalXpGained = 0,
startTime = System.currentTimeMillis(), startTime = System.currentTimeMillis(),
previousXp = 0 previousXp = 0
@ -167,16 +175,19 @@ object LootTrackerView {
private fun createWidgetPanel(bufferedImageSprite: BufferedImage, l1 : JLabel, l2 : JLabel): Panel { private fun createWidgetPanel(bufferedImageSprite: BufferedImage, l1 : JLabel, l2 : JLabel): Panel {
val imageCanvas = ImageCanvas(bufferedImageSprite).apply { val imageCanvas = ImageCanvas(bufferedImageSprite).apply {
size = Dimension(width, height) preferredSize = Dimension(bufferedImageSprite.width, bufferedImageSprite.height)
minimumSize = preferredSize
maximumSize = preferredSize
size = preferredSize
background = WIDGET_COLOR background = WIDGET_COLOR
} }
val imageContainer = Panel(FlowLayout()).apply { val imageContainer = Panel(BorderLayout()).apply {
background = WIDGET_COLOR background = WIDGET_COLOR
add(imageCanvas) add(imageCanvas, BorderLayout.NORTH)
} }
return Panel(BorderLayout(5, 5)).apply { return Panel(BorderLayout(5, 0)).apply {
background = WIDGET_COLOR background = WIDGET_COLOR
preferredSize = TOTAL_XP_WIDGET_SIZE preferredSize = TOTAL_XP_WIDGET_SIZE
add(imageContainer, BorderLayout.WEST) add(imageContainer, BorderLayout.WEST)
@ -185,7 +196,7 @@ object LootTrackerView {
} }
private fun createTextPanel(l1 : JLabel, l2: JLabel): Panel { private fun createTextPanel(l1 : JLabel, l2: JLabel): Panel {
return Panel(GridLayout(2, 1, 5, 5)).apply { return Panel(GridLayout(2, 1, 5, 0)).apply {
background = WIDGET_COLOR background = WIDGET_COLOR
add(l1) add(l1)
add(l2) add(l2)
@ -219,8 +230,9 @@ object LootTrackerView {
lootPanel.parent.maximumSize = size lootPanel.parent.maximumSize = size
lootPanel.parent.revalidate() lootPanel.parent.revalidate()
lootPanel.parent.repaint() lootPanel.parent.repaint()
lootPanel.revalidate() lootPanel.revalidate()
if(focusedView == VIEW_NAME)
lootPanel.repaint() lootPanel.repaint()
} }
} }
@ -231,7 +243,7 @@ object LootTrackerView {
} }
private fun createItemPanel(itemId: Int, quantity: Int): JPanel { private fun createItemPanel(itemId: Int, quantity: Int): JPanel {
val bufferedImageSprite = getBufferedImageFromSprite(API.GetObjSprite(itemId, quantity, true, 0, 0)) val bufferedImageSprite = getBufferedImageFromSprite(API.GetObjSprite(itemId, quantity, true, 1, 3153952))
// Create the panel for the item // Create the panel for the item
val itemPanel = FixedSizePanel(Dimension(36, 32)).apply { val itemPanel = FixedSizePanel(Dimension(36, 32)).apply {
@ -276,22 +288,22 @@ object LootTrackerView {
val gePricePerItem = gePriceMap[itemDef.id.toString()]?.toInt() ?: 0 val gePricePerItem = gePriceMap[itemDef.id.toString()]?.toInt() ?: 0
val totalGePrice = gePricePerItem * quantity val totalGePrice = gePricePerItem * quantity
val totalHaPrice = itemDef.cost * quantity val totalHaPrice = itemDef.cost * quantity
val geText = if (quantity > 1) " (${gePricePerItem} ea)" else "" val geText = if (quantity > 1) " (${formatValue(gePricePerItem)} ea)" else ""
val haText = if (quantity > 1) " (${itemDef.cost} ea)" else "" val haText = if (quantity > 1) " (${formatValue(itemDef.cost)} ea)" else ""
val bgColor = Helpers.colorToHex(TOOLTIP_BACKGROUND)
val text = "<html><div style='color: white; background-color: #323232; padding: 3px;'>" + val textColor = Helpers.colorToHex(secondaryColor)
val text = "<html><div style='color: "+textColor+"; background-color: "+bgColor+"; padding: 3px;'>" +
"${itemDef.name} x $quantity<br>" + "${itemDef.name} x $quantity<br>" +
"GE: $totalGePrice ${geText}<br>" + "GE: ${formatValue(totalGePrice)} ${geText}<br>" +
"HA: $totalHaPrice ${haText}</div></html>" "HA: ${formatValue(totalHaPrice)} ${haText}</div></html>"
val _font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16) val _font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
val c = Color(50,50,50)
if (customToolTipWindow == null) { if (customToolTipWindow == null) {
customToolTipWindow = JWindow().apply { customToolTipWindow = JWindow().apply {
contentPane = JLabel(text).apply { contentPane = JLabel(text).apply {
border = BorderFactory.createLineBorder(Color.BLACK) border = BorderFactory.createLineBorder(Color.BLACK)
isOpaque = true isOpaque = true
background = c background = TOOLTIP_BACKGROUND
foreground = Color.WHITE foreground = Color.WHITE
font = _font font = _font
} }
@ -316,6 +328,7 @@ object LootTrackerView {
panel.removeAll() panel.removeAll()
panel.add(createItemPanel(itemId, quantity).components[0], BorderLayout.CENTER) panel.add(createItemPanel(itemId, quantity).components[0], BorderLayout.CENTER)
panel.revalidate() panel.revalidate()
if(focusedView == VIEW_NAME)
panel.repaint() panel.repaint()
} }
@ -340,6 +353,7 @@ object LootTrackerView {
text = "${formatValue(newValue)} gp" text = "${formatValue(newValue)} gp"
putClientProperty("val", newValue) putClientProperty("val", newValue)
revalidate() revalidate()
if(focusedView == VIEW_NAME)
repaint() repaint()
} }
} }
@ -401,8 +415,9 @@ object LootTrackerView {
findLootItemsPanel(lootTrackerView, npcName)?.let { findLootItemsPanel(lootTrackerView, npcName)?.let {
} ?: run { } ?: run {
lootTrackerView.add(createLootFrame(npcName)) lootTrackerView.add(createLootFrame(npcName))
lootTrackerView.add(Box.createVerticalStrut(10)) lootTrackerView.add(Box.createVerticalStrut(8))
lootTrackerView.revalidate() lootTrackerView.revalidate()
if(focusedView == VIEW_NAME)
lootTrackerView.repaint() lootTrackerView.repaint()
} }
@ -427,7 +442,7 @@ object LootTrackerView {
} }
val labelPanel = JPanel(BorderLayout()).apply { val labelPanel = JPanel(BorderLayout()).apply {
background = Color(21, 21, 21) background = TITLE_BAR_COLOR
border = BorderFactory.createEmptyBorder(5, 5, 5, 5) border = BorderFactory.createEmptyBorder(5, 5, 5, 5)
maximumSize = Dimension(230, 24) maximumSize = Dimension(230, 24)
minimumSize = maximumSize minimumSize = maximumSize
@ -436,14 +451,14 @@ object LootTrackerView {
val killCount = npcKillCounts.getOrPut(npcName) { 0 } val killCount = npcKillCounts.getOrPut(npcName) { 0 }
val countLabel = JLabel(formatHtmlLabelText(npcName, secondaryColor, " x $killCount", primaryColor)).apply { val countLabel = JLabel(formatHtmlLabelText(npcName, secondaryColor, " x $killCount", primaryColor)).apply {
foreground = Color(200, 200, 200) foreground = secondaryColor
font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16) font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
horizontalAlignment = JLabel.LEFT horizontalAlignment = JLabel.LEFT
name = "killCountLabel_$npcName" name = "killCountLabel_$npcName"
} }
val valueLabel = JLabel("0 gp").apply { val valueLabel = JLabel("0 gp").apply {
foreground = Color(200, 200, 200) foreground = secondaryColor
font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16) font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
horizontalAlignment = JLabel.RIGHT horizontalAlignment = JLabel.RIGHT
name = "valueLabel_$npcName" name = "valueLabel_$npcName"
@ -491,13 +506,13 @@ object LootTrackerView {
val popupMenu = JPopupMenu() val popupMenu = JPopupMenu()
val rFont = Font("RuneScape Small", Font.TRUETYPE_FONT, 16) val rFont = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
popupMenu.background = Color(45, 45, 45) popupMenu.background = POPUP_BACKGROUND
// Create menu items with custom font and colors // Create menu items with custom font and colors
val menuItem1 = JMenuItem("Remove").apply { val menuItem1 = JMenuItem("Remove").apply {
font = rFont // Set custom font font = rFont // Set custom font
background = Color(45, 45, 45) // Dark background for item background = POPUP_BACKGROUND // Dark background for item
foreground = Color(220, 220, 220) // Light text color for item foreground = POPUP_FOREGROUND // Light text color for item
} }
popupMenu.add(menuItem1) popupMenu.add(menuItem1)
menuItem1.addActionListener { menuItem1.addActionListener {
@ -509,7 +524,7 @@ object LootTrackerView {
if (toRemoveIndex >= 0 && toRemoveIndex < components.size - 1) { if (toRemoveIndex >= 0 && toRemoveIndex < components.size - 1) {
val nextComponent = components[toRemoveIndex + 1] val nextComponent = components[toRemoveIndex + 1]
if (nextComponent is Box.Filler) { if (nextComponent is Box.Filler) {
// Nasty way to remove the Box.createVerticalStrut(10) after // Nasty way to remove the Box.createVerticalStrut(8) after
// the lootpanel. // the lootpanel.
parent.remove(nextComponent) parent.remove(nextComponent)
} }
@ -528,13 +543,13 @@ object LootTrackerView {
val popupMenu = JPopupMenu() val popupMenu = JPopupMenu()
val rFont = Font("RuneScape Small", Font.TRUETYPE_FONT, 16) val rFont = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
popupMenu.background = Color(45, 45, 45) popupMenu.background = POPUP_BACKGROUND
// Create menu items with custom font and colors // Create menu items with custom font and colors
val menuItem1 = JMenuItem("Reset Loot Tracker").apply { val menuItem1 = JMenuItem("Reset Loot Tracker").apply {
font = rFont // Set custom font font = rFont // Set custom font
background = Color(45, 45, 45) // Dark background for item background = POPUP_BACKGROUND // Dark background for item
foreground = Color(220, 220, 220) // Light text color for item foreground = POPUP_FOREGROUND // Light text color for item
} }
popupMenu.add(menuItem1) popupMenu.add(menuItem1)
menuItem1.addActionListener { menuItem1.addActionListener {
@ -572,7 +587,7 @@ object LootTrackerView {
wrapped.addMouseListener(rightClickListener) wrapped.addMouseListener(rightClickListener)
lootTrackerView?.add(Box.createVerticalStrut(5)) lootTrackerView?.add(Box.createVerticalStrut(5))
lootTrackerView?.add(wrapped) lootTrackerView?.add(wrapped)
lootTrackerView?.add(Box.createVerticalStrut(10)) lootTrackerView?.add(Box.createVerticalStrut(8))
lootTrackerView?.revalidate() lootTrackerView?.revalidate()
lootTrackerView?.repaint() lootTrackerView?.repaint()
} }

View file

@ -1,5 +1,7 @@
package KondoKit package KondoKit
import KondoKit.plugin.Companion.PROGRESS_BAR_FILL
import KondoKit.plugin.Companion.secondaryColor
import java.awt.Canvas import java.awt.Canvas
import java.awt.Color import java.awt.Color
import java.awt.Dimension import java.awt.Dimension
@ -26,24 +28,24 @@ class ProgressBar(
g.fillRect(0, 0, width, this.height) g.fillRect(0, 0, width, this.height)
// Draw the unfilled part of the progress bar // Draw the unfilled part of the progress bar
g.color = Color(61, 56, 49) // from Runelite g.color = PROGRESS_BAR_FILL
g.fillRect(width, 0, this.width - width, this.height) g.fillRect(width, 0, this.width - width, this.height)
// Variables for text position // Variables for text position
val textY = this.height / 2 + 6 val textY = this.height / 2 + 6
// Draw the current level on the far left // Draw the current level on the far left
drawTextWithShadow(g, "Lvl. $currentLevel", 5, textY, Color(255, 255, 255)) drawTextWithShadow(g, "Lvl. $currentLevel", 5, textY, secondaryColor)
// Draw the percentage in the middle // Draw the percentage in the middle
val percentageText = String.format("%.2f%%", progress) val percentageText = String.format("%.2f%%", progress)
val percentageWidth = g.fontMetrics.stringWidth(percentageText) val percentageWidth = g.fontMetrics.stringWidth(percentageText)
drawTextWithShadow(g, percentageText, (this.width - percentageWidth) / 2, textY, Color(255, 255, 255)) drawTextWithShadow(g, percentageText, (this.width - percentageWidth) / 2, textY, secondaryColor)
// Draw the next level on the far right // Draw the next level on the far right
val nextLevelText = "Lvl. $nextLevel" val nextLevelText = "Lvl. $nextLevel"
val nextLevelWidth = g.fontMetrics.stringWidth(nextLevelText) val nextLevelWidth = g.fontMetrics.stringWidth(nextLevelText)
drawTextWithShadow(g, nextLevelText, this.width - nextLevelWidth - 5, textY, Color(255, 255, 255)) drawTextWithShadow(g, nextLevelText, this.width - nextLevelWidth - 5, textY, secondaryColor)
} }
override fun getPreferredSize(): Dimension { override fun getPreferredSize(): Dimension {

View file

@ -2,10 +2,13 @@ package KondoKit
import KondoKit.Helpers.convertValue import KondoKit.Helpers.convertValue
import KondoKit.Helpers.showToast import KondoKit.Helpers.showToast
import KondoKit.plugin.Companion.TITLE_BAR_COLOR
import KondoKit.plugin.Companion.TOOLTIP_BACKGROUND
import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR
import KondoKit.plugin.Companion.WIDGET_COLOR import KondoKit.plugin.Companion.WIDGET_COLOR
import KondoKit.plugin.Companion.primaryColor import KondoKit.plugin.Companion.primaryColor
import KondoKit.plugin.Companion.secondaryColor import KondoKit.plugin.Companion.secondaryColor
import KondoKit.plugin.StateManager.focusedView
import plugin.Plugin import plugin.Plugin
import plugin.PluginInfo import plugin.PluginInfo
import plugin.PluginRepository import plugin.PluginRepository
@ -28,6 +31,7 @@ import kotlin.math.ceil
object ReflectiveEditorView { object ReflectiveEditorView {
var reflectiveEditorView: JPanel? = null var reflectiveEditorView: JPanel? = null
val loadedPlugins: MutableList<String> = mutableListOf() val loadedPlugins: MutableList<String> = mutableListOf()
const val VIEW_NAME = "REFLECTIVE_EDITOR_VIEW"
fun createReflectiveEditorView() { fun createReflectiveEditorView() {
val reflectiveEditorPanel = JPanel(BorderLayout()) val reflectiveEditorPanel = JPanel(BorderLayout())
reflectiveEditorPanel.background = VIEW_BACKGROUND_COLOR reflectiveEditorPanel.background = VIEW_BACKGROUND_COLOR
@ -100,7 +104,7 @@ object ReflectiveEditorView {
reflectiveEditorView.revalidate() reflectiveEditorView.revalidate()
if(plugin.StateManager.focusedView == "REFLECTIVE_EDITOR_VIEW") if(focusedView == VIEW_NAME)
reflectiveEditorView.repaint() reflectiveEditorView.repaint()
} }
@ -128,7 +132,7 @@ object ReflectiveEditorView {
label.font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16) label.font = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
labelPanel.add(label, BorderLayout.CENTER) labelPanel.add(label, BorderLayout.CENTER)
label.isOpaque = true label.isOpaque = true
label.background = Color(21, 21, 21) label.background = TITLE_BAR_COLOR
reflectiveEditorView.add(labelPanel) reflectiveEditorView.add(labelPanel)
for (field in exposedFields) { for (field in exposedFields) {
@ -270,7 +274,6 @@ object ReflectiveEditorView {
fun showCustomToolTip(text: String, component: JComponent) { fun showCustomToolTip(text: String, component: JComponent) {
val _font = Font("RuneScape Small", Font.PLAIN, 16) val _font = Font("RuneScape Small", Font.PLAIN, 16)
val backgroundColor = Color(50, 50, 50)
val maxWidth = 150 val maxWidth = 150
val lineHeight = 16 val lineHeight = 16
@ -290,10 +293,12 @@ object ReflectiveEditorView {
if (customToolTipWindow == null) { if (customToolTipWindow == null) {
customToolTipWindow = JWindow().apply { customToolTipWindow = JWindow().apply {
contentPane = JLabel("<html><div style='color: white; background-color: #323232; padding: 3px; word-break: break-all;'>$text</div></html>").apply { val bgColor = Helpers.colorToHex(TOOLTIP_BACKGROUND)
val textColor = Helpers.colorToHex(secondaryColor)
contentPane = JLabel("<html><div style='color: $textColor; background-color: $bgColor; padding: 3px; word-break: break-all;'>$text</div></html>").apply {
border = BorderFactory.createLineBorder(Color.BLACK) border = BorderFactory.createLineBorder(Color.BLACK)
isOpaque = true isOpaque = true
background = backgroundColor background = TOOLTIP_BACKGROUND
foreground = Color.WHITE foreground = Color.WHITE
font = _font font = _font
maximumSize = Dimension(maxWidth, Int.MAX_VALUE) maximumSize = Dimension(maxWidth, Int.MAX_VALUE)
@ -304,7 +309,9 @@ object ReflectiveEditorView {
} else { } else {
// Update the tooltip text // Update the tooltip text
val label = customToolTipWindow!!.contentPane as JLabel val label = customToolTipWindow!!.contentPane as JLabel
label.text = "<html><div style='color: white; background-color: #323232; padding: 3px; word-break: break-all;'>$text</div></html>" val bgColor = Helpers.colorToHex(TOOLTIP_BACKGROUND)
val textColor = Helpers.colorToHex(secondaryColor)
label.text = "<html><div style='color: $textColor; background-color: $bgColor; padding: 3px; word-break: break-all;'>$text</div></html>"
label.preferredSize = Dimension(maxWidth, requiredHeight) label.preferredSize = Dimension(maxWidth, requiredHeight)
customToolTipWindow!!.pack() customToolTipWindow!!.pack()
} }

View file

@ -1,8 +1,8 @@
package KondoKit package KondoKit
import KondoKit.plugin.Companion.SCROLL_BAR_COLOR
import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR
import rt4.GameShell.frame import rt4.GameShell.frame
import java.awt.Color
import java.awt.Graphics import java.awt.Graphics
import java.awt.Graphics2D import java.awt.Graphics2D
import java.awt.Rectangle import java.awt.Rectangle
@ -147,7 +147,7 @@ class ScrollablePanel(private val content: JPanel) : JPanel() {
if (showScrollbar) { if (showScrollbar) {
val g2 = g as Graphics2D val g2 = g as Graphics2D
val scrollbarX = 238 val scrollbarX = 238
g2.color = Color(64, 64, 64) g2.color = SCROLL_BAR_COLOR
g2.fillRect(scrollbarX, scrollbarY, 2, scrollbarHeight) g2.fillRect(scrollbarX, scrollbarY, 2, scrollbarHeight)
} }
} }

View file

@ -4,109 +4,172 @@ import rt4.GlIndexedSprite
import rt4.GlSprite import rt4.GlSprite
import rt4.SoftwareIndexedSprite import rt4.SoftwareIndexedSprite
import rt4.SoftwareSprite import rt4.SoftwareSprite
import java.awt.Color
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
// Define interfaces for common sprite types
interface BaseSprite {
val width: Int
val height: Int
}
interface IndexedSprite : BaseSprite {
val pixels: ByteArray
val palette: IntArray
}
interface NonIndexedSprite : BaseSprite {
val pixels: IntArray?
}
// Adapter functions for existing sprite types
fun adaptSoftwareSprite(sprite: SoftwareSprite): NonIndexedSprite {
return object : NonIndexedSprite {
override val width: Int = sprite.width
override val height: Int = sprite.height
override val pixels: IntArray? = sprite.pixels
}
}
fun adaptSoftwareIndexedSprite(sprite: SoftwareIndexedSprite): IndexedSprite {
return object : IndexedSprite {
override val width: Int = sprite.width
override val height: Int = sprite.height
override val pixels: ByteArray = sprite.pixels
override val palette: IntArray = sprite.pallet
}
}
fun adaptGlSprite(sprite: GlSprite): NonIndexedSprite {
return object : NonIndexedSprite {
override val width: Int = sprite.width
override val height: Int = sprite.height
override val pixels: IntArray? = sprite.pixels
}
}
fun adaptGlIndexedSprite(sprite: GlIndexedSprite): IndexedSprite {
return object : IndexedSprite {
override val width: Int = sprite.width
override val height: Int = sprite.height
override val pixels: ByteArray = sprite.pixels
override val palette: IntArray = sprite.pallet
}
}
object SpriteToBufferedImage { object SpriteToBufferedImage {
/** /**
* Converts a SoftwareSprite back into a BufferedImage. * Converts a BaseSprite into a BufferedImage.
*
* Handles both indexed and non-indexed sprites, with optional tinting and grayscale.
* *
* @param sprite The sprite to be converted. * @param sprite The sprite to be converted.
* @param tint An optional Color to tint the image.
* @param grayscale If true, converts the image to grayscale.
* @return The BufferedImage created from the sprite. * @return The BufferedImage created from the sprite.
*/ */
fun convertToBufferedImage(sprite: SoftwareSprite): BufferedImage { fun convertToBufferedImage(sprite: BaseSprite, tint: Color? = null, grayscale: Boolean = false): BufferedImage {
val width = sprite.width val width = sprite.width
val height = sprite.height val height = sprite.height
val image = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
when (sprite) {
is IndexedSprite -> {
val pixels = sprite.pixels val pixels = sprite.pixels
val palette = sprite.palette
// Create a BufferedImage with ARGB color model
val image = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
// Manually set pixels and print the pixel data
for (y in 0 until height) {
for (x in 0 until width) {
val pixel = pixels[y * width + x]
image.setRGB(x, y, pixel)
}
}
return image
}
fun convertToBufferedImage(sprite: SoftwareIndexedSprite): BufferedImage {
val width = sprite.width
val height = sprite.height
val pixels = sprite.pixels // byte[]
val palette = sprite.pallet
// Create a BufferedImage with ARGB color model
val image = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
// Manually set pixels using the palette // Manually set pixels using the palette
for (y in 0 until height) { for (y in 0 until height) {
for (x in 0 until width) { for (x in 0 until width) {
// Get the index from the sprite's pixel array
val index = pixels[y * width + x].toInt() and 0xFF val index = pixels[y * width + x].toInt() and 0xFF
// Map the index to a color in the palette var color = palette[index]
val color = palette[index]
// Set the ARGB color in the BufferedImage // Apply grayscale or tint if provided
image.setRGB(x, y, color) val finalColor = if (grayscale) {
} applyGrayscale(Color(color, true))
} } else if (tint != null) {
return image applyTint(Color(color, true), tint)
} else {
Color(color, true)
} }
fun convertToBufferedImage(sprite: GlIndexedSprite): BufferedImage { image.setRGB(x, y, finalColor.rgb)
val width = sprite.width }
val height = sprite.height }
val pixels = sprite.pixels // byte[] }
val palette = sprite.pallet is NonIndexedSprite -> {
val pixels = sprite.pixels ?: return image // Handle null case for GlSprite
// Create a BufferedImage with ARGB color model // Manually set pixels directly
val image = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
// Manually set pixels using the palette
for (y in 0 until height) { for (y in 0 until height) {
for (x in 0 until width) { for (x in 0 until width) {
// Get the index from the sprite's pixel array var color = pixels[y * width + x]
val index = pixels[y * width + x].toInt() and 0xFF
// Map the index to a color in the palette // Apply grayscale or tint if provided
val color = palette[index] val finalColor = if (grayscale) {
// Set the ARGB color in the BufferedImage applyGrayscale(Color(color, true))
image.setRGB(x, y, color) } else if (tint != null) {
applyTint(Color(color, true), tint)
} else {
Color(color, true)
}
image.setRGB(x, y, finalColor.rgb)
} }
} }
}
}
return image return image
} }
/**
* Applies a tint to a given color using the tint's alpha value to control the intensity.
*
* @param original The original color.
* @param tint The tint color to be applied, with alpha controlling the intensity.
* @return The tinted color.
*/
fun applyTint(original: Color, tint: Color): Color {
val alpha = tint.alpha / 255.0 // Normalize alpha to range [0, 1]
val invAlpha = 1.0 - alpha
fun convertToBufferedImage(sprite: GlSprite): BufferedImage { // Blend the tint with the original color based on the alpha
val width = sprite.width val r = (original.red * invAlpha + tint.red * alpha).toInt().coerceIn(0, 255)
val height = sprite.height val g = (original.green * invAlpha + tint.green * alpha).toInt().coerceIn(0, 255)
val pixels = sprite.pixels val b = (original.blue * invAlpha + tint.blue * alpha).toInt().coerceIn(0, 255)
// Create a BufferedImage with ARGB color model return Color(r, g, b, original.alpha)
val image = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
if(pixels == null) {
return image
} }
// Manually set pixels and print the pixel data
for (y in 0 until height) { /**
for (x in 0 until width) { * Converts a color to grayscale.
val pixel = pixels[y * width + x] *
image.setRGB(x, y, pixel) * @param original The original color.
} * @return The grayscale version of the color.
} */
return image fun applyGrayscale(original: Color): Color {
// Calculate the grayscale value using the luminosity method
val grayValue = (0.3 * original.red + 0.59 * original.green + 0.11 * original.blue).toInt()
return Color(grayValue, grayValue, grayValue, original.alpha)
} }
fun getBufferedImageFromSprite(sprite: Any?) : BufferedImage { /**
* Converts an unknown sprite object into a BufferedImage if it matches a known sprite type.
*
* @param sprite The sprite object to be converted.
* @param tint An optional Color to tint the image.
* @param grayscale If true, converts the image to grayscale.
* @return The BufferedImage created from the sprite or a default image if unsupported.
*/
fun getBufferedImageFromSprite(sprite: Any?, tint: Color? = null, grayscale: Boolean = false): BufferedImage {
return when (sprite) { return when (sprite) {
is GlSprite -> convertToBufferedImage(sprite) is SoftwareSprite -> convertToBufferedImage(adaptSoftwareSprite(sprite), tint, grayscale)
is SoftwareSprite -> convertToBufferedImage(sprite) is SoftwareIndexedSprite -> convertToBufferedImage(adaptSoftwareIndexedSprite(sprite), tint, grayscale)
is SoftwareIndexedSprite -> convertToBufferedImage(sprite) is GlSprite -> convertToBufferedImage(adaptGlSprite(sprite), tint, grayscale)
is GlIndexedSprite -> convertToBufferedImage(sprite) is GlIndexedSprite -> convertToBufferedImage(adaptGlIndexedSprite(sprite), tint, grayscale)
else -> BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB) else -> BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB) // Default empty image for unsupported types
} }
} }
} }

View file

@ -8,6 +8,8 @@ import KondoKit.Helpers.getSpriteId
import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite
import KondoKit.plugin.Companion.IMAGE_SIZE import KondoKit.plugin.Companion.IMAGE_SIZE
import KondoKit.plugin.Companion.LVL_ICON import KondoKit.plugin.Companion.LVL_ICON
import KondoKit.plugin.Companion.POPUP_BACKGROUND
import KondoKit.plugin.Companion.POPUP_FOREGROUND
import KondoKit.plugin.Companion.TOTAL_XP_WIDGET_SIZE import KondoKit.plugin.Companion.TOTAL_XP_WIDGET_SIZE
import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR
import KondoKit.plugin.Companion.WIDGET_COLOR import KondoKit.plugin.Companion.WIDGET_COLOR
@ -15,6 +17,7 @@ import KondoKit.plugin.Companion.WIDGET_SIZE
import KondoKit.plugin.Companion.playerXPMultiplier import KondoKit.plugin.Companion.playerXPMultiplier
import KondoKit.plugin.Companion.primaryColor import KondoKit.plugin.Companion.primaryColor
import KondoKit.plugin.Companion.secondaryColor import KondoKit.plugin.Companion.secondaryColor
import KondoKit.plugin.StateManager.focusedView
import plugin.api.API import plugin.api.API
import java.awt.* import java.awt.*
import java.awt.event.MouseAdapter import java.awt.event.MouseAdapter
@ -30,6 +33,7 @@ object XPTrackerView {
var totalXPWidget: XPWidget? = null var totalXPWidget: XPWidget? = null
val initialXP: MutableMap<Int, Int> = HashMap() val initialXP: MutableMap<Int, Int> = HashMap()
var xpTrackerView: JPanel? = null var xpTrackerView: JPanel? = null
const val VIEW_NAME = "XP_TRACKER_VIEW"
val npcHitpointsMap: Map<Int, Int> = try { val npcHitpointsMap: Map<Int, Int> = try {
@ -96,10 +100,10 @@ object XPTrackerView {
xpWidget.xpGainedLabel.text = formatHtmlLabelText("XP Gained: ", primaryColor, formattedXp, secondaryColor) xpWidget.xpGainedLabel.text = formatHtmlLabelText("XP Gained: ", primaryColor, formattedXp, secondaryColor)
// Update the progress bar with current level, progress, and next level // Update the progress bar with current level, progress, and next level
xpWidget.progressBar.updateProgress(progress, currentLevel, if (currentLevel < 99) currentLevel + 1 else 99, plugin.StateManager.focusedView == "XP_TRACKER_VIEW") xpWidget.progressBar.updateProgress(progress, currentLevel, if (currentLevel < 99) currentLevel + 1 else 99, focusedView == VIEW_NAME)
xpWidget.previousXp = xp xpWidget.previousXp = xp
if (plugin.StateManager.focusedView == "XP_TRACKER_VIEW") if (focusedView == VIEW_NAME)
xpWidget.container.repaint() xpWidget.container.repaint()
} }
@ -109,7 +113,7 @@ object XPTrackerView {
totalXPWidget.totalXpGained += xpGainedSinceLastUpdate totalXPWidget.totalXpGained += xpGainedSinceLastUpdate
val formattedXp = formatNumber(totalXPWidget.totalXpGained) val formattedXp = formatNumber(totalXPWidget.totalXpGained)
totalXPWidget.xpGainedLabel.text = formatHtmlLabelText("Gained: ", primaryColor, formattedXp, secondaryColor) totalXPWidget.xpGainedLabel.text = formatHtmlLabelText("Gained: ", primaryColor, formattedXp, secondaryColor)
if (plugin.StateManager.focusedView == "XP_TRACKER_VIEW") if (focusedView == VIEW_NAME)
totalXPWidget.container.repaint() totalXPWidget.container.repaint()
} }
@ -148,7 +152,7 @@ object XPTrackerView {
xpWidgets.clear() xpWidgets.clear()
xpTrackerView.revalidate() xpTrackerView.revalidate()
if (plugin.StateManager.focusedView == "XP_TRACKER_VIEW") if (focusedView == VIEW_NAME)
xpTrackerView.repaint() xpTrackerView.repaint()
} }
@ -164,10 +168,10 @@ object XPTrackerView {
val bufferedImageSprite = getBufferedImageFromSprite(API.GetSprite(LVL_ICON)) val bufferedImageSprite = getBufferedImageFromSprite(API.GetSprite(LVL_ICON))
val imageContainer = Panel(FlowLayout()).apply { val imageContainer = Panel(FlowLayout()).apply {
preferredSize = IMAGE_SIZE preferredSize = Dimension(bufferedImageSprite.width, bufferedImageSprite.height)
maximumSize = IMAGE_SIZE maximumSize = preferredSize
minimumSize = IMAGE_SIZE minimumSize = preferredSize
size = IMAGE_SIZE size = preferredSize
} }
bufferedImageSprite.let { image -> bufferedImageSprite.let { image ->
@ -182,7 +186,7 @@ object XPTrackerView {
imageContainer.size = Dimension(bufferedImageSprite.width, bufferedImageSprite.height) imageContainer.size = Dimension(bufferedImageSprite.width, bufferedImageSprite.height)
imageContainer.revalidate() imageContainer.revalidate()
if(plugin.StateManager.focusedView == "XP_TRACKER_VIEW") if(focusedView == VIEW_NAME)
imageContainer.repaint() imageContainer.repaint()
} }
@ -221,7 +225,7 @@ object XPTrackerView {
this.font = font this.font = font
}, },
xpPerHourLabel = xpPerHourLabel, xpPerHourLabel = xpPerHourLabel,
progressBar = ProgressBar(0.0, Color(150, 50, 50)), progressBar = ProgressBar(0.0, Color.BLACK), // Unused
totalXpGained = 0, totalXpGained = 0,
startTime = System.currentTimeMillis(), startTime = System.currentTimeMillis(),
previousXp = 0, previousXp = 0,
@ -272,25 +276,13 @@ object XPTrackerView {
val rFont = Font("RuneScape Small", Font.TRUETYPE_FONT, 16) val rFont = Font("RuneScape Small", Font.TRUETYPE_FONT, 16)
popupMenu.background = Color(45, 45, 45) popupMenu.background = POPUP_BACKGROUND
// Create menu items with custom font and colors // Create menu items with custom font and colors
val menuItem1 = JMenuItem("Reset Tracker").apply { val menuItem1 = JMenuItem("Reset Tracker").apply {
font = rFont // Set custom font font = rFont // Set custom font
background = Color(45, 45, 45) // Dark background for item background = POPUP_BACKGROUND // Dark background for item
foreground = Color(220, 220, 220) // Light text color for item foreground = POPUP_FOREGROUND // Light text color for item
}
val menuItem2 = JMenuItem("Option 2").apply {
font = rFont
background = Color(45, 45, 45)
foreground = Color(220, 220, 220)
}
val menuItem3 = JMenuItem("Option 3").apply {
font = rFont
background = Color(45, 45, 45)
foreground = Color(220, 220, 220)
} }
// Add menu items to the popup menu // Add menu items to the popup menu
@ -333,7 +325,7 @@ object XPTrackerView {
imageContainer.size = Dimension(image.width, image.height) // Ensure container respects the image size imageContainer.size = Dimension(image.width, image.height) // Ensure container respects the image size
imageContainer.revalidate() imageContainer.revalidate()
if(plugin.StateManager.focusedView == "XP_TRACKER_VIEW") if(focusedView == VIEW_NAME)
imageContainer.repaint() imageContainer.repaint()
} }
@ -374,7 +366,7 @@ object XPTrackerView {
val levelPanel = Panel().apply { val levelPanel = Panel().apply {
layout = BorderLayout(5, 0) layout = BorderLayout(5, 0)
background = Color(43, 43, 43) background = WIDGET_COLOR
} }
val progressBarPanel = ProgressBar(0.0, getProgressBarColor(skillId)).apply { val progressBarPanel = ProgressBar(0.0, getProgressBarColor(skillId)).apply {
@ -393,7 +385,7 @@ object XPTrackerView {
widgetPanel.add(levelPanel, BorderLayout.SOUTH) widgetPanel.add(levelPanel, BorderLayout.SOUTH)
widgetPanel.revalidate() widgetPanel.revalidate()
if(plugin.StateManager.focusedView == "XP_TRACKER_VIEW") if(focusedView == VIEW_NAME)
widgetPanel.repaint() widgetPanel.repaint()
return XPWidget( return XPWidget(

View file

@ -4,6 +4,8 @@ import KondoKit.Constants.COMBAT_LVL_SPRITE
import KondoKit.Helpers.formatHtmlLabelText import KondoKit.Helpers.formatHtmlLabelText
import KondoKit.Helpers.formatNumber import KondoKit.Helpers.formatNumber
import KondoKit.Helpers.getSpriteId import KondoKit.Helpers.getSpriteId
import KondoKit.Helpers.showAlert
import KondoKit.Helpers.showToast
import KondoKit.HiscoresView.createHiscoreSearchView import KondoKit.HiscoresView.createHiscoreSearchView
import KondoKit.HiscoresView.hiScoreView import KondoKit.HiscoresView.hiScoreView
import KondoKit.LootTrackerView.BAG_ICON import KondoKit.LootTrackerView.BAG_ICON
@ -26,6 +28,7 @@ import KondoKit.XPTrackerView.wrappedWidget
import KondoKit.XPTrackerView.xpTrackerView import KondoKit.XPTrackerView.xpTrackerView
import KondoKit.XPTrackerView.xpWidgets import KondoKit.XPTrackerView.xpWidgets
import KondoKit.plugin.StateManager.focusedView import KondoKit.plugin.StateManager.focusedView
import com.sun.org.apache.xpath.internal.operations.Bool
import plugin.Plugin import plugin.Plugin
import plugin.api.* import plugin.api.*
import plugin.api.API.* import plugin.api.API.*
@ -52,11 +55,26 @@ class plugin : Plugin() {
companion object { companion object {
val WIDGET_SIZE = Dimension(220, 50) val WIDGET_SIZE = Dimension(220, 50)
val TOTAL_XP_WIDGET_SIZE = Dimension(220, 30) val TOTAL_XP_WIDGET_SIZE = Dimension(220, 30)
val IMAGE_SIZE = Dimension(20, 20) val IMAGE_SIZE = Dimension(25, 23)
val WIDGET_COLOR = Color(30, 30, 30)
val VIEW_BACKGROUND_COLOR = Color(40, 40, 40) // Default Theme Colors
val primaryColor = Color(165, 165, 165) // Color for "XP Gained:" var WIDGET_COLOR = Color(30, 30, 30)
val secondaryColor = Color(255, 255, 255) // Color for "0" var TITLE_BAR_COLOR = Color(21, 21, 21)
var VIEW_BACKGROUND_COLOR = Color(40, 40, 40)
var primaryColor = Color(165, 165, 165) // Color for "XP Gained:"
var secondaryColor = Color(255, 255, 255) // Color for "0"
var POPUP_BACKGROUND = Color(45, 45, 45)
var POPUP_FOREGROUND = Color(220, 220, 220)
var TOOLTIP_BACKGROUND = Color(50,50,50)
var SCROLL_BAR_COLOR = Color(64, 64, 64)
var PROGRESS_BAR_FILL = Color(61, 56, 49)
var NAV_TINT: Color? = null
var NAV_GREYSCALE = false
var appliedTheme = ThemeType.RUNELITE
@Exposed("Theme colors for KondoKit, requires a relaunch to apply.")
var theme = ThemeType.RUNELITE
@Exposed("Default: true, Use Local JSON or the prices from the Live/Stable server API") @Exposed("Default: true, Use Local JSON or the prices from the Live/Stable server API")
var useLiveGEPrices = true var useLiveGEPrices = true
@ -90,6 +108,7 @@ class plugin : Plugin() {
private var initialized = false; private var initialized = false;
private var lastClickTime = 0L private var lastClickTime = 0L
private var lastUIOffset = 0 private var lastUIOffset = 0
private const val HIDDEN_VIEW = "HIDDEN";
private val drawActions = mutableListOf<() -> Unit>() private val drawActions = mutableListOf<() -> Unit>()
fun registerDrawAction(action: () -> Unit) { fun registerDrawAction(action: () -> Unit) {
@ -159,6 +178,14 @@ class plugin : Plugin() {
fun OnKondoValueUpdated(){ fun OnKondoValueUpdated(){
StoreData("kondoUseRemoteGE", useLiveGEPrices) StoreData("kondoUseRemoteGE", useLiveGEPrices)
StoreData("kondoTheme", theme.toString())
if(appliedTheme != theme) {
showAlert(
"KondoKit Theme changes require a relaunch.",
"KondoKit",
JOptionPane.INFORMATION_MESSAGE
)
}
StoreData("kondoPlayerXPMultiplier", playerXPMultiplier) StoreData("kondoPlayerXPMultiplier", playerXPMultiplier)
LootTrackerView.gePriceMap = LootTrackerView.loadGEPrices() LootTrackerView.gePriceMap = LootTrackerView.loadGEPrices()
StoreData("kondoLaunchMinimized", launchMinimized) StoreData("kondoLaunchMinimized", launchMinimized)
@ -191,7 +218,7 @@ class plugin : Plugin() {
private fun searchHiscore(username: String): Runnable { private fun searchHiscore(username: String): Runnable {
return Runnable { return Runnable {
setActiveView("HISCORE_SEARCH_VIEW") setActiveView(HiscoresView.VIEW_NAME)
val customSearchField = hiScoreView?.let { HiscoresView.CustomSearchField(it) } val customSearchField = hiScoreView?.let { HiscoresView.CustomSearchField(it) }
customSearchField?.searchPlayer(username) ?: run { customSearchField?.searchPlayer(username) ?: run {
@ -237,7 +264,7 @@ class plugin : Plugin() {
xpTrackerView?.add(Box.createVerticalStrut(5)) xpTrackerView?.add(Box.createVerticalStrut(5))
xpTrackerView?.revalidate() xpTrackerView?.revalidate()
if(focusedView == "XP_TRACKER_VIEW") if(focusedView == XPTrackerView.VIEW_NAME)
xpTrackerView?.repaint() xpTrackerView?.repaint()
updateWidget(xpWidget, xp) updateWidget(xpWidget, xp)
@ -290,6 +317,10 @@ class plugin : Plugin() {
if (frame != null) { if (frame != null) {
loadFont() loadFont()
val themeIndex = (GetData("kondoTheme") as? String) ?: "RUNELITE"
theme = ThemeType.valueOf(themeIndex)
applyTheme(getTheme(theme))
appliedTheme = theme
try { try {
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel") UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel")
@ -337,10 +368,10 @@ class plugin : Plugin() {
createLootTrackerView() createLootTrackerView()
createReflectiveEditorView() createReflectiveEditorView()
mainContentPanel.add(ScrollablePanel(xpTrackerView!!), "XP_TRACKER_VIEW") mainContentPanel.add(ScrollablePanel(xpTrackerView!!), XPTrackerView.VIEW_NAME)
mainContentPanel.add(ScrollablePanel(hiScoreView!!), "HISCORE_SEARCH_VIEW") mainContentPanel.add(ScrollablePanel(hiScoreView!!), HiscoresView.VIEW_NAME)
mainContentPanel.add(ScrollablePanel(lootTrackerView!!), "LOOT_TRACKER_VIEW") mainContentPanel.add(ScrollablePanel(lootTrackerView!!), LootTrackerView.VIEW_NAME)
mainContentPanel.add(ScrollablePanel(reflectiveEditorView!!), "REFLECTIVE_EDITOR_VIEW") mainContentPanel.add(ScrollablePanel(reflectiveEditorView!!), ReflectiveEditorView.VIEW_NAME)
val navPanel = Panel().apply { val navPanel = Panel().apply {
layout = BoxLayout(this, BoxLayout.Y_AXIS) layout = BoxLayout(this, BoxLayout.Y_AXIS)
@ -348,10 +379,10 @@ class plugin : Plugin() {
preferredSize = Dimension(NAVBAR_WIDTH, frame.height) preferredSize = Dimension(NAVBAR_WIDTH, frame.height)
} }
navPanel.add(createNavButton(LVL_ICON, "XP_TRACKER_VIEW")) navPanel.add(createNavButton(LVL_ICON, XPTrackerView.VIEW_NAME))
navPanel.add(createNavButton(MAG_SPRITE, "HISCORE_SEARCH_VIEW")) navPanel.add(createNavButton(MAG_SPRITE, HiscoresView.VIEW_NAME))
navPanel.add(createNavButton(LOOT_ICON, "LOOT_TRACKER_VIEW")) navPanel.add(createNavButton(LOOT_ICON, LootTrackerView.VIEW_NAME))
navPanel.add(createNavButton(WRENCH_ICON, "REFLECTIVE_EDITOR_VIEW")) navPanel.add(createNavButton(WRENCH_ICON, ReflectiveEditorView.VIEW_NAME))
var rightPanel = Panel(BorderLayout()).apply { var rightPanel = Panel(BorderLayout()).apply {
add(mainContentPanel, BorderLayout.CENTER) add(mainContentPanel, BorderLayout.CENTER)
@ -370,9 +401,9 @@ class plugin : Plugin() {
rightPanelWrapper?.let { frame.add(it, BorderLayout.EAST) } rightPanelWrapper?.let { frame.add(it, BorderLayout.EAST) }
if(!launchMinimized){ if(!launchMinimized){
setActiveView("XP_TRACKER_VIEW") setActiveView(XPTrackerView.VIEW_NAME)
} else { } else {
setActiveView("HIDDEN") setActiveView(HIDDEN_VIEW)
} }
initialized = true initialized = true
pluginsReloaded = true pluginsReloaded = true
@ -410,7 +441,7 @@ class plugin : Plugin() {
private fun setActiveView(viewName: String) { private fun setActiveView(viewName: String) {
// Handle the visibility of the main content panel // Handle the visibility of the main content panel
if (viewName == "HIDDEN") { if (viewName == HIDDEN_VIEW) {
mainContentPanel.isVisible = false mainContentPanel.isVisible = false
} else { } else {
if (!mainContentPanel.isVisible) { if (!mainContentPanel.isVisible) {
@ -434,7 +465,7 @@ class plugin : Plugin() {
} }
private fun createNavButton(spriteId: Int, viewName: String): JPanel { private fun createNavButton(spriteId: Int, viewName: String): JPanel {
val bufferedImageSprite = getBufferedImageFromSprite(GetSprite(spriteId)) val bufferedImageSprite = getBufferedImageFromSprite(GetSprite(spriteId), NAV_TINT, NAV_GREYSCALE)
val buttonSize = Dimension(NAVBAR_WIDTH, 32) val buttonSize = Dimension(NAVBAR_WIDTH, 32)
val imageSize = Dimension((bufferedImageSprite.width / 1.2f).toInt(), (bufferedImageSprite.height / 1.2f).toInt()) val imageSize = Dimension((bufferedImageSprite.width / 1.2f).toInt(), (bufferedImageSprite.height / 1.2f).toInt())
val cooldownDuration = 100L val cooldownDuration = 100L
@ -536,4 +567,103 @@ class plugin : Plugin() {
object StateManager { object StateManager {
var focusedView: String = "" var focusedView: String = ""
} }
fun applyTheme(theme: Theme) {
WIDGET_COLOR = theme.widgetColor
TITLE_BAR_COLOR = theme.titleBarColor
VIEW_BACKGROUND_COLOR = theme.viewBackgroundColor
primaryColor = theme.primaryColor
secondaryColor = theme.secondaryColor
POPUP_BACKGROUND = theme.popupBackground
POPUP_FOREGROUND = theme.popupForeground
TOOLTIP_BACKGROUND = theme.tooltipBackground
SCROLL_BAR_COLOR = theme.scrollBarColor
PROGRESS_BAR_FILL = theme.progressBarFill
NAV_TINT = theme.navTint
NAV_GREYSCALE = theme.navGreyScale
}
enum class ThemeType {
RUNELITE,
DARKER_RUNELITE,
SARADOMIN,
ORION,
}
fun getTheme(themeType: ThemeType): Theme {
return when (themeType) {
ThemeType.RUNELITE -> Theme(
widgetColor = Color(30, 30, 30),
titleBarColor = Color(21, 21, 21),
viewBackgroundColor = Color(40, 40, 40),
primaryColor = Color(165, 165, 165),
secondaryColor = Color(255, 255, 255),
popupBackground = Color(45, 45, 45),
popupForeground = Color(220, 220, 220),
tooltipBackground = Color(50, 50, 50),
scrollBarColor = Color(64, 64, 64),
progressBarFill = Color(61, 56, 49),
navTint = null,
navGreyScale = false
)
ThemeType.DARKER_RUNELITE -> Theme(
widgetColor = Color(15, 15, 15), // Darker widget backgrounds
titleBarColor = Color(10, 10, 10), // Even darker title bar
viewBackgroundColor = Color(20, 20, 20), // Very dark background for the view
primaryColor = Color(140, 140, 140), // Darker shade for primary text
secondaryColor = Color(210, 210, 210), // Slightly muted white for secondary text
popupBackground = Color(25, 25, 25), // Very dark popup backgrounds
popupForeground = Color(200, 200, 200), // Slightly muted light gray for popup text
tooltipBackground = Color(30, 30, 30), // Darker tooltips background
scrollBarColor = Color(40, 40, 40), // Darker scroll bar
progressBarFill = Color(45, 40, 35), // Darker progress bar fill
navTint = null, //Color(20, 20, 20, 60), // No specific tint applied
navGreyScale = false // Navigation retains color (if applicable)
)
ThemeType.ORION -> Theme(
widgetColor = Color(50, 50, 50), // Darker gray for widget backgrounds
titleBarColor = Color(35, 35, 35), // Very dark gray for the title bar
viewBackgroundColor = Color(60, 60, 60), // Medium-dark gray for view background
primaryColor = Color(180, 180, 180), // Lighter gray for primary text or highlights
secondaryColor = Color(210, 210, 210), // Light gray for secondary text
popupBackground = Color(45, 45, 45), // Dark gray for popup backgrounds
popupForeground = Color(230, 230, 230), // Light gray for popup text
tooltipBackground = Color(55, 55, 55), // Slightly darker gray for tooltips
scrollBarColor = Color(75, 75, 75), // Dark gray for scroll bars
progressBarFill = Color(100, 100, 100), // Medium gray for progress bar fill
navTint = null,
navGreyScale = true
)
ThemeType.SARADOMIN -> Theme(
widgetColor = Color(75, 60, 45),
titleBarColor = Color(60, 48, 36),
viewBackgroundColor = Color(95, 76, 58),
primaryColor = Color(180, 150, 120),
secondaryColor = Color(230, 210, 190),
popupBackground = Color(70, 56, 42),
popupForeground = Color(220, 200, 180),
tooltipBackground = Color(80, 65, 50),
scrollBarColor = Color(100, 85, 70),
progressBarFill = Color(130, 110, 90),
navTint = null,
navGreyScale = false
)
}
}
data class Theme(
val widgetColor: Color,
val titleBarColor: Color,
val viewBackgroundColor: Color,
val primaryColor: Color,
val secondaryColor: Color,
val popupBackground: Color,
val popupForeground: Color,
val tooltipBackground: Color,
val scrollBarColor: Color,
val progressBarFill: Color,
val navTint: Color?,
val navGreyScale: Boolean
)
} }