Skip to content

Commit 82edb16

Browse files
committed
feat: Add UI update logic when initialize or event occur
- Show challenges and completed challenges dynamically. - Update challenge process when event occur. - Add value change listener for nickname. - Add ScrollPane into dashboard.
1 parent 4d8fecc commit 82edb16

File tree

1 file changed

+149
-33
lines changed

1 file changed

+149
-33
lines changed

src/main/kotlin/com/github/ilovegamecoding/intellijcodexp/toolWindow/CodeXPToolWindowFactory.kt

Lines changed: 149 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package com.github.ilovegamecoding.intellijcodexp.toolWindow
22

33
import com.github.ilovegamecoding.intellijcodexp.StringUtil
4+
import com.github.ilovegamecoding.intellijcodexp.form.CodeXPChallengeForm
45
import com.github.ilovegamecoding.intellijcodexp.form.CodeXPDashboard
56
import com.github.ilovegamecoding.intellijcodexp.listeners.CodeXPListener
7+
import com.github.ilovegamecoding.intellijcodexp.model.CodeXPChallenge
68
import com.github.ilovegamecoding.intellijcodexp.services.CodeXPService
79
import com.intellij.openapi.application.ApplicationManager
810
import com.intellij.openapi.project.Project
911
import com.intellij.openapi.wm.ToolWindow
1012
import com.intellij.openapi.wm.ToolWindowFactory
13+
import com.intellij.ui.components.JBScrollPane
1114
import com.intellij.ui.content.ContentFactory
15+
import java.awt.BorderLayout
1216
import java.awt.Font
1317
import java.awt.GridBagConstraints
1418
import java.awt.GridLayout
@@ -31,7 +35,10 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
3135

3236
// Add the dashboard to the tool window
3337
val contentFactory = ContentFactory.SERVICE.getInstance()
34-
val content = contentFactory.createContent(codeXPDashboard.pMain, null, false)
38+
val scrollPane = JBScrollPane(codeXPDashboard.pMain)
39+
val rootPanel = JPanel(BorderLayout())
40+
rootPanel.add(BorderLayout.CENTER, scrollPane)
41+
val content = contentFactory.createContent(rootPanel, null, false)
3542
toolWindow.contentManager.addContent(content)
3643
}
3744

