Small enhancements to libpit to facilitate pit-swing.

Added delete() and createNewProject(String) to Project class.
Added nicer toString() method to Category enum.
This commit is contained in:
Jonathan Bernard
2010-02-24 03:05:37 -06:00
parent 45516a5cd9
commit 60109087e5
11 changed files with 145 additions and 34 deletions

View File

@ -1,11 +1,15 @@
package com.jdbernard.pit.swing
import com.jdbernard.pit.Category
import com.jdbernard.pit.Filter
import com.jdbernard.pit.Issue
import com.jdbernard.pit.Project
import com.jdbernard.pit.FileProject
import groovy.beans.Bindable
import java.awt.event.MouseEvent
import javax.swing.DefaultListModel
import javax.swing.JFileChooser
import javax.swing.JOptionPane
import javax.swing.JSplitPane
import javax.swing.ListSelectionModel
import javax.swing.tree.DefaultMutableTreeNode
@ -14,34 +18,78 @@ import javax.swing.tree.DefaultTreeModel
import javax.swing.tree.TreeSelectionModel
import net.miginfocom.swing.MigLayout
// VIEW-Specific data
/* ********************
* VIEW-Specific data
* ********************/
// cache the ListModels
projectListModels = [:]
categoryIcons = [(Category.BUG): imageIcon('/bug.png'),
(Category.CLOSED): imageIcon('/closed.png'),
(Category.FEATURE): imageIcon('/feature.png'),
(Category.TASK): imageIcon('/task.png')]
// map of category -> list icon
categoryIcons = [:]
openDialog = fileChooser(fileSelectionMode: JFileChooser.DIRECTORIES_ONLY)
// filter for projects and issues
filter = new Filter(categories: [])
// event methods
displayProject = { evt = null ->
def project= evt?.newLeadSelectionPath?.lastPathComponent?.userObject
@Bindable def popupProject = null
// initialize category-related view data
Category.values().each {
categoryIcons[(it)] = imageIcon("/${it.name().toLowerCase()}.png")
filter.categories.add(it)
}
/* ***************
* event methods
* ***************/
/**
* displayProject
* @param project Project to display.
*
*/
displayProject = { project = null ->
issueTextArea.text = ""
if (!project) return
if (!projectListModels[(project.name)]) {
def model = new DefaultListModel()
project.eachIssue { model.addElement(it) }
project.eachIssue(filter) { model.addElement(it) }
projectListModels[(project.name)] = model
}
issueList.setModel(projectListModels[(project.name)])
}
displayIssue = { evt = null ->
if (issueList.selectedValue)
issueTextArea.text = issueList.selectedValue.text
displayIssue = { issue = null ->
if (issue) issueTextArea.text = issue.text
}
showProjectPopup = { project, x, y ->
popupProject = project
projectPopupMenu[1].enabled = project != null
projectPopupMenu.show(projectTree, x, y)
}
/* ****************
* GUI components
* ****************/
openDialog = fileChooser(fileSelectionMode: JFileChooser.DIRECTORIES_ONLY)
projectPopupMenu = popupMenu() {
menuItem('New Project...',
actionPerformed: {
def name = JOptionPane.showInputDialog(frame, 'Project name:',
'New Project...', JOptionPane.QUESTION_MESSAGE)
if (!popupProject) popupProject = model.rootProject
def newProject = popupProject.createNewProject(name)
projectTree.model = new DefaultTreeModel(
makeNodes(model.rootProject))
})
menuItem('Delete Project',
actionPerformed: { popupProject.delete() })
}
frame = application(title:'Personal Issue Tracker',
@ -69,6 +117,29 @@ frame = application(title:'Personal Issue Tracker',
projectDir = openDialog.selectedFile
model.rootProject = new FileProject(projectDir)
})
menuItem('Exit', actionPerformed: { app.shutdown() })
}
menu('View') {
Category.values().each {
checkBoxMenuItem(it.toString(),
selected: filter.categories.contains(it),
actionPerformed: { evt ->
def cat = Category.toCategory(evt.source.text)
if (filter.categories.contains(cat)) {
filter.categories.remove(cat)
evt.source.selected = false
} else {
filter.categories.add(cat)
evt.source.selected = true
}
projectListModels.clear()
displayProject(projectTree.leadSelectionPath
?.lastPathComponent?.userObject)
})
}
}
}
@ -89,7 +160,19 @@ frame = application(title:'Personal Issue Tracker',
new DefaultTreeModel(makeNodes(model.rootProject))
} else new DefaultTreeModel()
}),
valueChanged: displayProject)
valueChanged: { evt ->
displayProject(evt?.newLeadSelectionPath
?.lastPathComponent?.userObject)
},
mouseClicked: { evt ->
if (evt.button == MouseEvent.BUTTON3) {
showProjectPopup(
projectTree.getPathForLocation(evt.x, evt.y)
?.lastPathComponent?.userObject,
evt.x, evt.y)
}
})
projectTree.selectionModel.selectionMode =
TreeSelectionModel.SINGLE_TREE_SELECTION
}
@ -103,7 +186,7 @@ frame = application(title:'Personal Issue Tracker',
cellRenderer: new IssueListCellRenderer(
issueIcons: categoryIcons),
selectionMode: ListSelectionModel.SINGLE_SELECTION,
valueChanged: displayIssue)
valueChanged: { displayIssue(issueList.selectedValue) })
}
scrollPane(constraints: "bottom") {
issueTextArea = textArea()
@ -112,8 +195,11 @@ frame = application(title:'Personal Issue Tracker',
}
}
/* ******************
* Auxilary methods
* ******************/
def makeNodes(Project project) {
def rootNode = new DefaultMutableTreeNode(project)
project.eachProject { rootNode.add(makeNodes(it)) }
project.eachProject(filter) { rootNode.add(makeNodes(it)) }
return rootNode
}