|
1 | 1 | package com.github.ilovegamecoding.intellijcodexp.toolWindow
|
2 | 2 |
|
| 3 | +import com.github.ilovegamecoding.intellijcodexp.StringUtil |
3 | 4 | import com.github.ilovegamecoding.intellijcodexp.form.CodeXPDashboard
|
4 |
| -import com.intellij.openapi.diagnostic.thisLogger |
| 5 | +import com.github.ilovegamecoding.intellijcodexp.listeners.CodeXPListener |
| 6 | +import com.github.ilovegamecoding.intellijcodexp.services.CodeXPService |
| 7 | +import com.intellij.openapi.application.ApplicationManager |
5 | 8 | import com.intellij.openapi.project.Project
|
6 | 9 | import com.intellij.openapi.wm.ToolWindow
|
7 | 10 | import com.intellij.openapi.wm.ToolWindowFactory
|
8 | 11 | import com.intellij.ui.content.ContentFactory
|
| 12 | +import java.awt.Font |
| 13 | +import java.awt.GridBagConstraints |
| 14 | +import java.awt.GridLayout |
| 15 | +import javax.swing.BorderFactory |
| 16 | +import javax.swing.JLabel |
| 17 | +import javax.swing.JPanel |
| 18 | +import javax.swing.event.DocumentEvent |
| 19 | +import javax.swing.event.DocumentListener |
9 | 20 |
|
10 | 21 |
|
11 | 22 | class CodeXPToolWindowFactory : ToolWindowFactory {
|
12 |
| - private var codeXPDashboard = CodeXPDashboard() |
| 23 | + override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) { |
| 24 | + // Get the CodeXP service |
| 25 | + val codeXPService = ApplicationManager.getApplication().getService(CodeXPService::class.java) |
13 | 26 |
|
14 |
| - init { |
15 |
| - thisLogger().warn("Don't forget to remove all non-needed sample code files with their corresponding registration entries in `plugin.xml`.") |
16 |
| - } |
| 27 | + // Create the dashboard |
| 28 | + val codeXPDashboard = CodeXPDashboard() |
17 | 29 |
|
18 |
| - private val contentFactory = ContentFactory.SERVICE.getInstance() |
| 30 | + initializeUI(codeXPService, codeXPDashboard) |
19 | 31 |
|
20 |
| - override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) { |
| 32 | + // Add the dashboard to the tool window |
| 33 | + val contentFactory = ContentFactory.SERVICE.getInstance() |
21 | 34 | val content = contentFactory.createContent(codeXPDashboard.pMain, null, false)
|
22 | 35 | toolWindow.contentManager.addContent(content)
|
23 | 36 | }
|
24 | 37 |
|
25 | 38 | override fun shouldBeAvailable(project: Project) = true
|
26 | 39 |
|
27 |
| - fun setXP(xp: Int) { |
28 |
| - codeXPDashboard.lblLevel.text = "$xp" |
| 40 | + /** |
| 41 | + * Initializes the UI of the dashboard. |
| 42 | + * |
| 43 | + * @param codeXPService The CodeXP service. |
| 44 | + * @param codeXPDashboard The CodeXP dashboard. |
| 45 | + */ |
| 46 | + private fun initializeUI(codeXPService: CodeXPService, codeXPDashboard: CodeXPDashboard) { |
| 47 | + // Listen to events from the CodeXP service |
| 48 | + val connection = ApplicationManager.getApplication().messageBus.connect() |
| 49 | + |
| 50 | + val constraints = GridBagConstraints() |
| 51 | + constraints.weightx = 1.0 |
| 52 | + constraints.fill = GridBagConstraints.HORIZONTAL |
| 53 | + val eventStatics = HashMap<CodeXPService.Event, JPanel>() |
| 54 | + CodeXPService.Event.values().forEachIndexed { index, event -> // Add ui for each event |
| 55 | + if (event != CodeXPService.Event.NONE) { // Ignore the NONE event type |
| 56 | + constraints.gridy = index |
| 57 | + |
| 58 | + val pEvent = JPanel(GridLayout(1, 3)) |
| 59 | + pEvent.border = BorderFactory.createEmptyBorder(0, 16, 8, 0) |
| 60 | + |
| 61 | + val lblEventName = JLabel(event.name) |
| 62 | + lblEventName.font = Font("Noto Sans SemiBold", Font.PLAIN, 14) |
| 63 | + lblEventName.border = BorderFactory.createEmptyBorder(0, 32, 0, 0) |
| 64 | + |
| 65 | + val lblEventReward = JLabel("+" + StringUtil.numberToStringWithCommas(event.xpValue) + " XP") |
| 66 | + lblEventReward.font = Font("Noto Sans SemiBold", Font.PLAIN, 14) |
| 67 | + lblEventReward.border = BorderFactory.createEmptyBorder(0, 32, 0, 0) |
| 68 | + |
| 69 | + val lblEventCount = |
| 70 | + JLabel(StringUtil.numberToStringWithCommas(codeXPService.state.getEventCount(event))) |
| 71 | + lblEventCount.font = Font("Noto Sans Medium", Font.PLAIN, 14) |
| 72 | + lblEventCount.horizontalAlignment = JLabel.CENTER |
| 73 | + |
| 74 | + pEvent.add(lblEventName) |
| 75 | + pEvent.add(lblEventReward) |
| 76 | + pEvent.add(lblEventCount) |
| 77 | + codeXPDashboard.pEventStatistics.add(pEvent, constraints) |
| 78 | + |
| 79 | + eventStatics[event] = pEvent |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + // Update the dashboard when events occur |
| 84 | + connection.subscribe(CodeXPListener.CODEXP_EVENT, object : CodeXPListener { |
| 85 | + override fun eventOccurred(event: CodeXPService.Event) { |
| 86 | + (eventStatics[event]!!.getComponent(2) as JLabel).text = |
| 87 | + StringUtil.numberToStringWithCommas(codeXPService.state.getEventCount(event)) |
| 88 | + updateXPInfo(codeXPService, codeXPDashboard) |
| 89 | + } |
| 90 | + }) |
| 91 | + |
| 92 | + codeXPDashboard.tfNickname.text = codeXPService.state.nickname |
| 93 | + codeXPDashboard.tfNickname.document.addDocumentListener(object : DocumentListener { |
| 94 | + override fun insertUpdate(e: DocumentEvent) { |
| 95 | + codeXPService.state.nickname = codeXPDashboard.tfNickname.text |
| 96 | + } |
| 97 | + |
| 98 | + override fun removeUpdate(e: DocumentEvent) { |
| 99 | + codeXPService.state.nickname = codeXPDashboard.tfNickname.text |
| 100 | + } |
| 101 | + |
| 102 | + override fun changedUpdate(e: DocumentEvent) { |
| 103 | + codeXPService.state.nickname = codeXPDashboard.tfNickname.text |
| 104 | + } |
| 105 | + }) |
| 106 | + |
| 107 | + updateXPInfo(codeXPService, codeXPDashboard) |
| 108 | + } |
| 109 | + |
| 110 | + /** |
| 111 | + * Updates the XP info on the dashboard. |
| 112 | + * |
| 113 | + * @param codeXPService The CodeXP service. |
| 114 | + * @param codeXPDashboard The CodeXP dashboard. |
| 115 | + */ |
| 116 | + fun updateXPInfo(codeXPService: CodeXPService, codeXPDashboard: CodeXPDashboard) { |
| 117 | + val totalXP = codeXPService.state.xp |
| 118 | + codeXPDashboard.lblTotalXP.text = StringUtil.numberToStringWithCommas(totalXP) |
| 119 | + val (currentLevel, xpIntoCurrentLevel, progressToNextLevel) = calculateLevelAndProgress( |
| 120 | + totalXP |
| 121 | + ) |
| 122 | + |
| 123 | + codeXPDashboard.lblCurrentLevel.text = StringUtil.numberToStringWithCommas(currentLevel.toLong()) |
| 124 | + codeXPDashboard.lblNextLevel.text = StringUtil.numberToStringWithCommas((currentLevel + 1).toLong()) |
| 125 | + codeXPDashboard.lblCurrentLevelXP.text = StringUtil.numberToStringWithCommas(xpIntoCurrentLevel) |
| 126 | + codeXPDashboard.pbCurrentLevelProgress.value = progressToNextLevel |
| 127 | + codeXPDashboard.pbCurrentLevelProgress.string = "$progressToNextLevel %" |
| 128 | + codeXPDashboard.lblLevel.text = StringUtil.numberToStringWithCommas(currentLevel.toLong()) |
| 129 | + } |
| 130 | + |
| 131 | + /** |
| 132 | + * Level info data class. |
| 133 | + */ |
| 134 | + data class LevelInfo( |
| 135 | + /** |
| 136 | + * Current level. |
| 137 | + */ |
| 138 | + val currentLevel: Int, |
| 139 | + |
| 140 | + /** |
| 141 | + * XP into the current level. |
| 142 | + */ |
| 143 | + val xpIntoCurrentLevel: Long, |
| 144 | + |
| 145 | + /** |
| 146 | + * Progress to the next level. |
| 147 | + */ |
| 148 | + val progressToNextLevel: Int |
| 149 | + ) |
| 150 | + |
| 151 | + /** |
| 152 | + * Calculates the level and progress to the next level. |
| 153 | + * |
| 154 | + * @param totalXP The total XP. |
| 155 | + * @return The level info. |
| 156 | + */ |
| 157 | + fun calculateLevelAndProgress(totalXP: Long): LevelInfo { |
| 158 | + var level = 1 |
| 159 | + var currentLevelXP = 300.0 |
| 160 | + var xp = 300.0 |
| 161 | + |
| 162 | + while (totalXP >= xp) { |
| 163 | + level++ |
| 164 | + currentLevelXP *= 1.05 |
| 165 | + xp += currentLevelXP |
| 166 | + } |
| 167 | + |
| 168 | + val xpIntoCurrentLevel = totalXP - (xp - currentLevelXP) |
| 169 | + val progress = (xpIntoCurrentLevel / currentLevelXP) * 100 |
| 170 | + |
| 171 | + return LevelInfo(level, xpIntoCurrentLevel.toLong(), progress.toInt()) |
29 | 172 | }
|
30 | 173 | }
|
| 174 | + |
0 commit comments