package com.vistatec.ocelot.lqi.gui;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Action;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.table.JTableHeader;
import com.vistatec.ocelot.PlatformSupport;
import com.vistatec.ocelot.lqi.LQIKeyEventManager;
import com.vistatec.ocelot.lqi.constants.LQIConstants;
import com.vistatec.ocelot.lqi.constants.ShortCutConstants;
import com.vistatec.ocelot.lqi.gui.editor.CategoryCellEditor;
import com.vistatec.ocelot.lqi.gui.editor.FloatCellEditor;
import com.vistatec.ocelot.lqi.gui.editor.LQIGridButtonEditor;
import com.vistatec.ocelot.lqi.gui.editor.TextAreaTableCellEditor;
import com.vistatec.ocelot.lqi.gui.renderer.ColorHeaderCellRenderer;
import com.vistatec.ocelot.lqi.gui.renderer.LQIGridButtonRenderer;
import com.vistatec.ocelot.lqi.gui.renderer.TextAreaColorCellRenderer;
import com.vistatec.ocelot.lqi.model.LQIErrorCategory;
import com.vistatec.ocelot.lqi.model.LQIGrid;
import com.vistatec.ocelot.lqi.model.LQISeverity;
import com.vistatec.ocelot.lqi.model.LQIShortCut;
/**
* Helper class for the LQI grid table management.
*/
public class LQIGridTableHelper implements MouseListener, TableCellListener,
ActionListener {
/** Minor severity column color. */
private static final Color MINOR_COL_COLOR = new Color(217, 234, 211);
// /** Serious severity column color. */
// private static final Color SERIOUS_COL_COLOR = new Color(252, 229, 205);
/** Critical severity column color. */
private static final Color CRITICAL_COL_COLOR = new Color(244, 204, 204);
/** LQI grid table row height constant. */
private static final int ROW_HEIGHT = 30;
/** LQI grid table column width constant. */
private static final int COLUMN_WITDH = 150;
/** LQI grid table Comment column width constant. */
private static final int COMMENT_COLUMN_WITDH = 250;
/** LQI grid table Weight column width constant. */
private static final int WEIGHT_COLUMN_WIDTH = 60;
/** The LQI grid table. */
private JTable lqiTable;
/** The LQI grid table model. */
private LQIGridTableModel lqiTableModel;
/** Object handling keyboard shortcuts. */
private LQIKeyEventManager keyEventManager;
/** List of all shortcut used in the LQI grid. */
private List<KeyStroke> shortcutsInUse;
/** table severity columns colors. */
private Color[] columnColors;
/** The severity columns pop up menu. */
private JPopupMenu severityMenu;
/** The severity properties menu item. */
private SeverityMenuItem mnuSeverityProps;
/** The delete severity menu item. */
private SeverityMenuItem mnuDelSeverity;
private PlatformSupport platformSupport;
/**
* Constructor.
*/
public LQIGridTableHelper(PlatformSupport platformSupport) {
this.platformSupport = platformSupport;
this.keyEventManager = LQIKeyEventManager.getInstance();
severityMenu = new JPopupMenu();
mnuSeverityProps = new SeverityMenuItem("Edit", SeverityMenuItem.EDIT);
mnuSeverityProps.addActionListener(this);
severityMenu.add(mnuSeverityProps);
mnuDelSeverity = new SeverityMenuItem("Delete", SeverityMenuItem.DELETE);
mnuDelSeverity.addActionListener(this);
severityMenu.add(mnuDelSeverity);
}
/**
* Create the LQI grid table.
*
* @param lqiGridObj
* the LQI grid object.
* @param mode
* the mode.
* @param gridButtonAction
* the action for LQI grid buttons.
* @return the LQI grid table.
*/
public JTable createLQIGridTable(LQIGrid lqiGridObj, int mode,
final Action gridButtonAction) {
initUsedShortcutList(lqiGridObj);
lqiTableModel = new LQIGridTableModel(lqiGridObj, mode);
initColorForColumns();
lqiTableModel.addTableCellListener(this);
lqiTable = new JTable(lqiTableModel);
lqiTable.setGridColor(Color.LIGHT_GRAY);
lqiTable.getTableHeader().setReorderingAllowed(false);
lqiTable.getTableHeader().addMouseListener(this);
return lqiTable;
}
/**
* Initializes the list containing used shortcuts.
*
* @param lqiGridObj
* the LQI grid.
*/
private void initUsedShortcutList(LQIGrid lqiGridObj) {
shortcutsInUse = new ArrayList<KeyStroke>();
if (lqiGridObj.getErrorCategories() != null) {
for (LQIErrorCategory errCat : lqiGridObj.getErrorCategories()) {
if (errCat.getShortcuts() != null) {
for (LQIShortCut shortcut : errCat.getShortcuts()) {
shortcutsInUse.add(shortcut.getKeyStroke());
}
}
}
}
}
/**
* Configures the table
*
* @param gridButtonAction
* the action for LQI grid buttons.
*/
public void configureTable(Action gridButtonAction) {
lqiTable.setRowHeight(ROW_HEIGHT);
lqiTable.getTableHeader()
.getColumnModel()
.getColumn(lqiTableModel.getErrorCategoryColumn())
.setHeaderRenderer(
new ColorHeaderCellRenderer(lqiTable.getBackground(),
lqiTable.getGridColor()));
int firstSeverityColIdx = lqiTableModel.getSeverityColsStartIndex();
for (int i = 0; i < columnColors.length; i++) {
lqiTable.getTableHeader()
.getColumnModel()
.getColumn(i + firstSeverityColIdx)
.setHeaderRenderer(
new ColorHeaderCellRenderer(columnColors[i],
lqiTable.getGridColor()));
}
lqiTable.getTableHeader()
.getColumnModel()
.getColumn(lqiTableModel.getCommentColumn())
.setHeaderRenderer(
new ColorHeaderCellRenderer(lqiTable.getBackground(),
lqiTable.getGridColor()));
int catWeightColIdx = lqiTableModel.getErrorCatWeightColumn();
if(catWeightColIdx > -1){
lqiTable.getTableHeader()
.getColumnModel()
.getColumn(catWeightColIdx)
.setHeaderRenderer(
new ColorHeaderCellRenderer(lqiTable.getBackground(),
lqiTable.getGridColor()));
}
ColorCellRenderer centerRenderer = new ColorCellRenderer(
lqiTable.getBackground());
centerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
lqiTable.getColumnModel()
.getColumn(lqiTableModel.getErrorCategoryColumn())
.setCellRenderer(centerRenderer);
lqiTable.getColumnModel()
.getColumn(lqiTableModel.getErrorCategoryColumn())
.setCellEditor(new CategoryCellEditor());
lqiTable.getColumnModel()
.getColumn(lqiTableModel.getCommentColumn())
.setCellRenderer(
new TextAreaColorCellRenderer(lqiTable.getBackground()));
lqiTable.getColumnModel().getColumn(lqiTableModel.getCommentColumn())
.setCellEditor(new TextAreaTableCellEditor());
if(catWeightColIdx > -1){
lqiTable.getColumnModel().getColumn(catWeightColIdx).setCellRenderer(centerRenderer);
lqiTable.getColumnModel().getColumn(catWeightColIdx).setCellEditor(new FloatCellEditor());
}
LQIGridButtonEditor buttonEditor = new LQIGridButtonEditor(
gridButtonAction);
for (int i = 0; i < columnColors.length; i++) {
lqiTable.getColumnModel()
.getColumn(firstSeverityColIdx + i)
.setCellRenderer(new LQIGridButtonRenderer(columnColors[i]));
lqiTable.getColumnModel().getColumn(firstSeverityColIdx + i)
.setCellEditor(buttonEditor);
}
for (int i = 0; i < lqiTable.getColumnCount(); i++) {
if (i != lqiTableModel.getErrorCatWeightColumn() && i != lqiTableModel.getCommentColumn()) {
lqiTable.getColumnModel().getColumn(i).setWidth(COLUMN_WITDH);
lqiTable.getColumnModel().getColumn(i)
.setMinWidth(COLUMN_WITDH);
}
}
lqiTable.getColumnModel().getColumn(lqiTableModel.getCommentColumn())
.setWidth(COMMENT_COLUMN_WITDH);
lqiTable.getColumnModel().getColumn(lqiTableModel.getCommentColumn())
.setMinWidth(COMMENT_COLUMN_WITDH);
if (lqiTableModel.getErrorCatWeightColumn() != -1) {
lqiTable.getColumnModel()
.getColumn(lqiTableModel.getErrorCatWeightColumn())
.setWidth(WEIGHT_COLUMN_WIDTH);
lqiTable.getColumnModel()
.getColumn(lqiTableModel.getErrorCatWeightColumn())
.setMinWidth(WEIGHT_COLUMN_WIDTH);
}
}
/**
* // * Gets the table width.
*
* @return newSeverity
*/
public int getTableWidth() {
int weightColWidth = 0;
int normalColCount = lqiTable.getColumnCount() - 1;
if(lqiTableModel.getErrorCatWeightColumn() != -1){
weightColWidth = WEIGHT_COLUMN_WIDTH;
normalColCount = lqiTable.getColumnCount() - 2;
}
return COLUMN_WITDH * (normalColCount)
+ COMMENT_COLUMN_WITDH + weightColWidth;
}
/**
* Updates the table header.
*/
private void updateTableHeader() {
int sevrityColsCount = lqiTableModel.getSeverityColumnsCount();
int severityColsFirstIdx = lqiTableModel.getSeverityColsStartIndex();
if (severityColsFirstIdx > -1) {
for (int index = severityColsFirstIdx; index < sevrityColsCount; index++) {
lqiTable.getTableHeader().getColumnModel().getColumn(index)
.setHeaderValue(lqiTableModel.getColumnName(index));
}
}
}
/**
* Adds a new error category by adding a new row to the LQI grid table.
*/
public void addErrorCategory() {
if (lqiTable.getRowCount() == LQIConstants.LQI_CATEGORIES_LIST.length) {
JOptionPane.showMessageDialog(lqiTable,
"Impossible to add a category: no LQI categories left.",
"LQI Grid Add Category", JOptionPane.WARNING_MESSAGE);
} else {
LQIErrorCategory errorCat = lqiTableModel.addRow();
lqiTable.getSelectionModel().setSelectionInterval(
lqiTableModel.getRowCount() - 1,
lqiTableModel.getRowCount() - 1);
if (lqiTable.editCellAt(lqiTableModel.getRowCount() - 1, 0)) {
lqiTable.getEditorComponent().requestFocusInWindow();
}
keyEventManager.errorCategoryAdded(lqiTableModel.getLQIGrid(),
errorCat);
}
}
/**
* Deletes the selected category. A message is prompt to the user asking to
* confirm the deletion. In case the user confirms, then the selected row is
* deleted.
*/
public void deleteSelectedErrorCategory() {
int selRow = lqiTable.getSelectedRow();
if (selRow != -1) {
int option = JOptionPane.showConfirmDialog(lqiTable,
"Do you want to delete the selected category?",
"LQI Grid Category Deletion", JOptionPane.YES_NO_OPTION);
if (option == JOptionPane.YES_OPTION) {
LQIErrorCategory errorCat = lqiTableModel.deleteRow(selRow);
keyEventManager.errorCategoryDeleted(
lqiTableModel.getLQIGrid(), errorCat);
if (errorCat.getShortcuts() != null) {
for (LQIShortCut shortcut : errorCat.getShortcuts()) {
shortcutsInUse.remove(shortcut.getKeyStroke());
}
}
}
}
}
/**
* Gets the LQI grid table.
*
* @return the LQI grid table.
*/
public JTable getLqiTable() {
return lqiTable;
}
/**
* Gets the LQI grid table model.
*
* @return the LQI grid table model.
*/
public LQIGridTableModel getLqiTableModel() {
return lqiTableModel;
}
/*
* (non-Javadoc)
*
* @see
* com.vistatec.ocelot.lqi.gui.TableCellListener#cellValueChanged(com.vistatec
* .ocelot.lqi.gui.TableCellEvent)
*/
@Override
public void cellValueChanged(TableCellEvent e) {
LQIErrorCategory errorCat = lqiTableModel.getErrorCategoryAtRow(e
.getRowIndex());
keyEventManager.categoryNameChanged(errorCat, (String) e.getOldValue());
}
/**
* Saves a new shortcut for the selected cell.
*
* @param keyCode
* the shortcut key code.
* @param modifiers
* the shortcut modifiers.
*/
public void saveShortCut(int keyCode, int[] modifiers) {
LQIErrorCategory errCat = lqiTableModel.getErrorCategoryAtRow(lqiTable
.getSelectedRow());
int selectedColumn = lqiTable.getSelectedColumn();
int modifier = 0;
for (int i = 0; i < modifiers.length; i++) {
modifier += modifiers[i];
}
KeyStroke newShortcut = KeyStroke.getKeyStroke(keyCode, modifier);
KeyStroke oldShortcut = null;
String severityName = null;
LQISeverity severity = lqiTableModel
.getSeverityByColumn(selectedColumn);
if (severity != null) {
severityName = severity.getName();
LQIShortCut catShortcut = errCat.getShortcut(severityName);
if (catShortcut != null) {
oldShortcut = catShortcut.getKeyStroke();
}
lqiTable.getCellEditor(lqiTable.getSelectedRow(),
lqiTable.getSelectedColumn()).stopCellEditing();
lqiTableModel.setShortCut(lqiTable.getSelectedRow(),
lqiTable.getSelectedColumn(), keyCode, modifiers);
keyEventManager.shortCutChanged(errCat, oldShortcut, severityName);
shortcutsInUse.remove(oldShortcut);
shortcutsInUse.add(newShortcut);
}
}
/**
* Handles the event a severity column changes.
*
* @param oldSeverity
* the old severity.
* @param newSeverity
* the new severity.
*/
public void severityColumnChanged(LQISeverity oldSeverity,
LQISeverity newSeverity) {
int columnIndex = lqiTableModel.getSeverityColIndex(oldSeverity
.getName());
try {
LQISeverity oldSevCloned = (LQISeverity) oldSeverity.clone();
if (columnIndex != -1) {
if (oldSevCloned.getScore() != newSeverity.getScore()) {
lqiTableModel.setScoreForColumn(newSeverity.getScore(),
columnIndex);
keyEventManager.errorSeverityScoreChanged(
newSeverity.getScore(), oldSevCloned.getName());
}
if (!oldSevCloned.getName().equals(newSeverity.getName())) {
lqiTableModel.setNameForSeverityColumn(
newSeverity.getName(), columnIndex);
keyEventManager.errorSeverityNameChanged(lqiTableModel
.getLQIGrid().getErrorCategories(), newSeverity
.getName(), oldSevCloned.getName());
}
if (oldSevCloned.getScore() == newSeverity.getScore()
&& !oldSevCloned.getName()
.equals(newSeverity.getName())) {
lqiTable.getTableHeader()
.getColumnModel()
.getColumn(columnIndex)
.setHeaderValue(
lqiTableModel.getColumnName(columnIndex));
SwingUtilities.windowForComponent(lqiTable).repaint();
} else {
lqiTableModel.sortSeverityColumns();
}
}
} catch (CloneNotSupportedException e) {
// never happens
}
}
/**
* Moves the selected row down.
*/
public void moveSelectedRowDown() {
int selRow = lqiTable.getSelectedRow();
if (selRow != -1) {
if (lqiTable.getCellEditor() != null) {
lqiTable.getCellEditor().stopCellEditing();
}
if (lqiTableModel.moveRowDown(selRow)) {
lqiTable.getSelectionModel().setSelectionInterval(selRow + 1,
selRow + 1);
}
}
}
/**
* Moves the selected row up.
*/
public void moveSelectedRowUp() {
int selRow = lqiTable.getSelectedRow();
if (selRow != -1) {
if (lqiTable.getCellEditor() != null) {
lqiTable.getCellEditor().stopCellEditing();
}
if (lqiTableModel.moveRowUp(selRow)) {
lqiTable.getSelectionModel().setSelectionInterval(selRow - 1,
selRow - 1);
}
}
}
/**
* Displays the dialog for creating a new severity.
*/
public void displayNewSeverityDialog() {
SeverityColumnPropsDialog dialog = new SeverityColumnPropsDialog(
(LQIGridDialog) SwingUtilities.windowForComponent(lqiTable),
null, null);
dialog.setVisible(true);
}
/**
* Handles the event the user clicked on the table header.
*
* @param e
* the mouse event
*/
private void handleClickOnHeaderEvent(MouseEvent e) {
if (lqiTableModel.getMode() == LQIGridDialog.CONFIG_MODE
&& e.getButton() == MouseEvent.BUTTON3) {
JTableHeader tableHeader = (JTableHeader) e.getSource();
final int colIndex = tableHeader.getColumnModel()
.getColumnIndexAtX(e.getX());
LQISeverity severity = lqiTableModel.getSeverityByColumn(colIndex);
if (severity != null) {
mnuDelSeverity.setSeverity(severity);
mnuSeverityProps.setSeverity(severity);
severityMenu.show(tableHeader, e.getX(), e.getY());
}
}
}
/**
* Replace the current configuration with a new one.
*
* @param lqiGridObject
* the new configuration
*/
public void replaceConfiguration(LQIGrid lqiGridObject) {
LQIGrid lqiGridToDiscard = lqiTableModel.getLQIGrid();
lqiTableModel.setLQIGrid(lqiGridObject);
updateTableHeader();
lqiTableModel.setChanged(false);
keyEventManager.removeActions(lqiGridToDiscard);
keyEventManager.load(lqiGridObject);
initUsedShortcutList(lqiGridObject);
}
/**
* Checks if the shortcut defined by given key code and modifiers is a
* reserved one.
*
* @param keyCode
* the key code
* @param modifiers
* the modifiers
* @return <code>true</code> if it is a reserved shortcut;
* <code>false</code> otherwise.
*/
public boolean isReservedShortcut(int keyCode, int[] modifiers) {
int modifier = 0;
for (int i = 0; i < modifiers.length; i++) {
modifier += modifiers[i];
}
KeyStroke shortCut = KeyStroke.getKeyStroke(keyCode, modifier);
return shortcutsInUse.contains(shortCut)
|| ShortCutConstants.getReservedKeyList(platformSupport).contains(shortCut);
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
*/
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() instanceof JTableHeader) {
handleClickOnHeaderEvent(e);
}
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
*/
@Override
public void mousePressed(MouseEvent e) {
if (e.getSource() instanceof JTableHeader) {
handleClickOnHeaderEvent(e);
}
}
/*
* (non-Javadoc)
*
* @see
* java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
*/
@Override
public void mouseReleased(MouseEvent e) {
// does nothing
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
*/
@Override
public void mouseEntered(MouseEvent e) {
// does nothing
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
*/
@Override
public void mouseExited(MouseEvent e) {
// does nothing
}
/**
* Initializes colors for severity columns.
*/
public void initColorForColumns() {
int colNum = lqiTableModel.getSeverityColumnsCount();
columnColors = new Color[colNum];
float p = 1;
double delta = 1.0 / (float) (colNum - 1);
for (int i = 1; i <= colNum; i++) {
float r = getValue(MINOR_COL_COLOR.getRed(),
CRITICAL_COL_COLOR.getRed(), p);
float g = getValue(MINOR_COL_COLOR.getGreen(),
CRITICAL_COL_COLOR.getGreen(), p);
float b = getValue(MINOR_COL_COLOR.getBlue(),
CRITICAL_COL_COLOR.getBlue(), p);
columnColors[i - 1] = new Color((int) r, (int) g, (int) b);
p -= delta;
}
}
private float getValue(float firstValue, float secValue, float p) {
float value = 0;
value = firstValue * p + secValue * (1 - p);
if (value < 0) {
value = 0;
} else if (value > 255) {
value = 255;
}
return value;
}
/**
* Adds a column for a severity passed as parameter.
*
* @param newSeverity
* the new severity
*/
public void addSeverityColumn(LQISeverity newSeverity) {
lqiTableModel.addSeverityColumn(newSeverity);
}
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(mnuDelSeverity)) {
deleteSeverity(mnuDelSeverity.getSeverity());
} else if (e.getSource().equals(mnuSeverityProps)) {
showSeverityPropsDialog(mnuSeverityProps.getSeverity());
}
}
/**
* Deletes a severity. Then the related column is removed.
*
* @param severity
* the severity to me deleted.
*/
private void deleteSeverity(LQISeverity severity) {
int option = JOptionPane.showConfirmDialog(lqiTable,
"Do you want to delete the \"" + severity.getName()
+ "\" column?", "Delete Severity Column",
JOptionPane.YES_NO_OPTION);
if (option == JOptionPane.YES_OPTION) {
System.out.println("Delete");
lqiTableModel.removeSeverityColumn(severity);
keyEventManager.errorSeverityDeleted(lqiTableModel.getLQIGrid()
.getErrorCategories(), severity);
}
}
/**
* Displays the severity property dialog.
*
* @param lqiSeverity
* the severity
*/
private void showSeverityPropsDialog(LQISeverity lqiSeverity) {
System.out.println("Edit");
final SeverityColumnPropsDialog severityDialog = new SeverityColumnPropsDialog(
(LQIGridDialog) SwingUtilities.windowForComponent(lqiTable),
null, lqiSeverity);
severityDialog.setVisible(true);
}
}
/**
* The Severity menu item class.
*/
class SeverityMenuItem extends JMenuItem {
/** The serial version UID. */
private static final long serialVersionUID = 8456313250004675606L;
/** The edit action. */
public static final int EDIT = 0;
/** The delete action. */
public static final int DELETE = 1;
/** The menu item action. */
private int mnuAction;
/** The severity. */
private LQISeverity severity;
/**
* Constructor
*
* @param text
* the menu item text
* @param mnuAction
* the action
*/
public SeverityMenuItem(String text, int mnuAction) {
super(text);
this.mnuAction = mnuAction;
}
/**
* Gets the menu item action.
*
* @return the menu item action.
*/
public int getMnuAction() {
return mnuAction;
}
/**
* Sets the severity.
*
* @param severity
* the severity.
*/
public void setSeverity(LQISeverity severity) {
this.severity = severity;
}
/**
* Gets the severity.
*
* @return the severity.
*/
public LQISeverity getSeverity() {
return severity;
}
}