@@ -40,32 +47,50 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
4047
/**
4148
* Initializes the UI of the dashboard.
4249
*
43-
* @param codeXPService The CodeXP service.
44-
* @param codeXPDashboard The CodeXP dashboard.
50+
* @param codeXPService CodeXP service.
51+
* @param codeXPDashboard CodeXP dashboard.
4552
*/
4653
private fun initializeUI(codeXPService: CodeXPService, codeXPDashboard: CodeXPDashboard) {
4754
// Listen to events from the CodeXP service
4855
val connection = ApplicationManager.getApplication().messageBus.connect()
4956

50-
val constraints = GridBagConstraints()
51-
constraints.weightx = 1.0
52-
constraints.fill = GridBagConstraints.HORIZONTAL
53-
val eventStatics = HashMap<CodeXPService.Event, JPanel>()
57+
// Set nickname and listen changes from the text field
58+
codeXPDashboard.tfNickname.text = codeXPService.state.nickname
59+
codeXPDashboard.tfNickname.document.addDocumentListener(object : DocumentListener {
60+
override fun insertUpdate(e: DocumentEvent) {
61+
updateNickname(codeXPService, codeXPDashboard)
62+
}
63+
64+
override fun removeUpdate(e: DocumentEvent) {
65+
updateNickname(codeXPService, codeXPDashboard)
66+
}
67+
68+
override fun changedUpdate(e: DocumentEvent) {
69+
updateNickname(codeXPService, codeXPDashboard)
70+
}
71+
})
72+
73+
// GridBagConstraints for the event statistics and challenges
74+
val gridBagConstraints = GridBagConstraints()
75+
gridBagConstraints.weightx = 1.0
76+
gridBagConstraints.fill = GridBagConstraints.HORIZONTAL
77+
78+
val eventStaticForms = HashMap<CodeXPService.Event, JPanel>()
79+
val challengeForms = HashMap<CodeXPService.Event, CodeXPChallengeForm>()
80+
5481
CodeXPService.Event.values().forEachIndexed { index, event -> // Add ui for each event
5582
if (event != CodeXPService.Event.NONE) { // Ignore the NONE event type
56-
constraints.gridy = index
83+
// Initialize event statistics
84+
gridBagConstraints.gridy = index
5785

5886
val pEvent = JPanel(GridLayout(1, 3))
5987
pEvent.border = BorderFactory.createEmptyBorder(0, 16, 8, 0)
60-
6188
val lblEventName = JLabel(event.name)
6289
lblEventName.font = Font("Noto Sans SemiBold", Font.PLAIN, 14)
6390
lblEventName.border = BorderFactory.createEmptyBorder(0, 32, 0, 0)
64-
6591
val lblEventReward = JLabel("+" + StringUtil.numberToStringWithCommas(event.xpValue) + " XP")
6692
lblEventReward.font = Font("Noto Sans SemiBold", Font.PLAIN, 14)
6793
lblEventReward.border = BorderFactory.createEmptyBorder(0, 32, 0, 0)
68-
6994
val lblEventCount =
7095
JLabel(StringUtil.numberToStringWithCommas(codeXPService.state.getEventCount(event)))
7196
lblEventCount.font = Font("Noto Sans Medium", Font.PLAIN, 14)
@@ -74,46 +99,77 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
7499
pEvent.add(lblEventName)
75100
pEvent.add(lblEventReward)
76101
pEvent.add(lblEventCount)
77-
codeXPDashboard.pEventStatistics.add(pEvent, constraints)
102+
codeXPDashboard.pEventStatistics.add(pEvent, gridBagConstraints)
78103

79-
eventStatics[event] = pEvent
104+
eventStaticForms[event] = pEvent
105+
106+
// Initialize challenges
107+
val challengeForm = createChallengeForm(codeXPService.state.challenges[event]!!)
108+
codeXPDashboard.pChallenges.add(challengeForm.pChallenge, gridBagConstraints)
109+
challengeForms[event] = challengeForm
80110
}
81111
}
82112

113+
// Initialize completed challenges
114+
codeXPService.state.completedChallenges.forEach { completedChallenge ->
115+
gridBagConstraints.gridy = codeXPDashboard.pCompletedChallenges.componentCount
116+
117+
val challengeForm = createChallengeForm(completedChallenge)
118+
codeXPDashboard.pCompletedChallenges.add(challengeForm.pChallenge, gridBagConstraints)
119+
}
120+
codeXPDashboard.lblCompletedChallengesCount.text =
121+
StringUtil.numberToStringWithCommas(codeXPService.state.completedChallenges.size.toLong())
122+
83123
// Update the dashboard when events occur
84124
connection.subscribe(CodeXPListener.CODEXP_EVENT, object : CodeXPListener {
85125
override fun eventOccurred(event: CodeXPService.Event) {
86-
(eventStatics[event]!!.getComponent(2) as JLabel).text =
126+
(eventStaticForms[event]!!.getComponent(2) as JLabel).text =
87127
StringUtil.numberToStringWithCommas(codeXPService.state.getEventCount(event))
88-
updateXPInfo(codeXPService, codeXPDashboard)
89-
}
90-
})
91128

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-
}
129+
val currentChallenge = codeXPService.state.challenges[event]!!
130+
val beforeChallengeForm = challengeForms[event]!!
97131

98-
override fun removeUpdate(e: DocumentEvent) {
99-
codeXPService.state.nickname = codeXPDashboard.tfNickname.text
100-
}
132+
if (currentChallenge.id == beforeChallengeForm.challengeID) { // Challenge is not completed
133+
updateChallengeProgress(currentChallenge, beforeChallengeForm)
134+
} else { // Before challenge is completed
135+
gridBagConstraints.gridy = codeXPDashboard.pCompletedChallenges.componentCount
136+
codeXPService.state.completedChallenges.find { it.id == beforeChallengeForm.challengeID }
137+
?.let { createChallengeForm(it).pChallenge }?.let {
138+
codeXPDashboard.pCompletedChallenges.add(
139+
it,
140+
gridBagConstraints
141+
)
142+
}
101143

102-
override fun changedUpdate(e: DocumentEvent) {
103-
codeXPService.state.nickname = codeXPDashboard.tfNickname.text
144+
setChallengeToForm(currentChallenge, challengeForms[event]!!)
145+
codeXPDashboard.lblCompletedChallengesCount.text =
146+
StringUtil.numberToStringWithCommas(codeXPService.state.completedChallenges.size.toLong())
147+
}
148+
149+
updateXPInfo(codeXPService, codeXPDashboard)
104150
}
105151
})
106152

107153
updateXPInfo(codeXPService, codeXPDashboard)
108154
}
109155

