Skip to content

Commit 337150d

Browse files
committed
Merge branch 'feature/create-core' into develop
- Add CodeXP plugin core logic - Add CodeXPService class for manage challenges and plugin - Add CodeXPChallenge class for challenge data - Remove unnecessary codes and change class names using CodeXP - Add CodeXPEventListener to catch document, frame, editor events
2 parents 58c858e + 21a75ea commit 337150d

File tree

10 files changed

+277
-56
lines changed

10 files changed

+277
-56
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.github.ilovegamecoding.intellijcodexp.listeners
2+
3+
import com.github.ilovegamecoding.intellijcodexp.services.CodeXPService
4+
import com.github.ilovegamecoding.intellijcodexp.model.CodeXPChallenge
5+
import com.intellij.ide.FrameStateListener
6+
import com.intellij.openapi.components.service
7+
import com.intellij.openapi.diagnostic.thisLogger
8+
import com.intellij.openapi.editor.EditorFactory
9+
import com.intellij.openapi.editor.event.DocumentEvent
10+
import com.intellij.openapi.editor.event.DocumentListener
11+
import com.intellij.openapi.editor.event.EditorFactoryEvent
12+
import com.intellij.openapi.editor.event.EditorFactoryListener
13+
14+
internal class CodeXPEventListener : DocumentListener, EditorFactoryListener, FrameStateListener {
15+
private val codeXPService = service<CodeXPService>()
16+
17+
init {
18+
val editorFactory = EditorFactory.getInstance()
19+
for (editor in editorFactory.allEditors) {
20+
editor.document.addDocumentListener(this)
21+
}
22+
editorFactory.addEditorFactoryListener(this) { }
23+
}
24+
25+
override fun documentChanged(event: DocumentEvent) {
26+
super.documentChanged(event)
27+
thisLogger().warn("CodeXPEventListener.documentChanged")
28+
codeXPService.increaseChallengeValue(CodeXPChallenge.Type.TYPING_COUNT, 1)
29+
}
30+
31+
override fun editorCreated(event: EditorFactoryEvent) {
32+
event.editor.document.addDocumentListener(this)
33+
}
34+
35+
override fun onFrameActivated() {
36+
37+
}
38+
}

src/main/kotlin/com/github/ilovegamecoding/intellijcodexp/listeners/MyFrameStateListener.kt

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.github.ilovegamecoding.intellijcodexp.model
2+
3+
/**
4+
* CodeXPChallenge class
5+
* CodeXPChallenge is a class that represents a challenge. Challenges are used to track the progress of the user.
6+
*
7+
* @constructor Create empty CodeXPChallenge.
8+
*/
9+
class CodeXPChallenge() {
10+
/**
11+
* Type of challenge.
12+
*/
13+
var type: Int = -1
14+
15+
/**
16+
* Name of challenge.
17+
*/
18+
var name: String = ""
19+
20+
/**
21+
* Description of challenge.
22+
*/
23+
var description: String = ""
24+
25+
/**
26+
* Reward XP of challenge when completed.
27+
*/
28+
var rewardXP: Long = 0L
29+
30+
/**
31+
* Current value of challenge.
32+
*/
33+
var value: Long = 0L
34+
35+
/**
36+
* Goal of challenge.
37+
*/
38+
var goal: Long = 0L
39+
40+
/**
41+
* Constructor for CodeXPChallenge with all parameters.
42+
*/
43+
constructor(
44+
type: Int,
45+
name: String,
46+
description: String,
47+
rewardXP: Long,
48+
value: Long,
49+
goal: Long
50+
) : this() {
51+
this.type = type
52+
this.name = name
53+
this.description = description
54+
this.rewardXP = rewardXP
55+
this.value = value
56+
this.goal = goal
57+
}
58+
59+
/**
60+
* Type of challenge.
61+
*
62+
* !! Do not ever change the order of the enum values. If you want to add a new challenge type, add it to the end of the enum !!
63+
*/
64+
enum class Type {
65+
TOTAL_XP,
66+
ACTION_COUNT,
67+
BUILD_COUNT,
68+
DEBUG_COUNT,
69+
RUN_COUNT,
70+
COMMIT_COUNT,
71+
PUSH_COUNT,
72+
MERGE_COUNT,
73+
PULL_COUNT,
74+
TYPING_COUNT,
75+
}
76+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package com.github.ilovegamecoding.intellijcodexp.services
2+
3+
import com.github.ilovegamecoding.intellijcodexp.model.CodeXPChallenge
4+
import com.intellij.openapi.components.*
5+
import com.intellij.util.xmlb.XmlSerializerUtil
6+
7+
/**
8+
* CodeXPService class
9+
*
10+
* This is the main class for the plugin. It manages the state of the plugin, including challenges, user progress, and more.
11+
* All data stored in the plugin is contained within this class.
12+
*/
13+
@Service(Service.Level.APP)
14+
@State(
15+
name = "com.github.ilovegamecoding.intellijcodexp.services.CodeXP",
16+
storages = [Storage("CodeXP.xml")]
17+
)
18+
class CodeXPService : PersistentStateComponent<CodeXPService> {
19+
/**
20+
* All current challenges yet to be completed.
21+
*/
22+
var challenges = mutableMapOf<Int, CodeXPChallenge>()
23+
24+
/**
25+
* All completed challenges.
26+
*/
27+
var completedChallenges = mutableMapOf<Int, CodeXPChallenge>()
28+
29+
/**
30+
* Plugin has been executed before.
31+
*/
32+
var hasExecuted: Boolean = false
33+
34+
/**
35+
* Nickname of the user.
36+
*/
37+
var nickname: String = ""
38+
39+
override fun getState(): CodeXPService {
40+
return this
41+
}
42+
43+
override fun loadState(state: CodeXPService) {
44+
XmlSerializerUtil.copyBean(state, this)
45+
}
46+
47+
/**
48+
* Reset the plugin.
49+
*/
50+
fun resetPlugin() {
51+
challenges.clear()
52+
completedChallenges.clear()
53+
hasExecuted = false
54+
nickname = ""
55+
}
56+
57+
/**
58+
* Executes a given lambda function only if the plugin has not been executed before.
59+
*
60+
* @param challenges Challenges to add to the plugin.
61+
*/
62+
fun initializePlugin(challenges: List<CodeXPChallenge>) {
63+
if (!hasExecuted) {
64+
// TODO: Add logic to execute only once
65+
66+
hasExecuted = true
67+
}
68+
69+
challenges.forEach(this::addChallenge)
70+
}
71+
72+
/**
73+
* Add a challenge to the plugin.
74+
*
75+
* @param challenge The challenge to add.
76+
*/
77+
fun addChallenge(challenge: CodeXPChallenge) {
78+
if (challenges.containsKey(challenge.type) || completedChallenges.containsKey(challenge.type)) return
79+
challenges[challenge.type] = challenge
80+
}
81+
82+
/**
83+
* Increase the value of a challenge.
84+
*
85+
* @param type The type of the challenge.
86+
* @param amount The amount to increase the challenge value by.
87+
*/
88+
fun increaseChallengeValue(type: CodeXPChallenge.Type, amount: Int) {
89+
val challenge = challenges[type.ordinal] ?: return
90+
91+
challenge.value += amount
92+
if (challenge.value >= challenge.goal) { // If challenge is completed
93+
challenges.remove(challenge.type)
94+
completedChallenges[challenge.type] = challenge
95+
}
96+
}
97+
}

src/main/kotlin/com/github/ilovegamecoding/intellijcodexp/services/MyProjectService.kt

Lines changed: 0 additions & 17 deletions
This file was deleted.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.github.ilovegamecoding.intellijcodexp.startup
2+
3+
import com.github.ilovegamecoding.intellijcodexp.model.CodeXPChallenge
4+
import com.github.ilovegamecoding.intellijcodexp.services.CodeXPService
5+
import com.intellij.openapi.components.service
6+
import com.intellij.openapi.project.Project
7+
import com.intellij.openapi.startup.StartupActivity
8+
9+
/**
10+
* CodeXPStartupActivity class
11+
*
12+
* This class is used to initialize the plugin when the IDE starts.
13+
*/
14+
class CodeXPStartupActivity : StartupActivity {
15+
override fun runActivity(project: Project) {
16+
with(service<CodeXPService>()) {
17+
initializePlugin(
18+
listOf(
19+
CodeXPChallenge(
20+
type = CodeXPChallenge.Type.TYPING_COUNT.ordinal,
21+
name = "Typing",
22+
description = "Just type anything. We will give you XP for it.",
23+
rewardXP = 100,
24+
value = 0,
25+
goal = 10
26+
),
27+
CodeXPChallenge(
28+
type = CodeXPChallenge.Type.ACTION_COUNT.ordinal,
29+
name = "Action",
30+
description = "Just do anything. We will give you XP for it.",
31+
rewardXP = 100,
32+
value = 0,
33+
goal = 10
34+
)
35+
)
36+
)
37+
}
38+
}
39+
}
Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
package com.github.ilovegamecoding.intellijcodexp.toolWindow
22

3+
import com.github.ilovegamecoding.intellijcodexp.services.CodeXPService
34
import com.intellij.openapi.components.service
45
import com.intellij.openapi.diagnostic.thisLogger
56
import com.intellij.openapi.project.Project
67
import com.intellij.openapi.wm.ToolWindow
78
import com.intellij.openapi.wm.ToolWindowFactory
8-
import com.intellij.ui.components.JBLabel
99
import com.intellij.ui.components.JBPanel
1010
import com.intellij.ui.content.ContentFactory
11-
import com.github.ilovegamecoding.intellijcodexp.MyBundle
12-
import com.github.ilovegamecoding.intellijcodexp.services.MyProjectService
13-
import javax.swing.JButton
1411

1512

16-
class MyToolWindowFactory : ToolWindowFactory {
13+
class CodeXPToolWindowFactory : ToolWindowFactory {
1714

1815
init {
1916
thisLogger().warn("Don't forget to remove all non-needed sample code files with their corresponding registration entries in `plugin.xml`.")
@@ -22,26 +19,22 @@ class MyToolWindowFactory : ToolWindowFactory {
2219
private val contentFactory = ContentFactory.SERVICE.getInstance()
2320

2421
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
25-
val myToolWindow = MyToolWindow(toolWindow)
26-
val content = contentFactory.createContent(myToolWindow.getContent(), null, false)
22+
val codeXPDashboard = CodeXPDashboard()
23+
val content = contentFactory.createContent(codeXPDashboard.getContent(), null, false)
2724
toolWindow.contentManager.addContent(content)
2825
}
2926

3027
override fun shouldBeAvailable(project: Project) = true
3128

32-
class MyToolWindow(toolWindow: ToolWindow) {
29+
class CodeXPDashboard() {
30+
private val service = service<CodeXPService>()
3331

34-
private val service = toolWindow.project.service<MyProjectService>()
32+
init {
33+
34+
}
3535

3636
fun getContent() = JBPanel<JBPanel<*>>().apply {
37-
val label = JBLabel(MyBundle.message("randomLabel", "?"))
38-
39-
add(label)
40-
add(JButton(MyBundle.message("shuffle")).apply {
41-
addActionListener {
42-
label.text = MyBundle.message("randomLabel", service.getRandomNumber())
43-
}
44-
})
37+
// TODO: Implement the UI for this feature
4538
}
4639
}
4740
}

src/main/resources/META-INF/plugin.xml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,21 @@
99
<resource-bundle>messages.MyBundle</resource-bundle>
1010

1111
<extensions defaultExtensionNs="com.intellij">
12-
<toolWindow factoryClass="com.github.ilovegamecoding.intellijcodexp.toolWindow.MyToolWindowFactory" id="MyToolWindow"/>
12+
<toolWindow factoryClass="com.github.ilovegamecoding.intellijcodexp.toolWindow.CodeXPToolWindowFactory"
13+
id="CodeXPToolWindow"/>
14+
<postStartupActivity implementation="com.github.ilovegamecoding.intellijcodexp.startup.CodeXPStartupActivity"/>
15+
<applicationService serviceImplementation="com.github.ilovegamecoding.intellijcodexp.services.CodeXPService"/>
1316
</extensions>
1417

18+
<application-components>
19+
</application-components>
20+
1521
<applicationListeners>
16-
<listener class="com.github.ilovegamecoding.intellijcodexp.listeners.MyFrameStateListener" topic="com.intellij.ide.FrameStateListener"/>
22+
<listener class="com.github.ilovegamecoding.intellijcodexp.listeners.CodeXPEventListener"
23+
topic="com.intellij.ide.FrameStateListener"/>
24+
<listener class="com.github.ilovegamecoding.intellijcodexp.listeners.CodeXPEventListener"
25+
topic="com.intellij.openapi.editor.event.DocumentListener"/>
26+
<listener class="com.github.ilovegamecoding.intellijcodexp.listeners.CodeXPEventListener"
27+
topic="com.intellij.openapi.editor.event.EditorFactoryListener"/>
1728
</applicationListeners>
1829
</idea-plugin>
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
name=My Plugin
2-
projectService=Project service: {0}
3-
randomLabel=The random number is: {0}
4-
shuffle=Shuffle
1+
name=CodeXP

0 commit comments

Comments
 (0)