diff --git a/issues/libpit/0007c5.rst b/issues/libpit/0007c6.rst similarity index 100% rename from issues/libpit/0007c5.rst rename to issues/libpit/0007c6.rst diff --git a/issues/libpit/0018c4.rst b/issues/libpit/0018c4.rst new file mode 100644 index 0000000..aadc61d --- /dev/null +++ b/issues/libpit/0018c4.rst @@ -0,0 +1,12 @@ +FileProject.delete() does not handle sub-projects correctly. +============================================================ + +FileProject.delete() deletes the project directory if the directory is empty, +but fails to do so if the directory is not empty. + +Initial Recommendation +---------------------- + +Loop through the issues and delete the files, loop through the projects and +call Project.delete(). Alternatively, use File.deleteDir() rather than +File.delete() diff --git a/issues/libpit/0019t4.rst b/issues/libpit/0019t4.rst new file mode 100644 index 0000000..747f212 --- /dev/null +++ b/issues/libpit/0019t4.rst @@ -0,0 +1,2 @@ +Add unit tests for FileIssue.delete() +===================================== diff --git a/issues/libpit/0020t4.rst b/issues/libpit/0020t4.rst new file mode 100644 index 0000000..4084980 --- /dev/null +++ b/issues/libpit/0020t4.rst @@ -0,0 +1,2 @@ +Add unit tests for FileProject.delete() +======================================= diff --git a/libpit/project.properties b/libpit/project.properties index 4281214..33881ba 100644 --- a/libpit/project.properties +++ b/libpit/project.properties @@ -1,10 +1,10 @@ -#Wed Feb 24 03:03:11 CST 2010 +#Wed Feb 24 04:27:18 CST 2010 build.dir=build src.dir=src lib.shared.dir=../shared-libs test.dir=test -build.number=4 -expected.application.version=1.1.5 +build.number=5 +expected.application.version=1.1.6 lib.dir=lib release.dir=release release.jar=pit-${application.version}.jar diff --git a/libpit/src/com/jdbernard/pit/FileIssue.groovy b/libpit/src/com/jdbernard/pit/FileIssue.groovy index 7b59cb8..846b621 100644 --- a/libpit/src/com/jdbernard/pit/FileIssue.groovy +++ b/libpit/src/com/jdbernard/pit/FileIssue.groovy @@ -41,6 +41,8 @@ public class FileIssue extends Issue { source.write(text) } + public boolean delete() { return source.delete() } + public static boolean isValidFilename(String name) { return name ==~ /(\d+)([bcft])(\d).*/ } diff --git a/libpit/src/com/jdbernard/pit/FileProject.groovy b/libpit/src/com/jdbernard/pit/FileProject.groovy index 4d8b2fc..f008c7c 100644 --- a/libpit/src/com/jdbernard/pit/FileProject.groovy +++ b/libpit/src/com/jdbernard/pit/FileProject.groovy @@ -72,7 +72,7 @@ class FileProject extends Project { return new FileProject(newDir) } - public boolean delete() { return source.delete() } + public boolean delete() { return source.deleteDir() } @Override public String toString() { return name } diff --git a/libpit/src/com/jdbernard/pit/Issue.groovy b/libpit/src/com/jdbernard/pit/Issue.groovy index 1fc2ec3..48c23eb 100644 --- a/libpit/src/com/jdbernard/pit/Issue.groovy +++ b/libpit/src/com/jdbernard/pit/Issue.groovy @@ -2,7 +2,7 @@ package com.jdbernard.pit import java.lang.IllegalArgumentException as IAE -public class Issue { +public abstract class Issue { protected String id protected Category category @@ -38,4 +38,6 @@ public class Issue { @Override public String toString() { return "${id}(${priority}): ${category} ${title}" } + + public abstract boolean delete() } diff --git a/libpit/test/com/jdbernard/pit/FileProjectTest.groovy b/libpit/test/com/jdbernard/pit/FileProjectTest.groovy index e6b52f8..bc12285 100644 --- a/libpit/test/com/jdbernard/pit/FileProjectTest.groovy +++ b/libpit/test/com/jdbernard/pit/FileProjectTest.groovy @@ -121,6 +121,8 @@ class FileProjectTest { assertEquals rootProj.name, 'renamedTestDir' assertTrue new File('renamedTestDir').exists() + + assert rootProj.source.deleteDir() } @Test void testCreateNewIssue() { diff --git a/libpit/test/com/jdbernard/pit/FilterTest.groovy b/libpit/test/com/jdbernard/pit/FilterTest.groovy index 58fed82..b873b68 100644 --- a/libpit/test/com/jdbernard/pit/FilterTest.groovy +++ b/libpit/test/com/jdbernard/pit/FilterTest.groovy @@ -15,16 +15,16 @@ class FilterTest { proj = new MockProject('proj1') - def issue = new Issue( '0000', Category.TASK, 5) + def issue = new MockIssue( '0000', Category.TASK, 5) proj.issues['0000'] = issue - issue = new Issue('0001', Category.BUG, 3) + issue = new MockIssue('0001', Category.BUG, 3) proj.issues['0001'] = issue - issue = new Issue('0002', Category.CLOSED, 9) + issue = new MockIssue('0002', Category.CLOSED, 9) proj.issues['0002'] = issue - issue = new Issue('0003', Category.FEATURE, 0) + issue = new MockIssue('0003', Category.FEATURE, 0) proj.issues['0003'] = issue def subProj = new MockProject('subproj1') diff --git a/libpit/test/com/jdbernard/pit/MockIssue.groovy b/libpit/test/com/jdbernard/pit/MockIssue.groovy new file mode 100644 index 0000000..9c32620 --- /dev/null +++ b/libpit/test/com/jdbernard/pit/MockIssue.groovy @@ -0,0 +1,6 @@ +package com.jdbernard.pit + +public class MockIssue extends Issue { + public MockIssue(String id, Category c, int p) { super (id, c, p) } + public boolean delete() { return true } +} diff --git a/pit-swing/griffon-app/views/com/jdbernard/pit/swing/PITView.groovy b/pit-swing/griffon-app/views/com/jdbernard/pit/swing/PITView.groovy index 6927c79..340d1dd 100644 --- a/pit-swing/griffon-app/views/com/jdbernard/pit/swing/PITView.groovy +++ b/pit-swing/griffon-app/views/com/jdbernard/pit/swing/PITView.groovy @@ -6,6 +6,7 @@ import com.jdbernard.pit.Issue import com.jdbernard.pit.Project import com.jdbernard.pit.FileProject import groovy.beans.Bindable +import java.awt.Point import java.awt.event.MouseEvent import javax.swing.DefaultListModel import javax.swing.JFileChooser @@ -31,7 +32,9 @@ categoryIcons = [:] // filter for projects and issues filter = new Filter(categories: []) -@Bindable def popupProject = null +popupProject = null + +popupIssue = null // initialize category-related view data Category.values().each { @@ -71,11 +74,20 @@ showProjectPopup = { project, x, y -> projectPopupMenu.show(projectTree, x, y) } +showIssuePopup = { issue, x, y -> + popupIssue = issue + issuePopupMenu.eachWithIndex { menuItem, idx -> + if (idx != 0) menuItem.enabled = issue != null } + issuePopupMenu.show(issueList, x, y) +} + /* **************** * GUI components * ****************/ openDialog = fileChooser(fileSelectionMode: JFileChooser.DIRECTORIES_ONLY) +//newIssueDialog = dialog() + projectPopupMenu = popupMenu() { menuItem('New Project...', actionPerformed: { @@ -85,15 +97,64 @@ projectPopupMenu = popupMenu() { if (!popupProject) popupProject = model.rootProject def newProject = popupProject.createNewProject(name) + popupProject.projects[(newProject.name)] = newProject projectTree.model = new DefaultTreeModel( makeNodes(model.rootProject)) }) menuItem('Delete Project', - actionPerformed: { popupProject.delete() }) + actionPerformed: { + if (!popupProject) return + popupProject.delete() + // do not like, tied to Project implementation + model.rootProject = new FileProject(model.rootProject.source) + }) +} + +issuePopupMenu = popupMenu() { + menuItem('New Issue...', + actionPerformed: { }) + + menuItem('Delete Issue', + actionPerformed: { + if (!popupIssue) return + popupIssue.delete() + + }) + + separator() + + menu('Change Category') { + Category.values().each { category -> + menuItem(category.toString(), + icon: categoryIcons[(category)], + actionPerformed: { + if (!popupIssue) return + popupIssue.category = category + issueList.invalidate() + }) + } + } + + menuItem('Change Priority...', + actionPerformed: { + if (!popupIssue) return + def newPriority = JOptionPane.showInputDialog(frame, + 'New priority (0-9)', 'Change Priority...', + JOptionPane.QUESTION_MESSAGE) + try { popupIssue.priority = newPriority.toInteger() } + catch (exception) { + JOptionPane.showMessage(frame, 'The priority value must ' + + 'be an integer in [0-9].', 'Change Priority...', + JOptionPane.ERROR_MESSAGE) + return + } + issueList.invalidate() + }) } frame = application(title:'Personal Issue Tracker', locationRelativeTo: null, + minimumSize: [600, 400], //size:[320,480], pack:true, //location:[50,50], @@ -186,7 +247,16 @@ frame = application(title:'Personal Issue Tracker', cellRenderer: new IssueListCellRenderer( issueIcons: categoryIcons), selectionMode: ListSelectionModel.SINGLE_SELECTION, - valueChanged: { displayIssue(issueList.selectedValue) }) + valueChanged: { displayIssue(issueList.selectedValue) }, + mouseClicked: { evt -> + if (evt.button == MouseEvent.BUTTON3) { + issueList.selectedIndex = issueList.locationToIndex( + [evt.x, evt.y] as Point) + + showIssuePopup(issueList.selectedValue, + evt.x, evt.y) + } + }) } scrollPane(constraints: "bottom") { issueTextArea = textArea() diff --git a/pit-swing/lib/pit-1.1.4.jar b/pit-swing/lib/pit-1.1.4.jar deleted file mode 100644 index 8dc6a2a..0000000 Binary files a/pit-swing/lib/pit-1.1.4.jar and /dev/null differ diff --git a/pit-swing/lib/pit-1.1.6.4.jar b/pit-swing/lib/pit-1.1.6.4.jar new file mode 100644 index 0000000..394656c Binary files /dev/null and b/pit-swing/lib/pit-1.1.6.4.jar differ diff --git a/pit-swing/src/main/com/jdbernard/pit/swing/IssueListCellRenderer.groovy b/pit-swing/src/main/com/jdbernard/pit/swing/IssueListCellRenderer.groovy index 5b6c142..b67a53f 100644 --- a/pit-swing/src/main/com/jdbernard/pit/swing/IssueListCellRenderer.groovy +++ b/pit-swing/src/main/com/jdbernard/pit/swing/IssueListCellRenderer.groovy @@ -15,6 +15,8 @@ public class IssueListCellRenderer extends DefaultListCellRenderer { selected, hasFocus) if (issueIcons[(value.category)]) component.setIcon(issueIcons[(value.category)]) + component.text = "${value.id} (${value.priority}): " + + "${value.title}" return component } } diff --git a/version.properties b/version.properties index 86ae6c2..6a4f13a 100644 --- a/version.properties +++ b/version.properties @@ -1 +1 @@ -application.version=1.1.5 +application.version=1.1.6