Files
pit/pit-swing/griffon-app/controllers/com/jdbernard/pit/swing/ProjectPanelController.groovy
2011-05-27 10:25:57 -05:00

223 lines
7.3 KiB
Groovy
Executable File

package com.jdbernard.pit.swing
import com.jdbernard.pit.Category
import com.jdbernard.pit.FileProject
import com.jdbernard.pit.FlatProjectView
import com.jdbernard.pit.Issue
import com.jdbernard.pit.Project
import com.jdbernard.pit.Status
import javax.swing.DefaultListModel
import javax.swing.JOptionPane
import javax.swing.tree.DefaultMutableTreeNode
import javax.swing.tree.DefaultTreeModel
import org.dom4j.Document
import org.dom4j.io.OutputFormat
import org.dom4j.io.XMLWriter
import org.nuiton.jrst.JRSTGenerator
import org.nuiton.jrst.JRSTReader
class ProjectPanelController {
// these will be injected by Griffon
def model
def view
def jrstReader
def jrstGen
static URL rst2htmlXSL =
ProjectPanelController.class.getResource("/rst2xhtml.xsl")
void mvcGroupInit(Map args) {
jrstReader = new JRSTReader()
jrstGen = new JRSTGenerator()
refreshProject()
}
/**
* displayProject
* @param project Project to display
*/
void displayProject(Project project) {
if (!project) return
view.issueTextArea.text = ""
view.issueTextDisplay.text = ""
view.issueTextPanelLayout.show(view.issueTextPanel, 'display')
// build a new IssueTableModel if none cached
if (!model.projectTableModels[(project.name)]) {
def itm = new IssueTableModel(project,
model.filter ?: model.mainMVC.model.filter)
itm.categoryIcons = model.mainMVC.model.categoryIcons
itm.statusIcons = model.mainMVC.model.statusIcons
model.projectTableModels[(project.name)] = itm
}
view.issueTable.setModel(model.projectTableModels[(project.name)])
def tcm = view.issueTable.columnModel
tcm.getColumn(0).maxWidth = 24
tcm.getColumn(1).maxWidth = 40
tcm.getColumn(2).maxWidth = 35
if (view.issueTable.model.columnCount == 5)
tcm.getColumn(4).maxWidth = 150
}
void displayIssue(Issue issue) {
if (!issue) return
// hack because binding view.issueTextArea.font to
// mainMVC.model.issueDetailFont causes problems
if (view.issueTextArea.font != model.mainMVC.model.issueDetailFont)
view.issueTextArea.font = model.mainMVC.model.issueDetailFont
view.issueTextArea.text = issue.text
view.issueTextArea.caretPosition = 0
view.issueTextDisplay.text = rst2html(issue.text)
view.issueTextDisplay.caretPosition = 0
view.issueTextPanelLayout.show(view.issueTextPanel, 'display')
}
void showProejctPopup(Project project, def x, def y) {
model.popupProject = project
view.projectPopupMenu.show(view.projectTree, x, y)
}
void showIssuePopup(Issue issue, def x, def y) {
model.popupIssue = issue
view.issuePopupMenu.show(view.issueTable, x, y)
}
void refreshProject() {
if (model.rootProject) {
def rootNode = new DefaultMutableTreeNode()
def flatview = new FlatProjectView('All Issues')
flatview.projects[(model.rootProject.name)] = model.rootProject
rootNode.add(new DefaultMutableTreeNode(flatview))
rootNode.add(makeNodes(model.rootProject))
view.projectTree.model = new DefaultTreeModel(rootNode)
} else {
view.projectTree.model = new DefaultTreeModel(
new DefaultMutableTreeNode())
}
}
void refreshIssues() {
model.projectTableModels.clear()
displayProject(model.selectedProject)
}
def makeNodes(Project project) {
def rootNode = new DefaultMutableTreeNode(project)
project.eachProject(model.filter ?: model.mainMVC.model.filter)
{ rootNode.add(makeNodes(it)) }
return rootNode
}
def newProject = { evt ->
def name = JOptionPane.showInputDialog(model.mainMVC.view.frame,
'Project name:', 'New Project...', JOptionPane.QUESTION_MESSAGE)
def project
if (evt.source == view.newProjectButton)
project = model.selectedProject ?: model.rootProject
else project = model.popupProject ?: model.rootProject
def newProject = project.createNewProject(name)
project.projects[(newProject.name)] = newProject
refreshProject()
}
def deleteProject = { evt ->
def project
if (evt.source == view.deleteProjectButton)
project = model.selectedProject ?: model.rootProject
else project = model.popupProject ?: model.rootProject
project.delete()
model.rootProject = new FileProject(model.rootProject.source)
}
def newIssue = { evt = null ->
model.newIssueDialogMVC.controller.show()
if (model.newIssueDialogMVC.model.accept) {
def nidModel = model.newIssueDialogMVC.model
def issueText = nidModel.text
if (model.mainMVC.model.templates[(nidModel.category)]) {
issueText = model.mainMVC.model.templates[(nidModel.category)]
issueText = issueText.replaceFirst(/TITLE/,
nidModel.text)
}
def issue = model.selectedProject.createNewIssue(
category: nidModel.category,
status: nidModel.status,
priority: nidModel.priority,
text: issueText)
model.projectTableModels[(model.selectedProject.name)] = null
displayProject(model.selectedProject)
}
}
def deleteIssue = { evt ->
def issue
if (evt.source == view.deleteIssueButton)
issue = getSelectedIssue()
else issue = model.popupIssue
model.selectedProject.issues.remove(issue.id)
view.issueTable.model.issues.remove(issue)
issue.delete()
view.issueTable.invalidate()
}
def getSelectedIssue() {
if (view.issueTable.selectionModel.isSelectionEmpty())
return null
return view.issueTable.model.issues[view.issueTable.
convertRowIndexToModel(view.issueTable.selectedRow)]
}
String rst2html(String rst) {
Document doc
StringWriter outString
StringBuilder result = new StringBuilder()
// read the RST in with the RST parser
new StringReader(rst).withReader { doc = jrstReader.read(it) }
// transform to XHTML
doc = jrstGen.transform(doc, rst2htmlXSL)
// write to the StringWriter
outString = new StringWriter()
outString.withWriter { new XMLWriter(it, new OutputFormat("", true)).write(doc) }
// java's embeded html is primitive, we need to massage the results
outString.toString().eachLine { line ->
// remove the XML version and encoding, title element, meta elems
if (line =~ /<\?.*\?>/ || line =~ /<meta.*$/ || line =~ /<title.*$/) { return }
// all other elements, remove all class, xmlns attributes
def m = (line =~ /(<\S+)(\s*(class|xmlns)=".*"\s*)*(\/?>.*)/)
if (m) line = m[0][1] + m[0][4]
result.append(line)
// add in the CSS information to the head
if (line =~ /<head>/) result.append('<style type="text/css">' +
model.issueCSS + '</style>')
}
return result.toString()
}
}