pit-swing 2.3.1: switched to using a table for the issue list.
This commit is contained in:
parent
b7670e69f3
commit
a5d01b05d2
Binary file not shown.
@ -2,5 +2,5 @@
|
|||||||
#Thu May 13 17:04:40 CDT 2010
|
#Thu May 13 17:04:40 CDT 2010
|
||||||
app.griffon.version=0.3
|
app.griffon.version=0.3
|
||||||
app.name=pit-swing
|
app.name=pit-swing
|
||||||
app.version=2.2.0
|
app.version=2.3.1
|
||||||
plugins.fest=0.3
|
plugins.fest=0.3
|
||||||
|
@ -13,9 +13,7 @@ class PITController {
|
|||||||
void mvcGroupInit(Map args) {
|
void mvcGroupInit(Map args) {
|
||||||
|
|
||||||
SwingUtilities.invokeAndWait {
|
SwingUtilities.invokeAndWait {
|
||||||
model.issueListRenderer = new IssueListCellRenderer()
|
model.issueListRenderer = new IssueTableCellRenderer()
|
||||||
model.issueListRenderer.categoryIcons = model.categoryIcons
|
|
||||||
model.issueListRenderer.statusIcons = model.statusIcons
|
|
||||||
|
|
||||||
def config = new File(System.getProperty('user.home'), '.pit')
|
def config = new File(System.getProperty('user.home'), '.pit')
|
||||||
config = new File(config, 'pit_swing.groovy')
|
config = new File(config, 'pit_swing.groovy')
|
||||||
|
@ -29,14 +29,22 @@ class ProjectPanelController {
|
|||||||
view.issueTextArea.text = ""
|
view.issueTextArea.text = ""
|
||||||
if (!project) return
|
if (!project) return
|
||||||
|
|
||||||
if (!model.projectListModels[(project.name)]) {
|
if (!model.projectTableModels[(project.name)]) {
|
||||||
def dlm = new DefaultListModel()
|
def itm = new IssueTableModel(project,
|
||||||
project.eachIssue(model.filter ?: model.mainMVC.model.filter)
|
model.filter ?: model.mainMVC.model.filter)
|
||||||
{ dlm.addElement(it) }
|
itm.categoryIcons = model.mainMVC.model.categoryIcons
|
||||||
model.projectListModels[(project.name)] = dlm
|
itm.statusIcons = model.mainMVC.model.statusIcons
|
||||||
|
model.projectTableModels[(project.name)] = itm
|
||||||
}
|
}
|
||||||
|
|
||||||
view.issueList.setModel(model.projectListModels[(project.name)])
|
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) {
|
void displayIssue(Issue issue) {
|
||||||
@ -58,7 +66,7 @@ class ProjectPanelController {
|
|||||||
|
|
||||||
void showIssuePopup(Issue issue, def x, def y) {
|
void showIssuePopup(Issue issue, def x, def y) {
|
||||||
model.popupIssue = issue
|
model.popupIssue = issue
|
||||||
view.issuePopupMenu.show(view.issueList, x, y)
|
view.issuePopupMenu.show(view.issueTable, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
void refreshProject() {
|
void refreshProject() {
|
||||||
@ -76,7 +84,7 @@ class ProjectPanelController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void refreshIssues() {
|
void refreshIssues() {
|
||||||
model.projectListModels.clear()
|
model.projectTableModels.clear()
|
||||||
displayProject(model.selectedProject)
|
displayProject(model.selectedProject)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +139,7 @@ class ProjectPanelController {
|
|||||||
status: nidModel.status,
|
status: nidModel.status,
|
||||||
priority: nidModel.priority,
|
priority: nidModel.priority,
|
||||||
text: issueText)
|
text: issueText)
|
||||||
model.projectListModels[(model.selectedProject.name)] = null
|
model.projectTableModels[(model.selectedProject.name)] = null
|
||||||
displayProject(model.selectedProject)
|
displayProject(model.selectedProject)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,20 +147,21 @@ class ProjectPanelController {
|
|||||||
def deleteIssue = { evt ->
|
def deleteIssue = { evt ->
|
||||||
def issue
|
def issue
|
||||||
if (evt.source == view.deleteIssueButton)
|
if (evt.source == view.deleteIssueButton)
|
||||||
issue = view.issueList.selectedValue
|
issue = getSelectedIssue()
|
||||||
else issue = model.popupIssue
|
else issue = model.popupIssue
|
||||||
|
|
||||||
model.selectedProject.issues.remove(issue.id)
|
model.selectedProject.issues.remove(issue.id)
|
||||||
model.projectListModels[(model.selectedProject.name)]
|
view.issueTable.model.issues.remove(issue)
|
||||||
.removeElement(issue)
|
|
||||||
|
|
||||||
issue.delete()
|
issue.delete()
|
||||||
|
view.issueTable.invlidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
def changeCategory = { evt ->
|
def getSelectedIssue() {
|
||||||
model.popupIssue.status = status
|
if (view.issueTable.selectionModel.isSelectionEmpty())
|
||||||
view.issueList.invalidate()
|
return null
|
||||||
view.issueList.repaint()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return view.issueTable.model.issues[view.issueTable.
|
||||||
|
convertRowIndexToModel(view.issueTable.selectedRow)]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ class ProjectPanelModel {
|
|||||||
@Bindable Issue popupIssue = null
|
@Bindable Issue popupIssue = null
|
||||||
|
|
||||||
// cache the ListModels
|
// cache the ListModels
|
||||||
def projectListModels = [:]
|
def projectTableModels = [:]
|
||||||
def issueCellRenderer
|
def issueCellRenderer
|
||||||
|
|
||||||
// local filter for projects and issues
|
// local filter for projects and issues
|
||||||
|
@ -10,8 +10,10 @@ import java.awt.Point
|
|||||||
import java.awt.event.MouseEvent
|
import java.awt.event.MouseEvent
|
||||||
import javax.swing.JOptionPane
|
import javax.swing.JOptionPane
|
||||||
import javax.swing.JSplitPane
|
import javax.swing.JSplitPane
|
||||||
|
import javax.swing.JTable
|
||||||
import javax.swing.JTextField
|
import javax.swing.JTextField
|
||||||
import javax.swing.ListSelectionModel
|
import javax.swing.ListSelectionModel
|
||||||
|
import javax.swing.table.TableCellRenderer
|
||||||
import javax.swing.tree.DefaultMutableTreeNode
|
import javax.swing.tree.DefaultMutableTreeNode
|
||||||
import javax.swing.tree.DefaultTreeCellRenderer
|
import javax.swing.tree.DefaultTreeCellRenderer
|
||||||
import javax.swing.tree.DefaultTreeModel
|
import javax.swing.tree.DefaultTreeModel
|
||||||
@ -83,8 +85,14 @@ issuePopupMenu = popupMenu() {
|
|||||||
icon: model.mainMVC.model.categoryIcons[(category)],
|
icon: model.mainMVC.model.categoryIcons[(category)],
|
||||||
enabled: bind { model.popupIssue != null },
|
enabled: bind { model.popupIssue != null },
|
||||||
actionPerformed: {
|
actionPerformed: {
|
||||||
model.popupIssue.category = category
|
try {
|
||||||
controller.refreshIssues()
|
model.popupIssue.category = category
|
||||||
|
controller.refreshIssues()
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
JOptionPane.showMessageDialog(mainMVC.view.frame,
|
||||||
|
ioe.getLocalizedMessage(), 'Change Category',
|
||||||
|
JOptionPane.ERROR_MESSAGE)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,8 +103,14 @@ issuePopupMenu = popupMenu() {
|
|||||||
icon: model.mainMVC.model.statusIcons[(status)],
|
icon: model.mainMVC.model.statusIcons[(status)],
|
||||||
enabled: bind { model.popupIssue != null },
|
enabled: bind { model.popupIssue != null },
|
||||||
actionPerformed: {
|
actionPerformed: {
|
||||||
model.popupIssue.status = status
|
try {
|
||||||
controller.refreshIssues()
|
model.popupIssue.status = status
|
||||||
|
controller.refreshIssues()
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
JOptionPane.showMessageDialog(mainMVC.view.frame,
|
||||||
|
ioe.getLocalizedMessage(), 'Change Status',
|
||||||
|
JOptionPane.ERROR_MESSAGE)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,11 +122,15 @@ issuePopupMenu = popupMenu() {
|
|||||||
'New priority (0-9)', 'Change Priority...',
|
'New priority (0-9)', 'Change Priority...',
|
||||||
JOptionPane.QUESTION_MESSAGE)
|
JOptionPane.QUESTION_MESSAGE)
|
||||||
try { model.popupIssue.priority = newPriority.toInteger() }
|
try { model.popupIssue.priority = newPriority.toInteger() }
|
||||||
catch (exception) {
|
catch (NumberFormatException nfe) {
|
||||||
JOptionPane.showMessageDialog(mainMVC.view.frame,
|
JOptionPane.showMessageDialog(mainMVC.view.frame,
|
||||||
'The priority value must be an integer in [0-9].',
|
'The priority value must be an integer in [0-9].',
|
||||||
'Change Priority...', JOptionPane.ERROR_MESSAGE)
|
'Change Priority...', JOptionPane.ERROR_MESSAGE)
|
||||||
return
|
return
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
JOptionPane.showMessageDialog(mainMVC.view.fraw,
|
||||||
|
ioe.getLocalizedMessage(), 'Change Priority...',
|
||||||
|
JOptionPane.ERROR_MESSAGE)
|
||||||
}
|
}
|
||||||
controller.refreshIssues()
|
controller.refreshIssues()
|
||||||
})
|
})
|
||||||
@ -188,7 +206,37 @@ panel = splitPane(orientation: JSplitPane.HORIZONTAL_SPLIT,
|
|||||||
scrollPane(constraints: gbc(fill: GBC.BOTH, weightx: 2,
|
scrollPane(constraints: gbc(fill: GBC.BOTH, weightx: 2,
|
||||||
weighty: 2, gridx: 0, gridy: 0, gridwidth: 3)) {
|
weighty: 2, gridx: 0, gridy: 0, gridwidth: 3)) {
|
||||||
|
|
||||||
issueList = list(
|
issueTable = table(
|
||||||
|
autoCreateRowSorter: true,
|
||||||
|
autoResizeMode: JTable.AUTO_RESIZE_LAST_COLUMN,
|
||||||
|
cellSelectionEnabled: false,
|
||||||
|
columnSelectionAllowed: false,
|
||||||
|
dragEnabled: false,
|
||||||
|
rowSelectionAllowed: true,
|
||||||
|
showHorizontalLines: false,
|
||||||
|
showVerticalLines: false,
|
||||||
|
mouseClicked: { evt ->
|
||||||
|
if (evt.button == MouseEvent.BUTTON3) {
|
||||||
|
def translatedPoint = evt.locationOnScreen.clone()
|
||||||
|
translatedPoint.translate(-issueTable.locationOnScreen.@x,
|
||||||
|
-issueTable.locationOnScreen.@y)
|
||||||
|
def row = issueTable.rowAtPoint(translatedPoint)
|
||||||
|
|
||||||
|
issueTable.setRowSelectionInterval(row, row)
|
||||||
|
|
||||||
|
controller.showIssuePopup(
|
||||||
|
controller.getSelectedIssue(), evt.x, evt.y)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
issueTable.setDefaultRenderer(Object.class,
|
||||||
|
model.issueCellRenderer)
|
||||||
|
issueTable.selectionModel.valueChanged = { evt ->
|
||||||
|
if (evt.valueIsAdjusting) return
|
||||||
|
controller.displayIssue(controller.getSelectedIssue())
|
||||||
|
}
|
||||||
|
|
||||||
|
/*issueList = list(
|
||||||
cellRenderer: model.issueCellRenderer,
|
cellRenderer: model.issueCellRenderer,
|
||||||
selectionMode: ListSelectionModel.SINGLE_SELECTION,
|
selectionMode: ListSelectionModel.SINGLE_SELECTION,
|
||||||
valueChanged: { evt ->
|
valueChanged: { evt ->
|
||||||
@ -202,7 +250,7 @@ panel = splitPane(orientation: JSplitPane.HORIZONTAL_SPLIT,
|
|||||||
controller.showIssuePopup(
|
controller.showIssuePopup(
|
||||||
issueList.selectedValue, evt.x, evt.y)
|
issueList.selectedValue, evt.x, evt.y)
|
||||||
}
|
}
|
||||||
})
|
})*/
|
||||||
}
|
}
|
||||||
|
|
||||||
wordWrapCheckBox = checkBox('Word wrap',
|
wordWrapCheckBox = checkBox('Word wrap',
|
||||||
@ -213,8 +261,8 @@ panel = splitPane(orientation: JSplitPane.HORIZONTAL_SPLIT,
|
|||||||
|
|
||||||
deleteIssueButton = button(deleteIssue,
|
deleteIssueButton = button(deleteIssue,
|
||||||
constraints: gbc(gridx: 2, gridy: 1, anchor: GBC.EAST),
|
constraints: gbc(gridx: 2, gridy: 1, anchor: GBC.EAST),
|
||||||
enabled: bind(source: issueList, sourceEvent: 'valueChanged',
|
enabled: bind(source: issueTable.selectionModel, sourceEvent: 'valueChanged',
|
||||||
sourceValue: { issueList.selectedValue != null }))
|
sourceValue: { !issueTable.selectionModel.isSelectionEmpty() }))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,19 +271,21 @@ panel = splitPane(orientation: JSplitPane.HORIZONTAL_SPLIT,
|
|||||||
wrapStyleWord: true,
|
wrapStyleWord: true,
|
||||||
lineWrap: bind(source: wordWrapCheckBox,
|
lineWrap: bind(source: wordWrapCheckBox,
|
||||||
sourceProperty: 'selected'),
|
sourceProperty: 'selected'),
|
||||||
editable: bind( source: issueList, sourceEvent: 'valueChanged',
|
editable: bind( source: issueTable.selectionModel, sourceEvent: 'valueChanged',
|
||||||
sourceValue: { issueList.selectedValue != null }),
|
sourceValue: { !issueTable.selectionModel.isSelectionEmpty() }),
|
||||||
font: model.mainMVC.model.issueDetailFont,
|
font: model.mainMVC.model.issueDetailFont,
|
||||||
focusGained: {},
|
focusGained: {},
|
||||||
focusLost: {
|
focusLost: {
|
||||||
if (!issueList?.selectedValue) return
|
def issue = controller.getSelectedIssue()
|
||||||
if (issueTextArea.text != issueList.selectedValue.text)
|
if (issue == null) return
|
||||||
issueList.selectedValue.text = issueTextArea.text
|
if (issueTextArea.text != issue.text)
|
||||||
|
issue.text = issueTextArea.text
|
||||||
},
|
},
|
||||||
mouseExited: {
|
mouseExited: {
|
||||||
if (!issueList?.selectedValue) return
|
def issue = controller.getSelectedIssue()
|
||||||
if (issueTextArea.text != issueList.selectedValue.text)
|
if (issue == null) return
|
||||||
issueList.selectedValue.text = issueTextArea.text
|
if (issueTextArea.text != issue.text)
|
||||||
|
issue.text = issueTextArea.text
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.jdbernard.pit.swing
|
||||||
|
|
||||||
|
import java.awt.Component
|
||||||
|
import java.awt.Dimension
|
||||||
|
import javax.swing.Icon
|
||||||
|
import javax.swing.JLabel
|
||||||
|
import javax.swing.JTable
|
||||||
|
import javax.swing.table.DefaultTableCellRenderer
|
||||||
|
|
||||||
|
public class IssueTableCellRenderer extends DefaultTableCellRenderer {
|
||||||
|
|
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||||
|
boolean isSelected, boolean hasFocus, int row, int col) {
|
||||||
|
super.getTableCellRendererComponent(table, value, isSelected,
|
||||||
|
hasFocus, row, col)
|
||||||
|
|
||||||
|
if (value instanceof String) {
|
||||||
|
if (col > 2) {
|
||||||
|
setHorizontalAlignment(JLabel.LEADING)
|
||||||
|
} else {
|
||||||
|
setText("<html><tt>" + getText() + "</tt></html>")
|
||||||
|
setHorizontalAlignment(JLabel.TRAILING)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.jdbernard.pit.swing
|
||||||
|
|
||||||
|
import com.jdbernard.pit.Filter
|
||||||
|
import com.jdbernard.pit.Issue
|
||||||
|
import com.jdbernard.pit.Project
|
||||||
|
import javax.swing.Icon
|
||||||
|
import javax.swing.table.AbstractTableModel
|
||||||
|
|
||||||
|
public class IssueTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
|
def issues = []
|
||||||
|
boolean projectsVisible = false
|
||||||
|
def categoryIcons = [:]
|
||||||
|
def statusIcons = [:]
|
||||||
|
|
||||||
|
public IssueTableModel(Project p, Filter f = null) {
|
||||||
|
p.eachIssue(f) { issues << it }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRowCount() {
|
||||||
|
return issues.size
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColumnCount() {
|
||||||
|
if (projectsVisible) return 5
|
||||||
|
else return 4
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValueAt(int row, int column) {
|
||||||
|
if (row >= getRowCount() || column > getColumnCount())
|
||||||
|
return null
|
||||||
|
|
||||||
|
switch(column) {
|
||||||
|
case 0: return getIcon(issues[row]); break
|
||||||
|
case 1: return issues[row].id; break
|
||||||
|
case 2: return "(" + issues[row].priority + "): "; break
|
||||||
|
case 3: return issues[row].title; break
|
||||||
|
case 4: return issues[row].project.name; break
|
||||||
|
default: return "Invalid row index."; break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getColumnClass(int column) {
|
||||||
|
switch (column) {
|
||||||
|
case 0: return Icon.class; break
|
||||||
|
default: return String.class; break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnName(int column) {
|
||||||
|
switch (column) {
|
||||||
|
case 0: return "C/S"; break
|
||||||
|
case 1: return "ID"; break
|
||||||
|
case 2: return "P"; break
|
||||||
|
case 3: return "Title/Summary"; break
|
||||||
|
case 4: return "Project"; break
|
||||||
|
default: return "ERR"; break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCellEditable(int row, int col) { return false }
|
||||||
|
|
||||||
|
private Icon getIcon(Issue issue) {
|
||||||
|
def icon
|
||||||
|
if (categoryIcons[(issue.category)]) {
|
||||||
|
icon = categoryIcons[(issue.category)]
|
||||||
|
|
||||||
|
if (statusIcons[(issue.status)])
|
||||||
|
icon = new CompositeIcon([icon, statusIcons[(issue.status)]])
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
BIN
release/pit-swing-2.3.1.jar
Normal file
BIN
release/pit-swing-2.3.1.jar
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user