/********************************************************************************
* *
* (c) Copyright 2010 Verizon Communications USA and The Open University UK *
* *
* This software is freely distributed in accordance with *
* the GNU Lesser General Public (LGPL) license, version 3 or later *
* as published by the Free Software Foundation. *
* For details see LGPL: http://www.fsf.org/licensing/licenses/lgpl.html *
* and GPL: http://www.fsf.org/licensing/licenses/gpl-3.0.html *
* *
* This software is provided by the copyright holders and contributors "as is" *
* and any express or implied warranties, including, but not limited to, the *
* implied warranties of merchantability and fitness for a particular purpose *
* are disclaimed. In no event shall the copyright owner or contributors be *
* liable for any direct, indirect, incidental, special, exemplary, or *
* consequential damages (including, but not limited to, procurement of *
* substitute goods or services; loss of use, data, or profits; or business *
* interruption) however caused and on any theory of liability, whether in *
* contract, strict liability, or tort (including negligence or otherwise) *
* arising in any way out of the use of this software, even if advised of the *
* possibility of such damage. *
* *
********************************************************************************/
package com.compendium.ui.tags;
import java.awt.Component;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DragSource;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Vector;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.compendium.LanguageProperties;
import com.compendium.ProjectCompendium;
import com.compendium.core.datamodel.NodeSummary;
import com.compendium.core.datamodel.View;
import com.compendium.ui.ProjectCompendiumFrame;
import com.compendium.ui.TableSorter;
import com.compendium.ui.UITableHeaderRenderer;
import com.compendium.ui.panels.UIHintNodeCodePanel;
import com.compendium.ui.panels.UIHintNodeViewsPanel;
/**
* This class controls the tags working table area.
*
* @author Michelle Bachler
*/
public class UIWorkingList implements TableModelListener, MouseListener, MouseMotionListener, PropertyChangeListener /*,
DragSourceListener, DragGestureListener, Transferable*/ {
static final Logger log = LoggerFactory.getLogger(UIWorkingList.class);
/** Table that holds the list data for this list view.*/
private JTable table;
/** The model for the data in the list view table.*/
private UITagsListTableModel model;
/** The table sort for the table for this list view.*/
private TableSorter sorter;
/** The crop target reference for this list instance.*/
//private DropTarget dropTarget = null;
/** The dialog used for the rollover hints.*/
private JDialog dialog = null;
/** The last row the rollover hint was for.*/
int lastRow = -1;
/** The last column the rollover hint was for.*/
int lastColumn = -1;
/** The data flavors supported by this class.*/
public static final DataFlavor[] supportedFlavors = { null };
static {
try { supportedFlavors[0] = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType); }
catch (Exception ex) { log.error("Error...", ex); }
}
/** The DragSource object associated with this node list.*/
private DragSource dragSource;
/**
* Constructor. Initializes and table and options for this list.
*/
public UIWorkingList() {
model = new UITagsListTableModel();
sorter = new TableSorter(model);
sorter.addTableModelListener(this);
table = new JTable(sorter);
//CSH.setHelpIDString(table,"node.views");
table.getColumn(LanguageProperties.getString(LanguageProperties.TAGS_BUNDLE, "UIWorkingList.img")).setPreferredWidth(10); //$NON-NLS-1$
table.getColumn(LanguageProperties.getString(LanguageProperties.TAGS_BUNDLE, "UIWorkingList.tags")).setPreferredWidth(10); //$NON-NLS-1$
table.getColumn(LanguageProperties.getString(LanguageProperties.TAGS_BUNDLE, "UIWorkingList.views")).setPreferredWidth(10); //$NON-NLS-1$
table.getColumn(LanguageProperties.getString(LanguageProperties.TAGS_BUNDLE, "UIWorkingList.label")).setPreferredWidth(300); //$NON-NLS-1$
table.getColumn(LanguageProperties.getString(LanguageProperties.TAGS_BUNDLE, "UIWorkingList.modedate")).setPreferredWidth(150); //$NON-NLS-1$
table.getColumn(LanguageProperties.getString(LanguageProperties.TAGS_BUNDLE, "UIWorkingList.img")).setMaxWidth(60); //$NON-NLS-1$
table.getColumn(LanguageProperties.getString(LanguageProperties.TAGS_BUNDLE, "UIWorkingList.tags")).setMaxWidth(60); //$NON-NLS-1$
table.getColumn(LanguageProperties.getString(LanguageProperties.TAGS_BUNDLE, "UIWorkingList.views")).setMaxWidth(60); //$NON-NLS-1$
table.getColumn(LanguageProperties.getString(LanguageProperties.TAGS_BUNDLE, "UIWorkingList.modedate")).setMaxWidth(200); //$NON-NLS-1$
table.getTableHeader().setReorderingAllowed(false);
sorter.addMouseListenerToHeaderInTable(table);
table.addMouseMotionListener(this);
table.addMouseListener(this);
table.setFont(ProjectCompendiumFrame.currentDefaultFont);
FontMetrics metrics = table.getFontMetrics(ProjectCompendiumFrame.currentDefaultFont);
table.setRowHeight(table.getRowMargin()+metrics.getHeight());
setRenderers();
((TableSorter)table.getModel()).setSelectedColumn(3);
//dragSource = new DragSource();
//dragSource.createDefaultDragGestureRecognizer((Component)this.table, DnDConstants.ACTION_COPY, this);
}
/**
* Return the font size to its default and then appliy the passed text zoom.
* (To the default specificed by the user in the Project Options)
*/
public void onReturnTextAndZoom(int zoom) {
Font font = table.getFont();
Font newFont = new Font(font.getName(), font.getStyle(), font.getSize()+zoom);
table.setFont(newFont);
FontMetrics metrics = table.getFontMetrics(newFont);
table.setRowHeight(table.getRowMargin()+metrics.getHeight());
}
/**
* Return the font size to its default
* (To the default specificed by the user in the Project Options)
*/
public void onReturnTextToActual() {
table.setFont(ProjectCompendiumFrame.currentDefaultFont);
FontMetrics metrics = table.getFontMetrics(ProjectCompendiumFrame.currentDefaultFont);
table.setRowHeight(table.getRowMargin()+metrics.getHeight());
}
/**
* Increase the currently dislayed font size by one point.
*/
public void onIncreaseTextSize() {
Font font = table.getFont();
Font newFont = new Font(font.getName(), font.getStyle(), font.getSize()+1);
table.setFont(newFont);
FontMetrics metrics = table.getFontMetrics(newFont);
table.setRowHeight(table.getRowMargin()+metrics.getHeight());
}
/**
* Reduce the currently dislayed font size by one point.
*/
public void onReduceTextSize() {
Font font = table.getFont();
Font newFont = new Font(font.getName(), font.getStyle(), font.getSize()-1);
table.setFont(newFont);
FontMetrics metrics = table.getFontMetrics(newFont);
table.setRowHeight(table.getRowMargin()+metrics.getHeight());
}
public void clearPopup() {
if (dialog != null) {
dialog.setVisible(false);
dialog.dispose();
dialog = null;
lastRow = -1;
lastColumn = -1;
}
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e){}
public void mouseClicked(MouseEvent e) {
if (lastColumn == UITagsListTableModel.VIEWS_COLUMN) {
clearPopup();
}
}
public void mouseExited(MouseEvent e) {
if (lastColumn == UITagsListTableModel.TAGS_COLUMN) {
clearPopup();
}
}
public void mouseDragged(MouseEvent e){}
public void mouseMoved(MouseEvent e) {
int column = table.columnAtPoint( e.getPoint() );
int row = table.rowAtPoint( e.getPoint() );
int ind = sorter.getRealRow(row);
if (ind == -1) {
return;
}
if (ind == lastRow && column == lastColumn) {
e.consume();
return;
}
if (column == UITagsListTableModel.TAGS_COLUMN) {
clearPopup();
NodeSummary summary = getNodeAt(row);
try {
if (summary.getCodeCount() > 0 ) {
UIHintNodeCodePanel pop = new UIHintNodeCodePanel(summary, 0, 0);
dialog = new JDialog(ProjectCompendium.APP);
lastRow = ind;
lastColumn = column;
dialog.add(pop);
dialog.setUndecorated(true);
dialog.pack();
Point point = e.getPoint();
SwingUtilities.convertPointToScreen(point, table);
//Point point = SwingUtilities.convertPoint(table, e.getPoint(), ProjectCompendium.APP);
dialog.setLocation(point.x+5, point.y);
dialog.setVisible(true);
}
}
catch(Exception ex) {
log.info("Error: (UIWorkingList.showCodes)\n\n"+ex.getMessage()); //$NON-NLS-1$
}
} if (column == UITagsListTableModel.VIEWS_COLUMN) {
clearPopup();
NodeSummary summary = getNodeAt(row);
try {
UIHintNodeViewsPanel pop = new UIHintNodeViewsPanel(summary, 0, 0);
dialog = new JDialog(ProjectCompendium.APP);
lastRow = ind;
lastColumn = column;
dialog.add(pop);
dialog.setUndecorated(true);
dialog.pack();
Point point = e.getPoint();
SwingUtilities.convertPointToScreen(point, table);
//Point point = SwingUtilities.convertPoint(table, e.getPoint(), ProjectCompendium.APP);
dialog.setLocation(point.x+5, point.y);
dialog.setVisible(true);
}
catch(Exception ex) {
log.info("Error: (UIWorkingList.showViews)\n\n"+ex.getMessage()); //$NON-NLS-1$
}
}
}
public void hideHint() {
if (dialog != null) {
dialog.setVisible(false);
dialog.dispose();
dialog = null;
lastRow = -1;
lastColumn = -1;
}
}
/*private class myViewsPanel extends UIHintNodeViewsPanel {
public myViewsPanel(NodeSummary node, int xPos, int yPos) {
super(node, xPos, yPos);
}
protected MouseListener createMouseListener() {
MouseListener mouse = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int index = lstViews.locationToIndex( e.getPoint());
String id = "";
View view = (View)views.elementAt(index);
id = view.getId();
if ( !id.equals(currentView.getId())) {
if (!htUserViews.containsKey(view.getId())
|| id.equals(ProjectCompendium.APP.getInBoxID())) {
UIViewFrame oUIViewFrame = ProjectCompendium.APP.addViewToDesktop(view, view.getLabel());
Vector history = new Vector();
history.addElement(new String(sTitle));
oUIViewFrame.setNavigationHistory(history);
if (oUIViewFrame instanceof UIMapViewFrame) {
UIViewPane oPane = ((UIMapViewFrame)oUIViewFrame).getViewPane();
oPane.hideViews();
UINode oUINode = (UINode) oPane.get(oNode.getId());
if (oUINode != null) {
JViewport viewport = oUIViewFrame.getViewport();
Rectangle nodeBounds = oUINode.getBounds();
Point parentPos = SwingUtilities.convertPoint((Component)oPane, nodeBounds.x, nodeBounds.y, viewport);
viewport.scrollRectToVisible( new Rectangle( parentPos.x, parentPos.y, nodeBounds.width, nodeBounds.height ) );
oUINode.setRollover(true);
oUINode.moveToFront();
}
} else {
UIListViewFrame oListViewFrame = (UIListViewFrame)oUIViewFrame;
UIList oUIList = oListViewFrame.getUIList();
int ind = oUIList.getIndexOf(oNode);
if (ind > -1) {
oUIList.getList().addRowSelectionInterval(ind, ind);
}
}
}
}
}
public void mouseExited(MouseEvent evt) {
dialog.setVisible(false);
dialog.dispose();
dialog = null;
lastRow = -1;
lastColumn = -1;
}
};
return mouse;
}
}*/
/**
* Update the table after a change.
*/
public void updateTable() {
sorter.fireTableChanged(new TableModelEvent(table.getModel()));
}
/**
* Display the new data.
* @param vtData
*/
public void refreshTable(Vector vtData) {
// REMOVE PropertyChangeListener from old data and add to new incoming data.
NodeSummary node = null;
Vector vtOldData = model.getData();
int count = vtOldData.size();
for (int i=0; i<count; i++) {
node = (NodeSummary)vtOldData.elementAt(i);
node.removePropertyChangeListener(this);
}
count = vtData.size();
for (int i=0; i<count; i++) {
node = (NodeSummary)vtData.elementAt(i);
node.addPropertyChangeListener(this);
}
int sort = sorter.getSelectedColumn();
model.removeAllElements();
model.setData(vtData);
sorter.setModel(model);
if (sort > -1) {
sorter.sortByColumn(sort, sorter.getAscending());
}
updateTable();
table.revalidate();
table.repaint();
}
public NodeSummary getNodeAt(int row) {
int realRow = sorter.getRealRow(row);
if (realRow == -1) {
return null;
} else {
return model.getNodeAt(realRow);
}
}
/**
* Process a TableModelEvent, when something has changed in the data.
* Refresh the table and repaint.
* @param tme, the associated TableModelEvent.
*/
public void tableChanged(TableModelEvent tme) {
table.invalidate();
table.repaint();
}
/**
* Set the header renderers for the table column headers and the table cells.
*/
public void setRenderers() {
int count = table.getModel().getColumnCount();
for (int i = 0; i < count; i++) {
TableColumn aColumn = table.getColumnModel().getColumn(i);
// Set the cell renderer for the column headers
UITableHeaderRenderer headerRenderer = new UITableHeaderRenderer();
aColumn.setHeaderRenderer(headerRenderer);
// Set the cell renderer for column cells
CellRenderer cellRenderer = new CellRenderer();
aColumn.setCellRenderer(cellRenderer);
}
}
/**
* The helper class renderers the table cells.
*/
public class CellRenderer extends DefaultTableCellRenderer {
CellRenderer() {
super();
setHorizontalAlignment(SwingConstants.LEFT);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
setFont(table.getFont());
setBorder( isSelected ?UIManager.getBorder("List.focusCellHighlightBorder") : new EmptyBorder(1,1,1,1)); //$NON-NLS-1$
if (isSelected) {
setBackground(table.getSelectionBackground());
setForeground(table.getSelectionForeground());
if(column == UITagsListTableModel.IMAGE_COLUMN){
setIcon( (Icon) value);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
value = ""; //$NON-NLS-1$
}
}
else {
setBackground(table.getBackground());
setForeground(table.getForeground());
if (column == UITagsListTableModel.IMAGE_COLUMN) {
setIcon( (Icon) value);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
value = ""; //$NON-NLS-1$
}
}
setValue(value);
return this;
}
protected void setValue(Object value) {
setText((value == null) ? "" : value.toString()); //$NON-NLS-1$
}
}
/**
* Return the JTable that holds the view list.
* @return JTable, the JTable that holds the view list.
*/
public JTable getList() {
return table;
}
/**
* Return the number of currently selected node in the list.
* @return int, the number of currently selected node in the list.
*/
public int getNumberOfSelectedNodes() {
return table.getSelectedRowCount();
}
/**
* Deselect all selected rows.
*/
public void deselectAll() {
table.clearSelection();
}
/**
* Return the number of nodes currently in this list view.
* @return int, the number of nodes currently in this list view.
*/
public int getNumberOfNodes() {
return table.getRowCount();
}
// PROPERTY CHANGE EVENT METHOD
/**
* Handle a PropertyChangeEvent.
* @param evt, the associated PropertyChangeEvent to handle.
*/
public void propertyChange(PropertyChangeEvent evt) {
String prop = evt.getPropertyName();
Object source = evt.getSource();
//Object oldvalue = evt.getOldValue();
//Object newvalue = evt.getNewValue();
if (source instanceof NodeSummary) {
if (prop.equals(NodeSummary.LABEL_PROPERTY) || prop.equals(View.CHILDREN_PROPERTY)) {
table.revalidate();
table.repaint();
}
/*if (prop.equals(NodeSummary.TAG_PROPERTY)) {
firePropertyChange(NodeSummary.TAG_PROPERTY, oldvalue, newvalue);
}
else if (prop.equals(NodeSummary.NODE_TYPE_PROPERTY)) {
}
else if (prop.equals(NodeSummary.VIEW_NUM_PROPERTY)) {
firePropertyChange(NodeSummary.VIEW_NUM_PROPERTY, oldvalue, newvalue);
}
else if (prop.equals(NodeSummary.STATE_PROPERTY)) {
firePropertyChange(NodeSummary.STATE_PROPERTY, oldvalue, newvalue);
}
else if (prop.equals(View.CHILDREN_PROPERTY)) {
firePropertyChange(CHILDREN_PROPERTY, oldvalue, newvalue);
}*/
}
}
// DRAG AND DROP METHODS
/**
* Returns an array of DataFlavor objects indicating the flavors the data
* can be provided in.
* @return an array of data flavors in which this data can be transferred
*/
/*public DataFlavor[] getTransferDataFlavors() {
return supportedFlavors;
}*/
/**
* Returns whether or not the specified data flavor is supported for
* this object.
* @param flavor the requested flavor for the data
* @return boolean indicating whether or not the data flavor is supported
*/
/*public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType);
}*/
/**
* Returns an object which represents the data to be transferred. The class
* of the object returned is defined by the representation class of the flavor.
*
* @param flavor the requested flavor for the data
* @see DataFlavor#getRepresentationClass
* @exception IOException if the data is no longer available in the requested flavor.
* @exception UnsupportedFlavorException if the requested data flavor is not supported.
*/
/*public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType))
return this;
else return null;
}*/
/**
* A <code>DragGestureRecognizer</code> has detected
* a platform-dependent drag initiating gesture and
* is notifying this listener
* in order for it to initiate the action for the user.
* <P>
* @param e the <code>DragGestureEvent</code> describing
* the gesture that has just occurred
*/
/*public void dragGestureRecognized(DragGestureEvent e) {
InputEvent in = e.getTriggerEvent();
if (in instanceof MouseEvent) {
MouseEvent evt = (MouseEvent)in;
boolean isLeftMouse = SwingUtilities.isLeftMouseButton(evt);
if (isLeftMouse && !evt.isAltDown()) {
dragSource.startDrag(e, DragSource.DefaultCopyDrop, this, this);
}
}
}*/
/**
* This method is invoked to signify that the Drag and Drop
* operation is complete. The getDropSuccess() method of
* the <code>DragSourceDropEvent</code> can be used to
* determine the termination state. The getDropAction() method
* returns the operation that the drop site selected
* to apply to the Drop operation. Once this method is complete, the
* current <code>DragSourceContext</code> and
* associated resources become invalid.
* HERE THE METHOD DOES NOTHING.
*
* @param e the <code>DragSourceDropEvent</code>
*/
//public void dragDropEnd(DragSourceDropEvent e) {}
/**
* Called as the cursor's hotspot enters a platform-dependent drop site.
* This method is invoked when all the following conditions are true:
* <UL>
* <LI>The cursor's hotspot enters the operable part of a platform-
* dependent drop site.
* <LI>The drop site is active.
* <LI>The drop site accepts the drag.
* </UL>
* HERE THE METHOD DOES NOTHING.
*
* @param e the <code>DragSourceDragEvent</code>
*/
//public void dragEnter(DragSourceDragEvent e) {}
/**
* Called as the cursor's hotspot exits a platform-dependent drop site.
* This method is invoked when any of the following conditions are true:
* <UL>
* <LI>The cursor's hotspot no longer intersects the operable part
* of the drop site associated with the previous dragEnter() invocation.
* </UL>
* OR
* <UL>
* <LI>The drop site associated with the previous dragEnter() invocation
* is no longer active.
* </UL>
* OR
* <UL>
* <LI> The current drop site has rejected the drag.
* </UL>
* HERE THE METHOD DOES NOTHING.
*
* @param e the <code>DragSourceEvent</code>
*/
//public void dragExit(DragSourceEvent e) {}
/**
* Called as the cursor's hotspot moves over a platform-dependent drop site.
* This method is invoked when all the following conditions are true:
* <UL>
* <LI>The cursor's hotspot has moved, but still intersects the
* operable part of the drop site associated with the previous
* dragEnter() invocation.
* <LI>The drop site is still active.
* <LI>The drop site accepts the drag.
* </UL>
* HERE THE METHOD DOES NOTHING.
*
* @param e the <code>DragSourceDragEvent</code>
*/
//public void dragOver(DragSourceDragEvent e) {}
/**
* Called when the user has modified the drop gesture.
* This method is invoked when the state of the input
* device(s) that the user is interacting with changes.
* Such devices are typically the mouse buttons or keyboard
* modifiers that the user is interacting with.
* HERE THE METHOD DOES NOTHING.
*
* @param e the <code>DragSourceDragEvent</code>
*/
//public void dropActionChanged(DragSourceDragEvent e) {}
}