156+
/**
157+
* Updates user nickname on the dashboard.
158+
*
159+
* @param codeXPService CodeXP service.
160+
* @param codeXPDashboard CodeXP dashboard.
161+
*/
162+
private fun updateNickname(codeXPService: CodeXPService, codeXPDashboard: CodeXPDashboard) {
163+
codeXPDashboard.tfNickname.text = codeXPService.state.nickname
164+
}
165+
110166
/**
111167
* Updates the XP info on the dashboard.
112168
*
113-
* @param codeXPService The CodeXP service.
114-
* @param codeXPDashboard The CodeXP dashboard.
169+
* @param codeXPService CodeXP service.
170+
* @param codeXPDashboard CodeXP dashboard.
115171
*/
116-
fun updateXPInfo(codeXPService: CodeXPService, codeXPDashboard: CodeXPDashboard) {
172+
private fun updateXPInfo(codeXPService: CodeXPService, codeXPDashboard: CodeXPDashboard) {
117173
val totalXP = codeXPService.state.xp
118174
codeXPDashboard.lblTotalXP.text = StringUtil.numberToStringWithCommas(totalXP)
119175
val (currentLevel, xpIntoCurrentLevel, progressToNextLevel) = calculateLevelAndProgress(
@@ -128,6 +184,66 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
128184
codeXPDashboard.lblLevel.text = StringUtil.numberToStringWithCommas(currentLevel.toLong())
129185
}
130186

187+
/**
188+
* Updates challenge progress on the challenge item.
189+
*
190+
* @param challenge Challenge.
191+
* @param challengeForm Challenge form.
192+
*/
193+
private fun updateChallengeProgress(challenge: CodeXPChallenge, challengeForm: CodeXPChallengeForm) {
194+
val progressPercentage = ((challenge.progress.toDouble() / challenge.goal) * 100).toInt()
195+
challengeForm.lblChallengeProgress.text = progressPercentage.toString()
196+
challengeForm.pbChallengeProgress.value = progressPercentage
197+
}
198+
199+
/**
200+
* Creates a challenge form.
201+
*
202+
* @param challenge Challenge to create the form for.
203+
* @return Challenge form.
204+
*/
205+
private fun createChallengeForm(challenge: CodeXPChallenge): CodeXPChallengeForm {
206+
val challengeForm = CodeXPChallengeForm()
207+
challengeForm.challengeID = challenge.id
208+
challengeForm.pChallenge.border = BorderFactory.createEmptyBorder(16, 32, 0, 32)
209+
challengeForm.lblChallengeName.text = challenge.name
210+
challengeForm.lblChallengeReward.text = StringUtil.numberToStringWithCommas(challenge.rewardXP)
211+
challengeForm.lblChallengeDescription.text =
212+
challenge.description.replace("[goal]", StringUtil.numberToStringWithCommas(challenge.goal))
213+
214+
if (challenge.progress >= challenge.goal) {
215+
challengeForm.lblChallengeProgress.isVisible = false
216+
challengeForm.pbChallengeProgress.isVisible = false
217+
challengeForm.lblChallengePercentageIcon.isVisible = false
218+
} else {
219+
updateChallengeProgress(challenge, challengeForm)
220+
}
221+
return challengeForm
222+
}
223+
224+
/**
225+
* Sets challenge to the form.
226+
*
227+
* @param challenge Challenge to set.
228+
* @param challengeForm Challenge form.
229+
*/
230+
private fun setChallengeToForm(challenge: CodeXPChallenge, challengeForm: CodeXPChallengeForm) {
231+
challengeForm.challengeID = challenge.id
232+
challengeForm.pChallenge.border = BorderFactory.createEmptyBorder(16, 32, 0, 32)
233+
challengeForm.lblChallengeName.text = challenge.name
234+
challengeForm.lblChallengeReward.text = StringUtil.numberToStringWithCommas(challenge.rewardXP)
235+
challengeForm.lblChallengeDescription.text =
236+
challenge.description.replace("[goal]", StringUtil.numberToStringWithCommas(challenge.goal))
237+
238+
if (challenge.progress >= challenge.goal) {
239+
challengeForm.lblChallengeProgress.isVisible = false
240+
challengeForm.pbChallengeProgress.isVisible = false
241+
challengeForm.lblChallengePercentageIcon.isVisible = false
242+
} else {
243+
updateChallengeProgress(challenge, challengeForm)
244+
}
245+
}
246+
131247
/**
132248
* Level info data class.
133249
*/
@@ -151,10 +267,10 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
151267
/**
152268
* Calculates the level and progress to the next level.
153269
*
154-
* @param totalXP The total XP.
155-
* @return The level info.
270+
* @param totalXP Total XP.
271+
* @return Level info data class.
156272
*/
157-
fun calculateLevelAndProgress(totalXP: Long): LevelInfo {
273+
private fun calculateLevelAndProgress(totalXP: Long): LevelInfo {
158274
var level = 1
159275
var currentLevelXP = 300.0
160276
var xp = 300.0

0 commit comments

Comments
 (0)