mirror of
https://gitlab.com/2009scape/rt4-client.git
synced 2025-12-16 11:30:19 -07:00
Fix tooltip labels
This commit is contained in:
parent
5bb81c7bd3
commit
5240963743
7 changed files with 135 additions and 156 deletions
|
|
@ -4,44 +4,31 @@ import KondoKit.pluginmanager.GitLabPlugin
|
||||||
import KondoKit.pluginmanager.PluginProperties
|
import KondoKit.pluginmanager.PluginProperties
|
||||||
import KondoKit.util.HttpFetcher
|
import KondoKit.util.HttpFetcher
|
||||||
import KondoKit.pluginmanager.GitLabConfig
|
import KondoKit.pluginmanager.GitLabConfig
|
||||||
|
import KondoKit.util.HttpStatusException
|
||||||
import KondoKit.util.JsonParser
|
import KondoKit.util.JsonParser
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import java.io.BufferedReader
|
|
||||||
import java.io.InputStreamReader
|
|
||||||
import java.net.HttpURLConnection
|
|
||||||
import java.util.concurrent.*
|
import java.util.concurrent.*
|
||||||
import javax.swing.SwingUtilities
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
object GitLabPluginFetcher {
|
object GitLabPluginFetcher {
|
||||||
|
private const val TAG = "GitLabPluginFetcher"
|
||||||
|
|
||||||
// Thread pool for concurrent plugin property fetching
|
// Thread pool for concurrent plugin property fetching
|
||||||
private val executorService = Executors.newFixedThreadPool(5)
|
private val executorService = Executors.newFixedThreadPool(5)
|
||||||
|
|
||||||
// Debug logging function
|
// Debug logging function
|
||||||
private fun debugLog(message: String) {
|
private fun debugLog(message: String) = PluginLogger.debug(TAG, message)
|
||||||
if (GitLabConfig.DEBUG) {
|
|
||||||
println("[GitLabPluginFetcher] $message")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to fetch plugins from GitLab
|
// Function to fetch plugins from GitLab
|
||||||
fun fetchGitLabPlugins(onComplete: (List<GitLabPlugin>) -> Unit) {
|
fun fetchGitLabPlugins(onComplete: (List<GitLabPlugin>) -> Unit) {
|
||||||
Thread {
|
Thread {
|
||||||
|
val plugins = mutableListOf<GitLabPlugin>()
|
||||||
try {
|
try {
|
||||||
debugLog("Starting to fetch GitLab plugins...")
|
debugLog("Starting to fetch GitLab plugins...")
|
||||||
val plugins = mutableListOf<GitLabPlugin>()
|
|
||||||
val apiUrl = GitLabConfig.getRepositoryTreeUrl()
|
val apiUrl = GitLabConfig.getRepositoryTreeUrl()
|
||||||
debugLog("API URL: $apiUrl")
|
debugLog("API URL: $apiUrl")
|
||||||
|
|
||||||
val connection = HttpFetcher.openGetConnection(apiUrl)
|
val response = HttpFetcher.fetchString(apiUrl)
|
||||||
|
|
||||||
// Read response
|
|
||||||
val responseCode = connection.responseCode
|
|
||||||
debugLog("Response code: $responseCode")
|
|
||||||
|
|
||||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
||||||
val reader = BufferedReader(InputStreamReader(connection.inputStream))
|
|
||||||
val response = reader.use { it.readText() }
|
|
||||||
debugLog("Response length: ${response.length} characters")
|
debugLog("Response length: ${response.length} characters")
|
||||||
debugLog("Response preview: ${response.take(200)}...")
|
debugLog("Response preview: ${response.take(200)}...")
|
||||||
|
|
||||||
|
|
@ -85,11 +72,11 @@ object GitLabPluginFetcher {
|
||||||
debugLog("Error getting plugin result: ${e.message}")
|
debugLog("Error getting plugin result: ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} catch (e: HttpStatusException) {
|
||||||
debugLog("HTTP error: $responseCode")
|
debugLog("HTTP error ${e.statusCode} fetching plugin tree: ${e.body.take(200)}")
|
||||||
val errorReader = BufferedReader(InputStreamReader(connection.errorStream))
|
} catch (e: Exception) {
|
||||||
val errorResponse = errorReader.use { it.readText() }
|
debugLog("Exception occurred: ${e.message}")
|
||||||
debugLog("Error response: $errorResponse")
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
debugLog("Completed fetching plugins. Total plugins: ${plugins.size}")
|
debugLog("Completed fetching plugins. Total plugins: ${plugins.size}")
|
||||||
|
|
@ -97,13 +84,6 @@ object GitLabPluginFetcher {
|
||||||
SwingUtilities.invokeLater {
|
SwingUtilities.invokeLater {
|
||||||
onComplete(plugins)
|
onComplete(plugins)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
debugLog("Exception occurred: ${e.message}")
|
|
||||||
e.printStackTrace()
|
|
||||||
SwingUtilities.invokeLater {
|
|
||||||
onComplete(emptyList())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,25 +93,16 @@ object GitLabPluginFetcher {
|
||||||
val pluginUrl = GitLabConfig.getRawFileUrl(pluginFilePath)
|
val pluginUrl = GitLabConfig.getRawFileUrl(pluginFilePath)
|
||||||
debugLog("Fetching plugin.properties from: $pluginUrl")
|
debugLog("Fetching plugin.properties from: $pluginUrl")
|
||||||
|
|
||||||
val connection = HttpFetcher.openGetConnection(pluginUrl)
|
try {
|
||||||
|
val rawContent = HttpFetcher.fetchString(pluginUrl)
|
||||||
// Read response
|
|
||||||
val responseCode = connection.responseCode
|
|
||||||
debugLog("plugin.properties response code: $responseCode")
|
|
||||||
|
|
||||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
||||||
val reader = BufferedReader(InputStreamReader(connection.inputStream))
|
|
||||||
val rawContent = reader.use { it.readText() }
|
|
||||||
debugLog("plugin.properties content length: ${rawContent.length} characters")
|
debugLog("plugin.properties content length: ${rawContent.length} characters")
|
||||||
debugLog("plugin.properties content preview: ${rawContent.take(200)}...")
|
debugLog("plugin.properties content preview: ${rawContent.take(200)}...")
|
||||||
|
|
||||||
return parseProperties(rawContent)
|
return parseProperties(rawContent)
|
||||||
} else {
|
} catch (e: HttpStatusException) {
|
||||||
debugLog("Failed to fetch plugin.properties. Response code: $responseCode")
|
debugLog("Failed to fetch plugin.properties. Response code: ${e.statusCode}")
|
||||||
val errorReader = BufferedReader(InputStreamReader(connection.errorStream))
|
debugLog("Error response for plugin.properties: ${e.body.take(200)}")
|
||||||
val errorResponse = errorReader.use { it.readText() }
|
throw Exception("Plugin file not found for folder: $folderPath", e)
|
||||||
debugLog("Error response for plugin.properties: $errorResponse")
|
|
||||||
throw Exception("Plugin file not found for folder: $folderPath")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import javax.swing.SwingUtilities
|
||||||
* Manages downloading and installing plugins from GitLab with concurrent support
|
* Manages downloading and installing plugins from GitLab with concurrent support
|
||||||
*/
|
*/
|
||||||
object PluginDownloadManager {
|
object PluginDownloadManager {
|
||||||
|
private const val TAG = "PluginDownloadManager"
|
||||||
private const val MAX_CONCURRENT_DOWNLOADS = 3
|
private const val MAX_CONCURRENT_DOWNLOADS = 3
|
||||||
|
|
||||||
// Thread pool for concurrent downloads
|
// Thread pool for concurrent downloads
|
||||||
|
|
@ -30,11 +31,7 @@ object PluginDownloadManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug logging function
|
// Debug logging function
|
||||||
private fun debugLog(message: String) {
|
private fun debugLog(message: String) = PluginLogger.debug(TAG, message)
|
||||||
if (GitLabConfig.DEBUG) {
|
|
||||||
println("[PluginDownloadManager] $message")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get download URL for debugging/logging purposes
|
// Get download URL for debugging/logging purposes
|
||||||
fun getDownloadUrlForLogging(plugin: GitLabPlugin): String {
|
fun getDownloadUrlForLogging(plugin: GitLabPlugin): String {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package KondoKit.pluginmanager
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared lightweight logger so pluginmanager classes don't each redefine
|
||||||
|
* their own debug helper tied to GitLabConfig.DEBUG.
|
||||||
|
*/
|
||||||
|
object PluginLogger {
|
||||||
|
fun debug(tag: String, message: String) {
|
||||||
|
if (GitLabConfig.DEBUG) {
|
||||||
|
println("[$tag] $message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -435,50 +435,50 @@ class SettingsPanel(private val plugin: Plugin) : JPanel() {
|
||||||
companion object {
|
companion object {
|
||||||
var customToolTipWindow: JWindow? = null
|
var customToolTipWindow: JWindow? = null
|
||||||
|
|
||||||
|
private var customToolTipLabel: JLabel? = null
|
||||||
|
|
||||||
fun showCustomToolTip(text: String, component: JComponent) {
|
fun showCustomToolTip(text: String, component: JComponent) {
|
||||||
val tooltipFont = ViewConstants.FONT_RUNESCAPE_SMALL_PLAIN_16
|
val tooltipFont = ViewConstants.FONT_RUNESCAPE_SMALL_PLAIN_16
|
||||||
val maxWidth = 150
|
val maxWidth = 150
|
||||||
|
|
||||||
// Create a dummy JLabel to get FontMetrics for the font used in the tooltip
|
|
||||||
val dummyLabel = JLabel()
|
|
||||||
dummyLabel.font = tooltipFont
|
|
||||||
val fontMetrics = dummyLabel.getFontMetrics(tooltipFont)
|
|
||||||
val lineHeight = fontMetrics.height
|
|
||||||
|
|
||||||
// Calculate the approximate width of the text
|
|
||||||
val textWidth = fontMetrics.stringWidth(text)
|
|
||||||
|
|
||||||
// Calculate the number of lines required based on the text width and max tooltip width
|
|
||||||
val numberOfLines = Math.ceil(textWidth.toDouble() / maxWidth).toInt()
|
|
||||||
|
|
||||||
// Calculate the required height of the tooltip
|
|
||||||
val requiredHeight = numberOfLines * lineHeight + 6 // Adding some padding
|
|
||||||
|
|
||||||
if (customToolTipWindow == null) {
|
|
||||||
customToolTipWindow = JWindow().apply {
|
|
||||||
val bgColor = Helpers.colorToHex(KondoKit.plugin.Companion.TOOLTIP_BACKGROUND)
|
val bgColor = Helpers.colorToHex(KondoKit.plugin.Companion.TOOLTIP_BACKGROUND)
|
||||||
val textColor = Helpers.colorToHex(KondoKit.plugin.Companion.secondaryColor)
|
val textColor = Helpers.colorToHex(KondoKit.plugin.Companion.secondaryColor)
|
||||||
contentPane = JLabel("<html><div style='color: $textColor; background-color: $bgColor; padding: 3px; word-break: break-all;'>$text</div></html>").apply {
|
// Constrain width via HTML so Swing's renderer wraps the text naturally.
|
||||||
|
val safeText = text
|
||||||
|
.replace("&", "&")
|
||||||
|
.replace("<", "<")
|
||||||
|
.replace(">", ">")
|
||||||
|
val html = """
|
||||||
|
<html>
|
||||||
|
<body style="margin:0; padding:6px; width:${maxWidth}px; color:$textColor; background-color:$bgColor; word-wrap:break-word;">
|
||||||
|
$safeText
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val (window, label) = if (customToolTipWindow == null || customToolTipLabel == null) {
|
||||||
|
val lbl = JLabel().apply {
|
||||||
border = BorderFactory.createLineBorder(Color.BLACK)
|
border = BorderFactory.createLineBorder(Color.BLACK)
|
||||||
isOpaque = true
|
isOpaque = true
|
||||||
background = KondoKit.plugin.Companion.TOOLTIP_BACKGROUND
|
background = KondoKit.plugin.Companion.TOOLTIP_BACKGROUND
|
||||||
foreground = Color.WHITE
|
foreground = Color.WHITE
|
||||||
font = tooltipFont
|
font = tooltipFont
|
||||||
maximumSize = Dimension(maxWidth, Int.MAX_VALUE)
|
horizontalAlignment = SwingConstants.LEFT
|
||||||
preferredSize = Dimension(maxWidth, requiredHeight)
|
verticalAlignment = SwingConstants.TOP
|
||||||
}
|
|
||||||
pack()
|
|
||||||
}
|
}
|
||||||
|
val win = JWindow().apply { contentPane.add(lbl) }
|
||||||
|
customToolTipWindow = win
|
||||||
|
customToolTipLabel = lbl
|
||||||
|
win to lbl
|
||||||
} else {
|
} else {
|
||||||
// Update the tooltip text
|
customToolTipWindow!! to customToolTipLabel!!
|
||||||
val label = customToolTipWindow!!.contentPane as JLabel
|
|
||||||
val bgColor = Helpers.colorToHex(KondoKit.plugin.Companion.TOOLTIP_BACKGROUND)
|
|
||||||
val textColor = Helpers.colorToHex(KondoKit.plugin.Companion.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)
|
|
||||||
customToolTipWindow!!.pack()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label.text = html
|
||||||
|
label.font = tooltipFont
|
||||||
|
label.preferredSize = null // let HTML + pack decide size from width constraint
|
||||||
|
window.pack()
|
||||||
|
|
||||||
// Position the tooltip near the component
|
// Position the tooltip near the component
|
||||||
val locationOnScreen = component.locationOnScreen
|
val locationOnScreen = component.locationOnScreen
|
||||||
customToolTipWindow!!.setLocation(locationOnScreen.x, locationOnScreen.y + 15)
|
customToolTipWindow!!.setLocation(locationOnScreen.x, locationOnScreen.y + 15)
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,23 @@ object GEPriceService {
|
||||||
val grand_exchange_price: String?
|
val grand_exchange_price: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private fun <T> mapToPriceMap(
|
||||||
|
items: Array<T>,
|
||||||
|
idSelector: (T) -> String?,
|
||||||
|
priceSelector: (T) -> String?
|
||||||
|
): Map<String, String> {
|
||||||
|
return items.mapNotNull { item ->
|
||||||
|
val id = idSelector(item)
|
||||||
|
val price = priceSelector(item)
|
||||||
|
if (id != null && price != null) id to price else null
|
||||||
|
}.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
fun loadRemotePrices(): Map<String, String> {
|
fun loadRemotePrices(): Map<String, String> {
|
||||||
return try {
|
return try {
|
||||||
val payload = HttpFetcher.fetchString(REMOTE_GE_URL)
|
val payload = HttpFetcher.fetchString(REMOTE_GE_URL)
|
||||||
val items = JsonParser.fromJson<Array<RemoteGEItem>>(payload)
|
val items = JsonParser.fromJson<Array<RemoteGEItem>>(payload)
|
||||||
items.mapNotNull { item ->
|
mapToPriceMap(items, { it.item_id }, { it.value })
|
||||||
val id = item.item_id
|
|
||||||
val value = item.value
|
|
||||||
if (id != null && value != null) id to value else null
|
|
||||||
}.toMap()
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
emptyMap()
|
emptyMap()
|
||||||
}
|
}
|
||||||
|
|
@ -36,11 +44,7 @@ object GEPriceService {
|
||||||
return try {
|
return try {
|
||||||
val json = jsonProvider() ?: return emptyMap()
|
val json = jsonProvider() ?: return emptyMap()
|
||||||
val items = JsonParser.fromJson<Array<LocalGEItem>>(json)
|
val items = JsonParser.fromJson<Array<LocalGEItem>>(json)
|
||||||
items.mapNotNull { item ->
|
mapToPriceMap(items, { it.id }, { it.grand_exchange_price })
|
||||||
val id = item.id
|
|
||||||
val price = item.grand_exchange_price
|
|
||||||
if (id != null && price != null) id to price else null
|
|
||||||
}.toMap()
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
emptyMap()
|
emptyMap()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import KondoKit.util.setFixedSize
|
||||||
import KondoKit.views.XPTrackerView.wrappedWidget
|
import KondoKit.views.XPTrackerView.wrappedWidget
|
||||||
import KondoKit.ui.components.PopupMenuComponent
|
import KondoKit.ui.components.PopupMenuComponent
|
||||||
import KondoKit.ui.components.ProgressBar
|
import KondoKit.ui.components.ProgressBar
|
||||||
|
import KondoKit.ui.components.LabelComponent
|
||||||
import KondoKit.ui.components.WidgetPanel
|
import KondoKit.ui.components.WidgetPanel
|
||||||
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
|
||||||
|
|
@ -171,12 +172,8 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createLabel(text: String): JLabel {
|
private fun createLabel(text: String): LabelComponent =
|
||||||
return JLabel(text).apply {
|
LabelComponent(text, alignment = JLabel.LEFT)
|
||||||
font = ViewConstants.FONT_RUNESCAPE_SMALL_16
|
|
||||||
horizontalAlignment = JLabel.LEFT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addItemToLootPanel(lootTrackerView: JPanel, drop: Item, npcName: String) {
|
private fun addItemToLootPanel(lootTrackerView: JPanel, drop: Item, npcName: String) {
|
||||||
findLootItemsPanel(lootTrackerView, npcName)?.let { lootPanel ->
|
findLootItemsPanel(lootTrackerView, npcName)?.let { lootPanel ->
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import KondoKit.util.attachPopupMenu
|
||||||
import KondoKit.util.XPTable
|
import KondoKit.util.XPTable
|
||||||
import KondoKit.ui.components.PopupMenuComponent
|
import KondoKit.ui.components.PopupMenuComponent
|
||||||
import KondoKit.ui.components.ProgressBar
|
import KondoKit.ui.components.ProgressBar
|
||||||
|
import KondoKit.ui.components.LabelComponent
|
||||||
import KondoKit.ui.components.WidgetPanel
|
import KondoKit.ui.components.WidgetPanel
|
||||||
import KondoKit.ui.components.XPWidget
|
import KondoKit.ui.components.XPWidget
|
||||||
import KondoKit.plugin.Companion.IMAGE_SIZE
|
import KondoKit.plugin.Companion.IMAGE_SIZE
|
||||||
|
|
@ -91,15 +92,11 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createMetricLabel(title: String, initialValue: String = "0", topPadding: Int = 0): JLabel {
|
private fun createMetricLabel(title: String, initialValue: String = "0", topPadding: Int = 0): LabelComponent =
|
||||||
return JLabel(formatHtmlLabelText("$title ", primaryColor, initialValue, secondaryColor)).apply {
|
LabelComponent(alignment = JLabel.LEFT).apply {
|
||||||
horizontalAlignment = JLabel.LEFT
|
updateHtmlText("$title ", primaryColor, initialValue, secondaryColor)
|
||||||
font = widgetFont
|
|
||||||
if (topPadding > 0) {
|
if (topPadding > 0) {
|
||||||
border = BorderFactory.createEmptyBorder(topPadding, 0, 0, 0)
|
border = BorderFactory.createEmptyBorder(topPadding, 0, 0, 0)
|
||||||
} else {
|
|
||||||
border = BorderFactory.createEmptyBorder(0, 0, 0, 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue