Skip to content

Commit a26fb12

Browse files
authored
add file preview in main dialog (#69)
1 parent 2f48f43 commit a26fb12

11 files changed

Lines changed: 417 additions & 127 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Module Maker Changelog
22

3+
## [1.0.23]
4+
- Add file preview
5+
36
## [1.0.22]
47
- Don't specify pluginUntilBuild. This plugin will work forever ;)
58

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pluginGroup = com.joetr.modulemaker
44
pluginName = ModuleMaker
55
pluginRepositoryUrl = https://github.com/j-roskopf/ModuleMakerPlugin
66
# SemVer format -> https://semver.org
7-
pluginVersion = 1.0.22
7+
pluginVersion = 1.0.23
88

99
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
1010
pluginSinceBuild = 222

src/main/kotlin/com/joetr/modulemaker/ModuleMakerDialogWrapper.kt

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,19 @@ class ModuleMakerDialogWrapper(
158158
"Cancel",
159159
2
160160
),
161+
object : AbstractAction("Preview") {
162+
override fun actionPerformed(e: ActionEvent?) {
163+
if (validateInput()) {
164+
displayPreviewDialog()
165+
} else {
166+
MessageDialogWrapper("Please fill out required values").show()
167+
}
168+
}
169+
},
161170
object : AbstractAction("Create") {
162171
override fun actionPerformed(e: ActionEvent?) {
163172
if (validateInput()) {
164-
create()
173+
create(previewMode = false)
165174
} else {
166175
MessageDialogWrapper("Please fill out required values").show()
167176
}
@@ -170,6 +179,11 @@ class ModuleMakerDialogWrapper(
170179
)
171180
}
172181

182+
private fun displayPreviewDialog() {
183+
val filesToBeCreated = create(previewMode = true)
184+
PreviewDialogWrapper(filesToBeCreated = filesToBeCreated, root = rootFromPath(rootDirectoryString())).show()
185+
}
186+
173187
private fun validateInput(): Boolean {
174188
return packageName.value.isNotEmpty() && selectedSrcValue.value != DEFAULT_SRC_VALUE && moduleName.value.isNotEmpty() && moduleName.value != DEFAULT_MODULE_NAME
175189
}
@@ -359,7 +373,7 @@ class ModuleMakerDialogWrapper(
359373
}
360374
}
361375

362-
private fun create() {
376+
private fun create(previewMode: Boolean): List<File> {
363377
val settingsGradleFile = getSettingsGradleFile()
364378
val moduleType = moduleTypeSelection.value
365379
val currentlySelectedFile = getCurrentlySelectedFile()
@@ -375,7 +389,7 @@ class ModuleMakerDialogWrapper(
375389
useKts = useKtsExtension.value
376390
)
377391
)
378-
fileWriter.createModule(
392+
val filesCreated = fileWriter.createModule(
379393
// at this point, selectedSrcValue has a value of something like /root/module/module2/
380394
// - we want to remove the root of the project to use as the file path in settings.gradle
381395
rootPathString = removeRootFromPath(selectedSrcValue.value),
@@ -403,10 +417,14 @@ class ModuleMakerDialogWrapper(
403417
gradleFileFollowModule = gradleFileNamedAfterModule.value,
404418
packageName = packageName.value,
405419
addReadme = addReadme.value,
406-
addGitIgnore = addGitIgnore.value
420+
addGitIgnore = addGitIgnore.value,
421+
previewMode = previewMode
407422
)
423+
424+
return filesCreated
408425
} else {
409426
MessageDialogWrapper("Couldn't find settings.gradle(.kts)").show()
427+
return emptyList()
410428
}
411429
}
412430

@@ -451,4 +469,8 @@ class ModuleMakerDialogWrapper(
451469
private fun removeRootFromPath(path: String): String {
452470
return path.split(File.separator).drop(1).joinToString(File.separator)
453471
}
472+
473+
private fun rootFromPath(path: String): String {
474+
return path.split(File.separator).last()
475+
}
454476
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyrightest (c) 2024 Joseph Roskopf
3+
*/
4+
5+
package com.joetr.modulemaker
6+
7+
import androidx.compose.foundation.layout.height
8+
import androidx.compose.foundation.layout.width
9+
import androidx.compose.material.Surface
10+
import androidx.compose.runtime.Composable
11+
import androidx.compose.runtime.mutableStateOf
12+
import androidx.compose.runtime.remember
13+
import androidx.compose.ui.Modifier
14+
import androidx.compose.ui.awt.ComposePanel
15+
import androidx.compose.ui.unit.dp
16+
import com.intellij.openapi.ui.DialogWrapper
17+
import com.intellij.openapi.util.io.FileUtilRt
18+
import com.joetr.modulemaker.data.toProjectFile
19+
import com.joetr.modulemaker.ui.file.FileTree
20+
import com.joetr.modulemaker.ui.file.FileTreeView
21+
import com.joetr.modulemaker.ui.theme.WidgetTheme
22+
import java.io.File
23+
import javax.swing.Action
24+
import javax.swing.JComponent
25+
26+
private const val WINDOW_WIDTH = 400
27+
private const val WINDOW_HEIGHT = 600
28+
29+
class PreviewDialogWrapper(val filesToBeCreated: List<File>, val root: String) : DialogWrapper(true) {
30+
31+
private var tempRoot: File
32+
33+
init {
34+
title = "Preview"
35+
init()
36+
37+
tempRoot = FileUtilRt.createTempDirectory(root, null, true)
38+
39+
createFileStructure(
40+
tempRoot,
41+
filesToBeCreated.map {
42+
val pathToRoot = tempRoot.absolutePath
43+
val split = it.absolutePath.split(root)
44+
45+
// splice together the files to have a root of our temp folder
46+
File(pathToRoot, split.drop(1).joinToString(separator = ""))
47+
}
48+
)
49+
}
50+
51+
override fun dispose() {
52+
super.dispose()
53+
tempRoot.parentFile.deleteRecursively()
54+
}
55+
56+
override fun createCenterPanel(): JComponent {
57+
return ComposePanel().apply {
58+
setBounds(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)
59+
setContent {
60+
WidgetTheme {
61+
Surface {
62+
FileTreeJPanel(
63+
modifier = Modifier.height(WINDOW_HEIGHT.dp).width(WINDOW_WIDTH.dp)
64+
)
65+
}
66+
}
67+
}
68+
}
69+
}
70+
71+
@Composable
72+
private fun FileTreeJPanel(
73+
modifier: Modifier = Modifier
74+
) {
75+
val height = remember { mutableStateOf(WINDOW_HEIGHT) }
76+
77+
FileTreeView(
78+
modifier = modifier,
79+
model = FileTree(root = tempRoot.toProjectFile()),
80+
height = height.value.dp,
81+
onClick = { }
82+
)
83+
}
84+
85+
private fun List<File>.root(): File {
86+
return this.minBy { file ->
87+
file.absolutePath.count { it.toString() == File.separator }
88+
}
89+
}
90+
91+
private fun createFileStructure(root: File, structure: List<File>) {
92+
root.mkdirs()
93+
structure.forEach {
94+
it.mkdirs()
95+
if (it.isDirectory.not() && it.extension.isEmpty().not()) {
96+
it.writeText("")
97+
}
98+
}
99+
}
100+
101+
override fun createActions(): Array<Action> {
102+
return arrayOf(
103+
DialogWrapperExitAction(
104+
"Okay",
105+
2
106+
)
107+
)
108+
}
109+
}

0 commit comments

Comments
 (0)