Skip to content

Commit 9c3adbe

Browse files
committed
Refactor tree handling and improve drag-and-drop logic
Added methods to handle category nodes more cleanly and avoid duplicate creation. Improved the drag-and-drop functionality by preserving empty categories and ensuring consistent node insertion logic. Simplified and reorganized related code for better readability and maintainability.
1 parent cb14315 commit 9c3adbe

File tree

1 file changed

+49
-34
lines changed

1 file changed

+49
-34
lines changed

src/main/kotlin/dev/meanmail/prettifypython/settings/PrettifySettingsComponent.kt

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ import javax.swing.filechooser.FileNameExtensionFilter
3030
import javax.swing.tree.*
3131

3232
class PrettifySettingsComponent {
33-
private val mainPanel: JPanel
3433
private val rootNode = DefaultMutableTreeNode("Mappings")
35-
private val treeModel = DefaultTreeModel(rootNode)
34+
private val treeModel = MappingTreeModel(rootNode)
3635
private val mappingsTree = Tree(treeModel).apply {
3736
isRootVisible = false
3837
showsRootHandles = true
@@ -53,8 +52,7 @@ class PrettifySettingsComponent {
5352
}
5453
private val json = Json { prettyPrint = true }
5554
private var resetButton: AnAction? = null
56-
57-
init {
55+
private val mainPanel = JPanel(BorderLayout()).apply {
5856
val toolbarDecorator = ToolbarDecorator.createDecorator(mappingsTree)
5957
.setAddAction { addNewMapping() }
6058
.setRemoveAction { removeSelectedMapping() }
@@ -81,9 +79,14 @@ class PrettifySettingsComponent {
8179
}
8280
}.also { resetButton = it })
8381

84-
mainPanel = JPanel(BorderLayout()).apply {
85-
add(toolbarDecorator.createPanel(), BorderLayout.CENTER)
86-
border = IdeBorderFactory.createTitledBorder("Symbol Mappings", false)
82+
add(toolbarDecorator.createPanel(), BorderLayout.CENTER)
83+
border = IdeBorderFactory.createTitledBorder("Symbol Mappings", false)
84+
}
85+
86+
private inner class MappingTreeModel(root: TreeNode) : DefaultTreeModel(root) {
87+
override fun isLeaf(node: Any?): Boolean {
88+
if (node !is DefaultMutableTreeNode) return true
89+
return node.userObject is MappingEntry
8790
}
8891
}
8992

@@ -116,29 +119,32 @@ class PrettifySettingsComponent {
116119

117120
private fun addMappingToTree(mapping: MappingEntry) {
118121
// Find or create category node
119-
var categoryNode = findOrCreateCategoryNode(mapping.category)
122+
val categoryNode = findOrCreateCategoryNode(mapping.category)
120123
val mappingNode = DefaultMutableTreeNode(mapping)
121124
treeModel.insertNodeInto(mappingNode, categoryNode, categoryNode.childCount)
122125
expandAllNodes()
123126
}
124127

125128
private fun findOrCreateCategoryNode(category: String): DefaultMutableTreeNode {
129+
// Search for existing category node
126130
for (i in 0 until rootNode.childCount) {
127131
val node = rootNode.getChildAt(i) as DefaultMutableTreeNode
128132
if (node.userObject.toString() == category) {
129133
return node
130134
}
131135
}
132-
val newNode = DefaultMutableTreeNode(category)
133-
treeModel.insertNodeInto(newNode, rootNode, rootNode.childCount)
134-
return newNode
136+
137+
// Create new category node if not found
138+
val categoryNode = DefaultMutableTreeNode(category)
139+
treeModel.insertNodeInto(categoryNode, rootNode, rootNode.childCount)
140+
return categoryNode
135141
}
136142

137143
private fun removeSelectedMapping() {
138-
val node = mappingsTree.lastSelectedPathComponent as? DefaultMutableTreeNode ?: return
139-
if (node.userObject is MappingEntry) {
140-
treeModel.removeNodeFromParent(node)
141-
}
144+
val selectedNode = mappingsTree.selectionPath?.lastPathComponent as? DefaultMutableTreeNode ?: return
145+
if (selectedNode.userObject !is MappingEntry) return
146+
147+
treeModel.removeNodeFromParent(selectedNode)
142148
}
143149

144150
private class MappingTransferable(private val mapping: MappingEntry) : Transferable {
@@ -157,6 +163,13 @@ class PrettifySettingsComponent {
157163
private inner class MappingTransferHandler(private val tree: JTree) : TransferHandler() {
158164
override fun getSourceActions(c: JComponent): Int = TransferHandler.MOVE
159165

166+
override fun createTransferable(component: JComponent): Transferable? {
167+
val node = tree.selectionPath?.lastPathComponent as? DefaultMutableTreeNode ?: return null
168+
if (node.userObject !is MappingEntry) return null
169+
170+
return MappingTransferable(node.userObject as MappingEntry)
171+
}
172+
160173
override fun canImport(support: TransferSupport): Boolean {
161174
if (!support.isDrop) return false
162175
support.setShowDropLocation(true)
@@ -166,15 +179,8 @@ class PrettifySettingsComponent {
166179
val targetPath = dropLocation.path ?: return false
167180
val targetNode = targetPath.lastPathComponent as DefaultMutableTreeNode
168181

169-
// Allow dropping only on root or category nodes
170-
return targetNode == rootNode || targetNode.parent == rootNode
171-
}
172-
173-
override fun createTransferable(component: JComponent): Transferable? {
174-
val node = tree.selectionPath?.lastPathComponent as? DefaultMutableTreeNode ?: return null
175-
if (node.userObject !is MappingEntry) return null
176-
177-
return MappingTransferable(node.userObject as MappingEntry)
182+
// Allow dropping only on category nodes (not root)
183+
return targetNode.parent == rootNode
178184
}
179185

180186
override fun importData(support: TransferSupport): Boolean {
@@ -183,24 +189,33 @@ class PrettifySettingsComponent {
183189
val dropLocation = support.getDropLocation() as? JTree.DropLocation ?: return false
184190
val targetPath = dropLocation.path ?: return false
185191
val targetNode = targetPath.lastPathComponent as DefaultMutableTreeNode
192+
val childIndex = dropLocation.childIndex
186193

187194
val draggedNode = tree.selectionPath?.lastPathComponent as? DefaultMutableTreeNode ?: return false
188195
val draggedMapping = draggedNode.userObject as? MappingEntry ?: return false
189196

190-
// Determine target category
191-
val targetCategory = when {
192-
targetNode == rootNode -> draggedMapping.category
193-
targetNode.parent == rootNode -> targetNode.userObject.toString()
194-
else -> return false
195-
}
196-
197-
treeModel.removeNodeFromParent(draggedNode)
197+
// Target category is always the category we're dropping on
198+
val targetCategory = targetNode.userObject.toString()
198199

199200
// Create new mapping with target category
200201
val newMapping = draggedMapping.copy(category = targetCategory)
201202

202-
// Add to target category
203-
addMappingToTree(newMapping)
203+
// Calculate insert index
204+
val insertIndex = if (childIndex >= 0) childIndex else targetNode.childCount
205+
206+
// Create and insert the new node
207+
val newMappingNode = DefaultMutableTreeNode(newMapping)
208+
209+
// First insert the new node
210+
treeModel.insertNodeInto(newMappingNode, targetNode, insertIndex)
211+
212+
// Then remove the old node
213+
treeModel.removeNodeFromParent(draggedNode)
214+
215+
// Make sure the new node is visible
216+
val newPath = TreePath(newMappingNode.path)
217+
tree.scrollPathToVisible(newPath)
218+
tree.selectionPath = newPath
204219

205220
expandAllNodes()
206221
return true

0 commit comments

Comments
 (0)