1
1
package com.github.ilovegamecoding.intellijcodexp.toolWindow
2
2
3
3
import com.github.ilovegamecoding.intellijcodexp.StringUtil
4
+ import com.github.ilovegamecoding.intellijcodexp.form.CodeXPChallengeForm
4
5
import com.github.ilovegamecoding.intellijcodexp.form.CodeXPDashboard
5
6
import com.github.ilovegamecoding.intellijcodexp.listeners.CodeXPListener
7
+ import com.github.ilovegamecoding.intellijcodexp.model.CodeXPChallenge
6
8
import com.github.ilovegamecoding.intellijcodexp.services.CodeXPService
7
9
import com.intellij.openapi.application.ApplicationManager
8
10
import com.intellij.openapi.project.Project
9
11
import com.intellij.openapi.wm.ToolWindow
10
12
import com.intellij.openapi.wm.ToolWindowFactory
13
+ import com.intellij.ui.components.JBScrollPane
11
14
import com.intellij.ui.content.ContentFactory
15
+ import java.awt.BorderLayout
12
16
import java.awt.Font
13
17
import java.awt.GridBagConstraints
14
18
import java.awt.GridLayout
@@ -31,7 +35,10 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
31
35
32
36
// Add the dashboard to the tool window
33
37
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 )
35
42
toolWindow.contentManager.addContent(content)
36
43
}
37
44
@@ -40,32 +47,50 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
40
47
/* *
41
48
* Initializes the UI of the dashboard.
42
49
*
43
- * @param codeXPService The CodeXP service.
44
- * @param codeXPDashboard The CodeXP dashboard.
50
+ * @param codeXPService CodeXP service.
51
+ * @param codeXPDashboard CodeXP dashboard.
45
52
*/
46
53
private fun initializeUI (codeXPService : CodeXPService , codeXPDashboard : CodeXPDashboard ) {
47
54
// Listen to events from the CodeXP service
48
55
val connection = ApplicationManager .getApplication().messageBus.connect()
49
56
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
+
54
81
CodeXPService .Event .values().forEachIndexed { index, event -> // Add ui for each event
55
82
if (event != CodeXPService .Event .NONE ) { // Ignore the NONE event type
56
- constraints.gridy = index
83
+ // Initialize event statistics
84
+ gridBagConstraints.gridy = index
57
85
58
86
val pEvent = JPanel (GridLayout (1 , 3 ))
59
87
pEvent.border = BorderFactory .createEmptyBorder(0 , 16 , 8 , 0 )
60
-
61
88
val lblEventName = JLabel (event.name)
62
89
lblEventName.font = Font (" Noto Sans SemiBold" , Font .PLAIN , 14 )
63
90
lblEventName.border = BorderFactory .createEmptyBorder(0 , 32 , 0 , 0 )
64
-
65
91
val lblEventReward = JLabel (" +" + StringUtil .numberToStringWithCommas(event.xpValue) + " XP" )
66
92
lblEventReward.font = Font (" Noto Sans SemiBold" , Font .PLAIN , 14 )
67
93
lblEventReward.border = BorderFactory .createEmptyBorder(0 , 32 , 0 , 0 )
68
-
69
94
val lblEventCount =
70
95
JLabel (StringUtil .numberToStringWithCommas(codeXPService.state.getEventCount(event)))
71
96
lblEventCount.font = Font (" Noto Sans Medium" , Font .PLAIN , 14 )
@@ -74,46 +99,77 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
74
99
pEvent.add(lblEventName)
75
100
pEvent.add(lblEventReward)
76
101
pEvent.add(lblEventCount)
77
- codeXPDashboard.pEventStatistics.add(pEvent, constraints )
102
+ codeXPDashboard.pEventStatistics.add(pEvent, gridBagConstraints )
78
103
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
80
110
}
81
111
}
82
112
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
+
83
123
// Update the dashboard when events occur
84
124
connection.subscribe(CodeXPListener .CODEXP_EVENT , object : CodeXPListener {
85
125
override fun eventOccurred (event : CodeXPService .Event ) {
86
- (eventStatics [event]!! .getComponent(2 ) as JLabel ).text =
126
+ (eventStaticForms [event]!! .getComponent(2 ) as JLabel ).text =
87
127
StringUtil .numberToStringWithCommas(codeXPService.state.getEventCount(event))
88
- updateXPInfo(codeXPService, codeXPDashboard)
89
- }
90
- })
91
128
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]!!
97
131
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
+ }
101
143
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)
104
150
}
105
151
})
106
152
107
153
updateXPInfo(codeXPService, codeXPDashboard)
108
154
}
109
155
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
+
110
166
/* *
111
167
* Updates the XP info on the dashboard.
112
168
*
113
- * @param codeXPService The CodeXP service.
114
- * @param codeXPDashboard The CodeXP dashboard.
169
+ * @param codeXPService CodeXP service.
170
+ * @param codeXPDashboard CodeXP dashboard.
115
171
*/
116
- fun updateXPInfo (codeXPService : CodeXPService , codeXPDashboard : CodeXPDashboard ) {
172
+ private fun updateXPInfo (codeXPService : CodeXPService , codeXPDashboard : CodeXPDashboard ) {
117
173
val totalXP = codeXPService.state.xp
118
174
codeXPDashboard.lblTotalXP.text = StringUtil .numberToStringWithCommas(totalXP)
119
175
val (currentLevel, xpIntoCurrentLevel, progressToNextLevel) = calculateLevelAndProgress(
@@ -128,6 +184,66 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
128
184
codeXPDashboard.lblLevel.text = StringUtil .numberToStringWithCommas(currentLevel.toLong())
129
185
}
130
186
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
+
131
247
/* *
132
248
* Level info data class.
133
249
*/
@@ -151,10 +267,10 @@ class CodeXPToolWindowFactory : ToolWindowFactory {
151
267
/* *
152
268
* Calculates the level and progress to the next level.
153
269
*
154
- * @param totalXP The total XP.
155
- * @return The level info.
270
+ * @param totalXP Total XP.
271
+ * @return Level info data class .
156
272
*/
157
- fun calculateLevelAndProgress (totalXP : Long ): LevelInfo {
273
+ private fun calculateLevelAndProgress (totalXP : Long ): LevelInfo {
158
274
var level = 1
159
275
var currentLevelXP = 300.0
160
276
var xp = 300.0
0 commit comments