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:
parent
45516a5cd9
commit
60109087e5
@ -1,10 +1,10 @@
|
||||
#Mon Feb 22 07:08:09 CST 2010
|
||||
#Wed Feb 24 03:03:11 CST 2010
|
||||
build.dir=build
|
||||
src.dir=src
|
||||
lib.shared.dir=../shared-libs
|
||||
test.dir=test
|
||||
build.number=2
|
||||
expected.application.version=1.1.4
|
||||
build.number=4
|
||||
expected.application.version=1.1.5
|
||||
lib.dir=lib
|
||||
release.dir=release
|
||||
release.jar=pit-${application.version}.jar
|
||||
|
Binary file not shown.
BIN
libpit/release/pit-1.1.5.jar
Normal file
BIN
libpit/release/pit-1.1.5.jar
Normal file
Binary file not shown.
@ -43,9 +43,9 @@ badd +1 test/com/jdbernard/pit/IssueTest.groovy
|
||||
badd +6 src/com/jdbernard/pit/Project.groovy
|
||||
badd +1 test/com/jdbernard/pit/ProjectTest.groovy
|
||||
badd +1 src/com/jdbernard/pit/FileIssue.groovy
|
||||
badd +0 test/com/jdbernard/pit/FileIssueTest.groovy
|
||||
badd +1 test/com/jdbernard/pit/FileIssueTest.groovy
|
||||
badd +1 src/com/jdbernard/pit/FileProject.groovy
|
||||
badd +0 test/com/jdbernard/pit/FileProjectTest.groovy
|
||||
badd +1 test/com/jdbernard/pit/FileProjectTest.groovy
|
||||
args build.xml
|
||||
edit build.xml
|
||||
set splitbelow splitright
|
||||
@ -701,12 +701,12 @@ setlocal nowinfixwidth
|
||||
setlocal wrap
|
||||
setlocal wrapmargin=0
|
||||
silent! normal! zE
|
||||
let s:l = 103 - ((26 * winheight(0) + 39) / 78)
|
||||
let s:l = 1 - ((0 * winheight(0) + 39) / 78)
|
||||
if s:l < 1 | let s:l = 1 | endif
|
||||
exe s:l
|
||||
normal! zt
|
||||
103
|
||||
normal! 04l
|
||||
1
|
||||
normal! 0
|
||||
wincmd w
|
||||
exe 'vert 1resize ' . ((&columns * 91 + 91) / 182)
|
||||
exe 'vert 2resize ' . ((&columns * 90 + 91) / 182)
|
||||
@ -1260,12 +1260,12 @@ setlocal nowinfixwidth
|
||||
setlocal wrap
|
||||
setlocal wrapmargin=0
|
||||
silent! normal! zE
|
||||
let s:l = 40 - ((39 * winheight(0) + 39) / 78)
|
||||
let s:l = 1 - ((0 * winheight(0) + 39) / 78)
|
||||
if s:l < 1 | let s:l = 1 | endif
|
||||
exe s:l
|
||||
normal! zt
|
||||
40
|
||||
normal! 029l
|
||||
1
|
||||
normal! 0
|
||||
wincmd w
|
||||
argglobal
|
||||
edit test/com/jdbernard/pit/FileProjectTest.groovy
|
||||
@ -1364,17 +1364,16 @@ setlocal nowinfixwidth
|
||||
setlocal wrap
|
||||
setlocal wrapmargin=0
|
||||
silent! normal! zE
|
||||
let s:l = 154 - ((77 * winheight(0) + 39) / 78)
|
||||
let s:l = 1 - ((0 * winheight(0) + 39) / 78)
|
||||
if s:l < 1 | let s:l = 1 | endif
|
||||
exe s:l
|
||||
normal! zt
|
||||
154
|
||||
1
|
||||
normal! 0
|
||||
wincmd w
|
||||
2wincmd w
|
||||
exe 'vert 1resize ' . ((&columns * 91 + 91) / 182)
|
||||
exe 'vert 2resize ' . ((&columns * 90 + 91) / 182)
|
||||
tabnext 6
|
||||
tabnext 1
|
||||
if exists('s:wipebuf')
|
||||
silent exe 'bwipe ' . s:wipebuf
|
||||
endif
|
||||
|
@ -8,9 +8,11 @@ public enum Category {
|
||||
|
||||
public static Category toCategory(String s) {
|
||||
for(c in Category.values())
|
||||
if (c.toString().startsWith(s.toUpperCase())) return c
|
||||
if (c.name().startsWith(s.toUpperCase())) return c
|
||||
throw new IllegalArgumentException("No category matches ${s}.")
|
||||
}
|
||||
|
||||
public String getSymbol() { toString()[0].toLowerCase() }
|
||||
|
||||
public String toString() { return "${name()[0]}${name()[1..-1].toLowerCase()}" }
|
||||
}
|
||||
|
@ -36,6 +36,11 @@ public class FileIssue extends Issue {
|
||||
|
||||
public String getFilename() { return makeFilename(id, category, priority) }
|
||||
|
||||
public void setText(String text) {
|
||||
super.setText(text)
|
||||
source.write(text)
|
||||
}
|
||||
|
||||
public static boolean isValidFilename(String name) {
|
||||
return name ==~ /(\d+)([bcft])(\d).*/
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ class FileProject extends Project {
|
||||
protected File source
|
||||
|
||||
public FileProject(File dir) {
|
||||
super(dir.name)
|
||||
super(dir.canonicalFile.name)
|
||||
|
||||
if (!dir.isDirectory())
|
||||
throw new IllegalArgumentException(
|
||||
@ -65,6 +65,15 @@ class FileProject extends Project {
|
||||
return issue
|
||||
}
|
||||
|
||||
public FileProject createNewProject(String name) {
|
||||
def newDir = new File(source, name)
|
||||
newDir.mkdirs()
|
||||
|
||||
return new FileProject(newDir)
|
||||
}
|
||||
|
||||
public boolean delete() { return source.delete() }
|
||||
|
||||
@Override
|
||||
public String toString() { return name }
|
||||
|
||||
|
@ -30,4 +30,8 @@ public abstract class Project {
|
||||
String toString() { return name }
|
||||
|
||||
public abstract Issue createNewIssue(Map options)
|
||||
|
||||
public abstract Project createNewProject(String name)
|
||||
|
||||
public abstract boolean delete()
|
||||
}
|
||||
|
@ -7,4 +7,10 @@ class MockProject extends Project {
|
||||
public Issue createNewIssue(Map options) {
|
||||
throw new UnsupportedOperationException()
|
||||
}
|
||||
|
||||
public Project createNewProject(String name) {
|
||||
throw new UnsupportedOperationException()
|
||||
}
|
||||
|
||||
public boolean delete() { return true }
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
application.version=1.1.4
|
||||
application.version=1.1.5
|
||||
|
Loading…
x
Reference in New Issue
Block a user