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
|
||||
app.griffon.version=0.3
|
||||
app.name=pit-swing
|
||||
app.version=2.2.0
|
||||
app.version=2.3.1
|
||||
plugins.fest=0.3
|
||||
|
@ -13,9 +13,7 @@ class PITController {
|
||||
void mvcGroupInit(Map args) {
|
||||
|
||||
SwingUtilities.invokeAndWait {
|
||||
model.issueListRenderer = new IssueListCellRenderer()
|
||||
model.issueListRenderer.categoryIcons = model.categoryIcons
|
||||
model.issueListRenderer.statusIcons = model.statusIcons
|
||||
model.issueListRenderer = new IssueTableCellRenderer()
|
||||
|
||||
def config = new File(System.getProperty('user.home'), '.pit')
|
||||
config = new File(config, 'pit_swing.groovy')
|
||||
|
@ -29,14 +29,22 @@ class ProjectPanelController {
|
||||
view.issueTextArea.text = ""
|
||||
if (!project) return
|
||||
|
||||
if (!model.projectListModels[(project.name)]) {
|
||||
def dlm = new DefaultListModel()
|
||||
project.eachIssue(model.filter ?: model.mainMVC.model.filter)
|
||||
{ dlm.addElement(it) }
|
||||
model.projectListModels[(project.name)] = dlm
|
||||
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.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) {
|
||||
@ -58,7 +66,7 @@ class ProjectPanelController {
|
||||
|
||||
void showIssuePopup(Issue issue, def x, def y) {
|
||||
model.popupIssue = issue
|
||||
view.issuePopupMenu.show(view.issueList, x, y)
|
||||
view.issuePopupMenu.show(view.issueTable, x, y)
|
||||
}
|
||||
|
||||
void refreshProject() {
|
||||
@ -76,7 +84,7 @@ class ProjectPanelController {
|
||||
}
|
||||
|
||||
void refreshIssues() {
|
||||
model.projectListModels.clear()
|
||||
model.projectTableModels.clear()
|
||||
displayProject(model.selectedProject)
|
||||
}
|
||||
|
||||
@ -131,7 +139,7 @@ class ProjectPanelController {
|
||||
status: nidModel.status,
|
||||
priority: nidModel.priority,
|
||||
text: issueText)
|
||||
model.projectListModels[(model.selectedProject.name)] = null
|
||||
model.projectTableModels[(model.selectedProject.name)] = null
|
||||
displayProject(model.selectedProject)
|
||||
}
|
||||
}
|
||||
@ -139,20 +147,21 @@ class ProjectPanelController {
|
||||
def deleteIssue = { evt ->
|
||||
def issue
|
||||
if (evt.source == view.deleteIssueButton)
|
||||
issue = view.issueList.selectedValue
|
||||
issue = getSelectedIssue()
|
||||
else issue = model.popupIssue
|
||||
|
||||
model.selectedProject.issues.remove(issue.id)
|
||||
model.projectListModels[(model.selectedProject.name)]
|
||||
.removeElement(issue)
|
||||
view.issueTable.model.issues.remove(issue)
|
||||
|
||||
issue.delete()
|
||||
view.issueTable.invlidate()
|
||||
}
|
||||
|
||||
def changeCategory = { evt ->
|
||||
model.popupIssue.status = status
|
||||
view.issueList.invalidate()
|
||||
view.issueList.repaint()
|
||||
}
|
||||
def getSelectedIssue() {
|
||||
if (view.issueTable.selectionModel.isSelectionEmpty())
|
||||
return null
|
||||
|
||||
return view.issueTable.model.issues[view.issueTable.
|
||||
convertRowIndexToModel(view.issueTable.selectedRow)]
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class ProjectPanelModel {
|
||||
@Bindable Issue popupIssue = null
|
||||
|
||||
// cache the ListModels
|
||||
def projectListModels = [:]
|
||||
def projectTableModels = [:]
|
||||
def issueCellRenderer
|
||||
|
||||
// local filter for projects and issues
|
||||
|
@ -10,8 +10,10 @@ import java.awt.Point
|
||||
import java.awt.event.MouseEvent
|
||||
import javax.swing.JOptionPane
|
||||
import javax.swing.JSplitPane
|
||||
import javax.swing.JTable
|
||||
import javax.swing.JTextField
|
||||
import javax.swing.ListSelectionModel
|
||||
import javax.swing.table.TableCellRenderer
|
||||
import javax.swing.tree.DefaultMutableTreeNode
|
||||
import javax.swing.tree.DefaultTreeCellRenderer
|
||||
import javax.swing.tree.DefaultTreeModel
|
||||
@ -83,8 +85,14 @@ issuePopupMenu = popupMenu() {
|
||||
icon: model.mainMVC.model.categoryIcons[(category)],
|
||||
enabled: bind { model.popupIssue != null },
|
||||
actionPerformed: {
|
||||
try {
|
||||
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)],
|
||||
enabled: bind { model.popupIssue != null },
|
||||
actionPerformed: {
|
||||
try {
|
||||
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...',
|
||||
JOptionPane.QUESTION_MESSAGE)
|
||||
try { model.popupIssue.priority = newPriority.toInteger() }
|
||||
catch (exception) {
|
||||
catch (NumberFormatException nfe) {
|
||||
JOptionPane.showMessageDialog(mainMVC.view.frame,
|
||||
'The priority value must be an integer in [0-9].',
|
||||
'Change Priority...', JOptionPane.ERROR_MESSAGE)
|
||||
return
|
||||
} catch (IOException ioe) {
|
||||
JOptionPane.showMessageDialog(mainMVC.view.fraw,
|
||||
ioe.getLocalizedMessage(), 'Change Priority...',
|
||||
JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
controller.refreshIssues()
|
||||
})
|
||||
@ -188,7 +206,37 @@ panel = splitPane(orientation: JSplitPane.HORIZONTAL_SPLIT,
|
||||
scrollPane(constraints: gbc(fill: GBC.BOTH, weightx: 2,
|
||||
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,
|
||||
selectionMode: ListSelectionModel.SINGLE_SELECTION,
|
||||
valueChanged: { evt ->
|
||||
@ -202,7 +250,7 @@ panel = splitPane(orientation: JSplitPane.HORIZONTAL_SPLIT,
|
||||
controller.showIssuePopup(
|
||||
issueList.selectedValue, evt.x, evt.y)
|
||||
}
|
||||
})
|
||||
})*/
|
||||
}
|
||||
|
||||
wordWrapCheckBox = checkBox('Word wrap',
|
||||
@ -213,8 +261,8 @@ panel = splitPane(orientation: JSplitPane.HORIZONTAL_SPLIT,
|
||||
|
||||
deleteIssueButton = button(deleteIssue,
|
||||
constraints: gbc(gridx: 2, gridy: 1, anchor: GBC.EAST),
|
||||
enabled: bind(source: issueList, sourceEvent: 'valueChanged',
|
||||
sourceValue: { issueList.selectedValue != null }))
|
||||
enabled: bind(source: issueTable.selectionModel, sourceEvent: 'valueChanged',
|
||||
sourceValue: { !issueTable.selectionModel.isSelectionEmpty() }))
|
||||
|
||||
}
|
||||
|
||||
@ -223,19 +271,21 @@ panel = splitPane(orientation: JSplitPane.HORIZONTAL_SPLIT,
|
||||
wrapStyleWord: true,
|
||||
lineWrap: bind(source: wordWrapCheckBox,
|
||||
sourceProperty: 'selected'),
|
||||
editable: bind( source: issueList, sourceEvent: 'valueChanged',
|
||||
sourceValue: { issueList.selectedValue != null }),
|
||||
editable: bind( source: issueTable.selectionModel, sourceEvent: 'valueChanged',
|
||||
sourceValue: { !issueTable.selectionModel.isSelectionEmpty() }),
|
||||
font: model.mainMVC.model.issueDetailFont,
|
||||
focusGained: {},
|
||||
focusLost: {
|
||||
if (!issueList?.selectedValue) return
|
||||
if (issueTextArea.text != issueList.selectedValue.text)
|
||||
issueList.selectedValue.text = issueTextArea.text
|
||||
def issue = controller.getSelectedIssue()
|
||||
if (issue == null) return
|
||||
if (issueTextArea.text != issue.text)
|
||||
issue.text = issueTextArea.text
|
||||
},
|
||||
mouseExited: {
|
||||
if (!issueList?.selectedValue) return
|
||||
if (issueTextArea.text != issueList.selectedValue.text)
|
||||
issueList.selectedValue.text = issueTextArea.text
|
||||
def issue = controller.getSelectedIssue()
|
||||
if (issue == null) return
|
||||
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