/********************************************************************************
* *
* (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;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.border.AbstractBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.compendium.LanguageProperties;
import com.compendium.ProjectCompendium;
import com.compendium.core.ICoreConstants;
import com.compendium.core.datamodel.IModel;
import com.compendium.core.datamodel.ModelSessionException;
import com.compendium.core.datamodel.NodePosition;
import com.compendium.core.datamodel.NodeSummary;
import com.compendium.core.datamodel.PCSession;
import com.compendium.core.datamodel.View;
import com.compendium.ui.popups.UIViewUnreadPopupMenu;
/**
* This class is used to display unread view
* @author Lakshmi Prabhakaran
*
*/
public class UIViewUnread extends JPanel implements IUIConstants , TreeSelectionListener , PropertyChangeListener {
static final Logger log = LoggerFactory.getLogger(UIViewUnread.class);
/** The serial version id */
private static final long serialVersionUID = 4469006144090220368L;
/** The colour to use for selected text in the node label.*/
private static final Color SELECTED_TEXT_COLOR = Color.black;
/** The name of the project in the outline view.*/
private String sProject = ""; //$NON-NLS-1$
/** The cache model for the currently open database.*/
private IModel oModel = ProjectCompendium.APP.getModel();
/** The session for this model.*/
private PCSession oSession = null;
/** The user Id of the current user */
private String userID = ""; //$NON-NLS-1$
/** Has this panel been drawn yet?*/
private boolean drawn = false;
/** The JTree to display unread view */
private JTree tree = null;
/** The root Node of the tree */
protected DefaultMutableTreeNode rootNode = null;
/** Hashtable containing vector of unread nodes against the view */
private Hashtable htViewsNodes = new Hashtable();
/** Vector of the unread view nodes */
private Vector vtUnreadViews = new Vector();
/** Vector of the view nodes */
private Vector vtViews = new Vector();
/** node id against a list of tree nodes */
private Hashtable htTreeNodes = new Hashtable();
/** Node summary against their views */
private Hashtable htNodeAndViews = new Hashtable();
/** Currently selected node */
private UIViewOutlineTreeNode selectedNode = null;
/** Total unread nodes */
private int nUnread = 0;
/** Label to display number of unread nodes */
private JLabel lblUnread = new JLabel();
/**
/**
* Constructor.
* @param sProject, The name of the database in the unread view.
*/
public UIViewUnread(String sProject) {
this.sProject = sProject;
this.userID = oModel.getUserProfile().getId();
oSession = oModel.getSession();
}
/**
* Draws the contents of this panel.
*/
public void draw() {
ProjectCompendium.APP.setWaitCursor();
setLayout(new BorderLayout());
UIViewOutlineTreeNode node = new UIViewOutlineTreeNode(sProject, -1);
rootNode = new DefaultMutableTreeNode(node);
DefaultTreeModel treeModel = new DefaultTreeModel(rootNode);
tree = new JTree(treeModel);
tree.setFont(ProjectCompendiumFrame.currentDefaultFont);
createTree();
// Create a tree that allows one selection at a time.
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setEditable(false);
tree.setShowsRootHandles(true);
tree.setToggleClickCount(4);
// Set the icon for nodes.
TreeNodeRenderer renderer = new TreeNodeRenderer();
tree.setCellRenderer(renderer);
// Enable tool tips.
ToolTipManager.sharedInstance().registerComponent(tree);
// Listen for the changes.
tree.addTreeSelectionListener(this);
tree.addFocusListener(new FocusAdapter(){
public void focusGained(FocusEvent arg0) {
TreePath path = tree.getSelectionPath();
if(path != null){
DefaultMutableTreeNode treeNode = (((DefaultMutableTreeNode) path.getLastPathComponent()));
UIViewOutlineTreeNode node =(UIViewOutlineTreeNode)treeNode.getUserObject();
if( treeNode != rootNode){
setStatus(node.getObject());
}
}else{
ProjectCompendium.APP.setStatus(""); //$NON-NLS-1$
}
}
public void focusLost(FocusEvent arg0) {
ProjectCompendium.APP.setStatus(""); //$NON-NLS-1$
}
});
tree.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if(tree.isFocusOwner() && selectedNode != null){
if (selectedNode != null && selectedNode != rootNode.getUserObject()){
if((e.getKeyCode() == KeyEvent.VK_F12 && e.getModifiers() == 0)){
onMarkSeenUnseen(selectedNode.getObject(), ICoreConstants.READSTATE);
e.consume();
} else if((e.getModifiers() == Event.SHIFT_MASK && e.getKeyCode() == KeyEvent.VK_F12)){
onMarkSeenUnseen(selectedNode.getObject(), ICoreConstants.UNREADSTATE);
e.consume();
}
}
}
}
});
tree.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent evt) {
TreePath selPath = tree.getPathForLocation(evt.getX(), evt.getY());
UIViewOutlineTreeNode parentNode = null;
UIViewOutlineTreeNode childNode = null;
DefaultMutableTreeNode treeNode = null;
boolean isRightMouse = SwingUtilities.isRightMouseButton(evt);
boolean isLeftMouse = SwingUtilities.isLeftMouseButton(evt);
if (ProjectCompendium.isMac &&
(evt.getButton() == 3 && evt.isShiftDown()) ||
(evt.getButton() == 1 && evt.isAltDown())) {
isRightMouse = true;
isLeftMouse = false;
}
if(selPath != null ) {
treeNode = (((DefaultMutableTreeNode) selPath.getLastPathComponent()));
childNode =(UIViewOutlineTreeNode)treeNode.getUserObject();
if(!treeNode.equals(rootNode)){
if(tree.isFocusOwner() && isLeftMouse){
NodeSummary node = childNode.getObject();
//setStatus
setStatus(node);
if (evt.getClickCount() == 2){
// Open the view if it is a Map/ List other wise open the parent view.
if( View.isViewType(childNode.getType())) {
parentNode = childNode;
} else {
DefaultMutableTreeNode parent = null;
Object[] nodes = (Object[]) selPath.getPath();
// parent view is the node at level 1
parent = (DefaultMutableTreeNode)nodes[1];
parentNode = (UIViewOutlineTreeNode) parent.getUserObject();
}
View parentView = View.getView(parentNode.getId());
NodeSummary child = (NodeSummary)childNode.getObject();
openView(parentView, child);
}
} else if(tree.isFocusOwner() && isRightMouse){
tree.setSelectionPath(selPath);
NodeSummary node = (NodeSummary)childNode.getObject();
if ((node.getId()).equals(ProjectCompendium.APP.getInBoxID())){
return ;
}
UIViewUnreadPopupMenu popup = new UIViewUnreadPopupMenu (LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.popupMenuTitle"), node, UIViewUnread.this); //$NON-NLS-1$
popup.show(tree, evt.getX(),evt.getY());
}
}
tree.requestFocus();
evt.consume();
}
}
});
//keep all nodes expanded
tree.expandPath(tree.getPathForRow(0));
int count = rootNode.getChildCount();
for(int i = count; i >= 1 ; i--){
if(tree.getPathForRow(i) != null && (!rootNode.getChildAt(i-1).isLeaf())){
tree.expandPath(tree.getPathForRow(i));
}
}
Dimension size = tree.getPreferredSize();
JScrollPane oScrollPane = new JScrollPane(tree);
oScrollPane.setBackground(Color.white);
oScrollPane.setPreferredSize(new Dimension(300, size.height));
add(oScrollPane, BorderLayout.CENTER);
JPanel panel = new JPanel();
GridBagLayout grid = new GridBagLayout();
panel.setLayout(grid);
GridBagConstraints gc = new GridBagConstraints();
gc.insets = new Insets(5,5,5,5);
gc.anchor = GridBagConstraints.WEST;
int y = 0;
JLabel label = new JLabel(LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.totalUnread")+"="); //$NON-NLS-1$ //$NON-NLS-2$
label.setBounds(10,10,10,10);
gc.gridy = y;
gc.gridx = 0;
grid.setConstraints(label, gc);
panel.add(label);
gc.gridx = 1;
grid.setConstraints(lblUnread, gc);
panel.add(lblUnread);
lblUnread.setText(String.valueOf(nUnread));
gc.gridx = 2;
gc.gridheight = 2;
gc.weightx = 1;
gc.anchor = GridBagConstraints.EAST;
JPanel oButtonPanel = createButtonPanel();
grid.setConstraints(oButtonPanel, gc);
panel.add(oButtonPanel);
add(panel, BorderLayout.SOUTH);
drawn = true;
ProjectCompendium.APP.setDefaultCursor();
}
/**
* Create and return the button panel.
*/
private JPanel createButtonPanel() {
JPanel oButtonPanel = new JPanel();
UIButton pbRefresh = new UIButton(LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.refreshButton")); //$NON-NLS-1$
pbRefresh.setMnemonic(LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.refreshButtonMnemonic").charAt(0)); //$NON-NLS-1$
pbRefresh.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ProjectCompendium.APP.setWaitCursor();
refresh();
ProjectCompendium.APP.setDefaultCursor();
}
});
oButtonPanel.add(pbRefresh);
UIButton pbCancel = new UIButton(LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.closeButton")); //$NON-NLS-1$
pbCancel.setMnemonic(LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.closeButtonMnemonic").charAt(0)); //$NON-NLS-1$
pbCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ProjectCompendium.APP.getMenuManager().removeUnreadView(true);
}
});
oButtonPanel.add(pbCancel);
return oButtonPanel;
}
/**
* 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 = ProjectCompendiumFrame.currentDefaultFont;
Font newFont = new Font(font.getName(), font.getStyle(), font.getSize()+zoom);
tree.setFont(newFont);
FontMetrics metrics = tree.getFontMetrics(newFont);
tree.setRowHeight(metrics.getHeight());
}
/**
* Return the font size to its default
* (To the default specificed by the user in the Project Options)
*/
public void onReturnTextToActual() {
tree.setFont(ProjectCompendiumFrame.currentDefaultFont);
FontMetrics metrics = tree.getFontMetrics(ProjectCompendiumFrame.currentDefaultFont);
tree.setRowHeight(metrics.getHeight());
}
/**
* Increase the currently dislayed font size by one point.
*/
public void onIncreaseTextSize() {
Font font = tree.getFont();
Font newFont = new Font(font.getName(), font.getStyle(), font.getSize()+1);
tree.setFont(newFont);
FontMetrics metrics = tree.getFontMetrics(newFont);
tree.setRowHeight(metrics.getHeight());
}
/**
* Reduce the currently dislayed font size by one point.
*/
public void onReduceTextSize() {
Font font = tree.getFont();
Font newFont = new Font(font.getName(), font.getStyle(), font.getSize()-1);
tree.setFont(newFont);
FontMetrics metrics = tree.getFontMetrics(newFont);
tree.setRowHeight(metrics.getHeight());
}
/**
* returns true if the panel is drawn.
* @return Returns the drawn.
*/
public boolean isDrawn() {
return drawn;
}
/**
* adds nodes to the tree depending on the option selected
*
*/
public void createTree(){
rootNode.removeAllChildren();
nUnread = 0;
try {
View homeView = oModel.getUserProfile().getHomeView();
homeView.initialize(oSession, oModel);
vtViews.add(homeView);
getAllNodes(homeView);
} catch (SQLException e) {
log.error("Error...", e);
}
for(int i = 0; i< vtViews.size(); i++){
View view = (View) vtViews.get(i);
view.initialize(oSession, oModel);
if(htViewsNodes.containsKey(view)){
UIViewOutlineTreeNode treeNode = new UIViewOutlineTreeNode(view);
DefaultMutableTreeNode oTreeNode = new DefaultMutableTreeNode(treeNode);
// add to listeners
if(!view.getListenerList().contains(this)){
view.addPropertyChangeListener(this);
}
if(view.getState() == ICoreConstants.UNREADSTATE)
nUnread ++ ;
Vector nodes = new Vector();
nodes.add(oTreeNode);
htTreeNodes.put(view.getId(), nodes);
UIArrangeLeftRight arrange = new UIArrangeLeftRight();
if (view != null)
arrange.processView(view);
Vector vtNodes = (Vector) htViewsNodes.get(view);
for(int j = 0;j < vtNodes.size(); j++){
NodeSummary node = (NodeSummary) vtNodes.get(j);
node.initialize(oSession, oModel);
UIViewOutlineTreeNode childNode = new UIViewOutlineTreeNode(node);
DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(childNode);
// add to listeners
if(!node.getListenerList().contains(this)){
node.addPropertyChangeListener(this);
}
if(node.getState() == ICoreConstants.UNREADSTATE){
nUnread ++ ;
oTreeNode.add(childTreeNode);
}
if(htTreeNodes.containsKey(node.getId())){
Vector vtTreeNodes = (Vector) htTreeNodes.get(node.getId());
if(!vtTreeNodes.contains(childTreeNode))
vtTreeNodes.add(childTreeNode);
} else {
Vector vtTreeNodes = new Vector();
vtTreeNodes.add(childTreeNode);
htTreeNodes.put(node.getId(), vtTreeNodes);
}
}
if((view.getState() == ICoreConstants.UNREADSTATE) || oTreeNode.getChildCount() > 0 ){
if(view.equals(ProjectCompendium.APP.getInBoxView())){
rootNode.insert(oTreeNode, 0);
} else {
rootNode.add(oTreeNode);
}
}
}
}
lblUnread.setText(String.valueOf(nUnread));
}
/**
*
* @param view
* @return
* @throws SQLException
*/
public Hashtable getAllNodes(NodeSummary view) throws SQLException{
String viewID = view.getId();
Vector viewNodes = new Vector();
Enumeration nodes = oModel.getNodeService().getChildNodes(oSession, viewID);
int count = 0;
for(Enumeration e = nodes; e.hasMoreElements();){
NodeSummary nsum = (NodeSummary)e.nextElement();
if(View.isViewType(nsum.getType())) {
if(!vtViews.contains(nsum)){
vtViews.add(nsum);
viewNodes.add(nsum);
}
if(!htViewsNodes.containsKey(nsum)){
htViewsNodes.put(nsum, new Vector());
}
} else {
//store all views against the nodes. It is used when adding a node in the unread view due to state change
if(!htNodeAndViews.containsKey(nsum)){
Vector vtNodes = new Vector();
vtNodes.add(view);
htNodeAndViews.put(nsum, vtNodes);
} else {
Vector vtNodes = (Vector) htNodeAndViews.get(nsum);
if(!vtNodes.contains(view))
vtNodes.add(view);
}//end if
//it is used for populating the tree
if(!htViewsNodes.containsKey(view)){
Vector vtNodes = new Vector();
vtNodes.add(nsum);
htViewsNodes.put(view, vtNodes);
} else {
Vector vtNodes = (Vector) htViewsNodes.get(view);
vtNodes.add(nsum);
}//end if
}// end else
} //end for
for(int i = 0; i < viewNodes.size(); i++){
NodeSummary childView = (View) viewNodes.get(i);
getAllNodes(childView);
}
return htViewsNodes;
}
/**
* Opens the given view and highlights the given node
* @param viewSum, View to be opened
* @param ns, NodeSummary of the node to be highlighted
*/
public void openView(View viewSum, NodeSummary ns) {
try {
View view = viewSum;
view.initialize(oSession, oModel);
view.initializeMembers();
UIViewFrame viewFrame = ProjectCompendium.APP.addViewToDesktop(view, view.getLabel());
viewFrame.setNavigationHistory(viewFrame.getChildNavigationHistory());
if(!viewSum.equals(ns)){
if(viewFrame instanceof UIMapViewFrame) {
UIMapViewFrame mapViewFrame = (UIMapViewFrame) viewFrame;
UIViewPane viewPane = mapViewFrame.getViewPane();
//get the uinode components in the viewpane layer
Component nodearray[] = viewPane.getComponentsInLayer((UIViewPane.NODE_LAYER).intValue());
int i=0; UINode uinode = null;
while(i < nodearray.length) {
uinode = (UINode)nodearray[i++];
if(uinode.getNode().equals(ns)){
viewPane.setSelectedNode(uinode, ICoreConstants.SINGLESELECT);
if(uinode.isFocusOwner() == false) {
uinode.setFocusable(true);
}
if(uinode.isSelected() == false)
uinode.setSelected(true);
JViewport port = mapViewFrame.getViewport();
Point nodePos = uinode.getNodePosition().getPos();
Dimension dim = port.getExtentSize();
int portX = (int) ((dim.width/2) - uinode.getWidth());
int portY = (int) ((dim.height/2) - uinode.getHeight());
Point parentPos = SwingUtilities.convertPoint((Component)viewPane, nodePos.x, nodePos.y, port);
int hAdjust = parentPos.x - portX;
int vAdjust = parentPos.y - portY;
int currentV = mapViewFrame.getVerticalScrollBarPosition();
int currentH = mapViewFrame.getHorizontalScrollBarPosition();
mapViewFrame.setVerticalScrollBarPosition(currentV + vAdjust, false);
mapViewFrame.setHorizontalScrollBarPosition(currentH + hAdjust, false);
viewPane.setZoom(1.0);
viewPane.scale();
break;
}
}
} else if(viewFrame instanceof UIListViewFrame){
UIListViewFrame listViewFrame = (UIListViewFrame) viewFrame;
int rowIndex = listViewFrame.getUIList().getIndexOf(ns);
listViewFrame.getUIList().selectNode(rowIndex, ICoreConstants.SINGLESELECT);
JTable table = listViewFrame.list;
JScrollPane scrollPane = listViewFrame.getScrollPane();
JViewport port = listViewFrame.getViewport();
Dimension dim = scrollPane.getSize();
int x = 0 ;
int y = (rowIndex * table.getRowHeight())-(dim.height/2);
if (y < 0){
y = 0;
}
Point nodePos = new Point (0, y );
port.setViewPosition(nodePos);
}
}
Vector history = new Vector();
history.addElement(view.getLabel());
viewFrame.setNavigationHistory(history);
} catch (SQLException e) {
log.error("Error...", e);
} catch (ModelSessionException e) {
log.error("Error...", e);
}
}
/**
* Displays the author, creation date and detail in the status bar
* @param oNode NodeSummary of the node
*/
private void setStatus(NodeSummary oNode){
String sStatus = ""; //$NON-NLS-1$
String author = oNode.getAuthor();
String creationDate = (UIUtilities.getSimpleDateFormat("dd, MMMM, yyyy h:mm a").format(oNode.getCreationDate()).toString()); //$NON-NLS-1$
String showtext = author + " " + creationDate +", " + //$NON-NLS-1$ //$NON-NLS-2$
oNode.getDetail();
if (showtext != null) {
showtext = showtext.replace('\n',' ');
showtext = showtext.replace('\r',' ');
showtext = showtext.replace('\t',' ');
sStatus = showtext;
}
ProjectCompendium.APP.setStatus(sStatus);
}
/**
* Returns to the list of nodes associated with the given id
* @return Vector, list of nodes
*/
public Vector getTreeNode(String id) {
Vector v = new Vector();
if(htTreeNodes.containsKey(id)){
v = (Vector) htTreeNodes.get(id) ;
}
return v;
}
/**
* Marks seen/unseen for the given node
* @param node com.compendium.code.datamodel.NodeSummary, the node associated with this menu.
* @param state, the state to set
*/
public void onMarkSeenUnseen(NodeSummary node, int state){
try {
String nodeID = node.getId();
String homeID = ProjectCompendium.APP.getHomeView().getId();
String inboxID = ProjectCompendium.APP.getInBoxID();
if(!(nodeID.equals(homeID) || nodeID.equals(inboxID))) {
node.setState(state);
}
} catch(Exception io) {
if(state == ICoreConstants.READSTATE)
log.info(LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.unableToMarkSeen")); //$NON-NLS-1$
else
log.info(LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.unableToMarkUnseen")); //$NON-NLS-1$
}
}
/**
* Marks seen/unseen for whole view
* @param view com.compendium.code.datamodel.View, the view associated with this menu.
* @param state, the state to set
*/
public void onMarkAll(NodeSummary view, int state){
try {
String viewID = view.getId();
String homeID = ProjectCompendium.APP.getHomeView().getId();
String inboxID = ProjectCompendium.APP.getInBoxID();
if(!(viewID.equals(homeID) || viewID.equals(inboxID))) {
view.setState(state);
}
Enumeration nodes = ProjectCompendium.APP.getModel().getNodeService().getChildNodes(
ProjectCompendium.APP.getModel().getSession(), view.getId());
for(Enumeration e = nodes;e.hasMoreElements();) {
NodeSummary nodeSummary = (NodeSummary)e.nextElement();
String nodeID = nodeSummary.getId();
if(!(nodeID.equals(homeID) || nodeID.equals(inboxID))) {
nodeSummary.setState(state);
}
}
} catch(Exception io) {
if(state == ICoreConstants.READSTATE)
log.info(LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.unableToMarkSeen")); //$NON-NLS-1$
else
log.info(LanguageProperties.getString(LanguageProperties.UI_GENERAL_BUNDLE, "UIViewUnread.unableToMarkUnseen")); //$NON-NLS-1$
}
}
/**
* Repaints the view frames.
* @param views , The views to be refreshed
*/
private void reopenViews(Vector views) {
for(int i = 0; i < views.size(); i++){
View view = (View)views.get(i);
UIViewFrame internalFrame = ProjectCompendium.APP.getInternalFrame(view);
if(internalFrame != null){
ProjectCompendium.APP.getAllFrames().remove(internalFrame);
internalFrame.dispose();
internalFrame = ProjectCompendium.APP.addViewToDesktop(view, view.getLabel());
try {
internalFrame.setClosed(false);
} catch (PropertyVetoException e) {
log.error("Error...", e);
}
if(view.equals(ProjectCompendium.APP.getHomeView())){
String label = " " +oModel.getUserProfile().getUserName() + "\'s " + view.getLabel(); //$NON-NLS-1$ //$NON-NLS-2$
internalFrame.setTitle(label);
internalFrame.setClosable(false);
}
// internalFrame.setNavigationHistory(internalFrame.getChildNavigationHistory());
}
}
}//end of reopenViews
/**
* Refreshes the unread view
*
*/
public void refresh(){
int nCount = rootNode.getChildCount();
for(int i = nCount-1; i >= 0; i--) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) rootNode.getChildAt(i);
int nChild = treeNode.getChildCount();
for(int j = nChild-1; j >= 0 ; j--){
DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(j);
UIViewOutlineTreeNode childNode = (UIViewOutlineTreeNode) child.getUserObject();
if(childNode.getState() == ICoreConstants.READSTATE ||
childNode.getState() == ICoreConstants.MODIFIEDSTATE){
child.removeFromParent();
}
}
if(treeNode.getChildCount() <= 0){
UIViewOutlineTreeNode node = (UIViewOutlineTreeNode) treeNode.getUserObject();
if(node.getState() == ICoreConstants.READSTATE ||
node.getState() == ICoreConstants.MODIFIEDSTATE){
treeNode.removeFromParent();
}
}
}
/*
for (Enumeration e = htTreeNodes.keys(); e.hasMoreElements();){
NodeSummary node = NodeSummary.getNodeSummary((String)e.nextElement());
node.removePropertyChangeListener(this);
}
rootNode.removeAllChildren();
htViewsNodes.clear();
htTreeNodes.clear();
vtViews.clear();
vtUnreadViews.clear();
createTree();
*/
((DefaultTreeModel)tree.getModel()).reload(rootNode);
tree.repaint();
//keep all nodes expanded
tree.expandPath(tree.getPathForRow(0));
int count = rootNode.getChildCount();
for(int i = count; i >= 1 ; i--){
if(tree.getPathForRow(i) != null && (!rootNode.getChildAt(i-1).isLeaf())){
tree.expandPath(tree.getPathForRow(i));
}
}
}//end of refresh
/**
* To remove the given node from the given View in the unread view
* @param view the View in which node is present
* @param ns the nodesummary of the node
*/
public void removeNode(View view, NodeSummary ns){
if(ns instanceof View){
Vector vtNodes = (Vector) getTreeNode(ns.getId());
for(int i = 0; i < vtNodes.size(); i++) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) vtNodes.get(i);
if(treeNode.getParent() != null) {
if (!treeNode.isLeaf()){
int count = treeNode.getChildCount();
for(int j = 0; j < count; j++){
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) treeNode.getChildAt(j);
UIViewOutlineTreeNode child = (UIViewOutlineTreeNode) childNode.getUserObject();
NodeSummary nodeSum = child.getObject();
treeNode.remove(childNode);
Vector childNodes = (Vector) getTreeNode(ns.getId());
childNodes.remove(childNode);
Vector v =((Vector)htNodeAndViews.get(ns));
v.remove(view);
((DefaultTreeModel)tree.getModel()).reload(childNode);
}
} else {
rootNode.remove(treeNode);
Vector childNodes = (Vector) getTreeNode(ns.getId());
childNodes.remove(treeNode);
Vector v =((Vector)htNodeAndViews.get(ns));
v.remove(view);
}
}
}
} else {
Vector vtNodes = (Vector) getTreeNode(view.getId());
for(int i = 0; i < vtNodes.size(); i++) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) vtNodes.get(i);
UIViewOutlineTreeNode node = (UIViewOutlineTreeNode) treeNode.getUserObject();
if (!treeNode.isLeaf()){
int count = treeNode.getChildCount();
for(int j = 0; j < count; j++){
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) treeNode.getChildAt(j);
UIViewOutlineTreeNode child = (UIViewOutlineTreeNode) childNode.getUserObject();
NodeSummary nodeSum = child.getObject();
if(ns.equals(nodeSum)){
treeNode.remove(childNode);
Vector childNodes = (Vector) getTreeNode(ns.getId());
childNodes.remove(childNode);
Vector v =((Vector)htNodeAndViews.get(ns));
v.remove(view);
((DefaultTreeModel)tree.getModel()).reload(childNode);
}
}
if (treeNode.getChildCount() == 0 && view.getState() != ICoreConstants.UNREADSTATE){
rootNode.remove(treeNode);
((DefaultTreeModel)tree.getModel()).reload(rootNode);
}
}
}
}
if(ns.getState() == ICoreConstants.UNREADSTATE){
nUnread --;
lblUnread.setText(String.valueOf(nUnread));
}
}
public void addNode(DefaultMutableTreeNode treeNode, NodeSummary ns, View oView){
if(ns instanceof View){
int index = rootNode.getIndex(treeNode);
if(index == -1){
if(ns.equals(ProjectCompendium.APP.getInBoxView())){
rootNode.insert(treeNode, 0);
} else {
rootNode.add(treeNode);
}
((DefaultTreeModel)tree.getModel()).reload(rootNode);
if(!treeNode.isLeaf())
tree.expandPath(new TreePath(treeNode.getPath()));
}
} else {
Vector viewNodes = getTreeNode(oView.getId());
for(int j =0; j < viewNodes.size(); j ++){
DefaultMutableTreeNode viewNode = (DefaultMutableTreeNode) viewNodes.get(j);
int index = rootNode.getIndex(viewNode);
if(index == -1){
if(oView.equals(ProjectCompendium.APP.getInBoxView())){
rootNode.insert(viewNode, 0);
} else {
rootNode.add(viewNode);
}
((DefaultTreeModel)tree.getModel()).reload(rootNode);
}
viewNode.add(treeNode);
((DefaultTreeModel)tree.getModel()).reload(viewNode);
tree.expandPath(new TreePath(viewNode.getPath()));
}
}
}
/**
* Called whenever the value of the selection changes to update status
*/
public void valueChanged(TreeSelectionEvent arg0) {
TreePath path = arg0.getPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
selectedNode = ((UIViewOutlineTreeNode) node.getUserObject());
UIViewOutlineTreeNode treeNode = (UIViewOutlineTreeNode)(node.getUserObject());
if(treeNode.getObject() != null )
setStatus(treeNode.getObject());
else
ProjectCompendium.APP.setStatus(""); //$NON-NLS-1$
}
/**
* Handles property change events.
* @param evt, the associated PropertyChangeEvent object.
*/
public void propertyChange(PropertyChangeEvent evt) {
Object obj = evt.getSource();
String prop = evt.getPropertyName();
Object oldvalue = evt.getOldValue();
Object newvalue = evt.getNewValue();
// get the expanded tree descendants.
Enumeration e = tree.getExpandedDescendants(new TreePath(rootNode.getPath()));
if(prop.equals(NodeSummary.IMAGE_PROPERTY)){
NodeSummary ns = (NodeSummary) obj;
Vector nodes = getTreeNode(ns.getId());
for(int i =0; i < nodes.size(); i++){
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) nodes.get(i);
UIViewOutlineTreeNode node = (UIViewOutlineTreeNode) treeNode.getUserObject();
node.setReference(ns.getSource());
}
}
else if(prop.equals(NodeSummary.STATE_PROPERTY)){
NodeSummary ns = (NodeSummary) obj;
int newState = ((Integer) newvalue).intValue();
int oldState = ((Integer) oldvalue).intValue();
Vector nodes = getTreeNode(ns.getId());
for(int i =0; i < nodes.size(); i++){
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) nodes.get(i);
UIViewOutlineTreeNode node = (UIViewOutlineTreeNode) treeNode.getUserObject();
if(!node.getObject().equals(ProjectCompendium.APP.getHomeView())){ //treeNode != rootNode.getFirstChild()
node.setState(newState);
}
if(newState == ICoreConstants.UNREADSTATE){
nUnread ++;
lblUnread.setText(String.valueOf(nUnread));
} else if (oldState == ICoreConstants.UNREADSTATE){
nUnread --;
lblUnread.setText(String.valueOf(nUnread));
}
if(ns instanceof View){
if ((newState == ICoreConstants.UNREADSTATE) && (treeNode.getParent() == null)){
addNode(treeNode, ns, null);
((DefaultTreeModel)tree.getModel()).reload(treeNode);
}
} else {
Vector vtNodes = (Vector)htNodeAndViews.get(ns);
View view = (View) vtNodes.get(i);
if(view != null){
if ((newState == ICoreConstants.UNREADSTATE) && (treeNode.getParent() == null)){
addNode(treeNode, ns, view);
((DefaultTreeModel)tree.getModel()).reload(treeNode);
}
}
}
}
} else if(prop.equals(View.NODE_REMOVED)){
View oView = (View) obj;
NodeSummary ns = (NodeSummary) newvalue;
removeNode(oView, ns);
} else if(prop.equals(NodeSummary.LABEL_PROPERTY)){
NodeSummary ns = (NodeSummary) obj;
String newLabel = newvalue.toString();
Vector vtNodes = (Vector) getTreeNode(ns.getId());
for(int i = 0; i < vtNodes.size(); i++){
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) vtNodes.get(i);
UIViewOutlineTreeNode node = (UIViewOutlineTreeNode)treeNode.getUserObject();
node.setLabel(newLabel);
((DefaultTreeModel)tree.getModel()).reload(treeNode);
}
} else if((prop.equals(View.NODE_ADDED)) || (prop.equals(View.NODE_TRANSCLUDED))){
NodePosition np = (NodePosition) newvalue;
View oView = np.getView();
NodeSummary ns = np.getNode();
ns.initialize(oSession, oModel);
UIArrangeLeftRight arrange = new UIArrangeLeftRight();
if (oView != null)
arrange.processView(oView);
UIViewOutlineTreeNode node = new UIViewOutlineTreeNode(ns);
DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(node);
boolean isAlreadyAdded = true;
//store all views against the nodes. It is used when adding a node in the unread view due to state change
if(!htNodeAndViews.containsKey(ns)){
Vector vtNodes = new Vector();
vtNodes.add(oView);
htNodeAndViews.put(ns, vtNodes);
} else {
Vector vtNodes = (Vector) htNodeAndViews.get(ns);
if(!vtNodes.contains(oView)){
vtNodes.add(oView);
isAlreadyAdded = false; //if the node is already for the view don't add to vtTreeNodes
}
}//end if
if(htTreeNodes.containsKey(ns.getId())){
Vector vtTreeNodes = (Vector) htTreeNodes.get(ns.getId());
if(!vtTreeNodes.contains(treeNode) && !isAlreadyAdded) {
vtTreeNodes.add(treeNode);
if(ns.getState() == ICoreConstants.UNREADSTATE && treeNode.getParent() == null){
addNode(treeNode, ns, oView);
((DefaultTreeModel)tree.getModel()).reload(treeNode);
nUnread ++;
lblUnread.setText(String.valueOf(nUnread));
}
}
} else {
Vector vtTreeNodes = new Vector();
vtTreeNodes.add(treeNode);
htTreeNodes.put(ns.getId(), vtTreeNodes);
if(ns.getState() == ICoreConstants.UNREADSTATE && treeNode.getParent() == null){
addNode(treeNode, ns, oView);
((DefaultTreeModel)tree.getModel()).reload(treeNode);
}
}
// add to listeners
if(!ns.getListenerList().contains(this)){
ns.addPropertyChangeListener(this);
}
} else if (prop.equals(NodeSummary.NODE_TYPE_PROPERTY)){
NodeSummary ns = (NodeSummary) obj;
int newType = Integer.parseInt(newvalue.toString());
int oldType = Integer.parseInt(oldvalue.toString());
Vector vtNodes = (Vector) getTreeNode(ns.getId());
for(int i = 0; i < vtNodes.size(); i++){
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) vtNodes.get(i);
UIViewOutlineTreeNode node = (UIViewOutlineTreeNode)treeNode.getUserObject();
node.setType(newType);
}
}
// expand all the expanded tree nodes
if(e != null){
for (;e.hasMoreElements();){
TreePath path = (TreePath)e.nextElement();
if(tree.getRowForPath(path) != -1)
tree.expandPath(path);
}
}
tree.repaint();
}
/**
* Create and show the right-click node popup menu for the given node.
* @param node com.compendium.core.datamodel.NodeSummary, the node to create the popup for.
* @param x, the x position of the mouse event that triggered this request.
* @param y, the y position of the mouse event that triggered this request.
*/
public UIViewUnreadPopupMenu showPopupMenu(NodeSummary node, int x, int y) {
UIViewUnreadPopupMenu popup = new UIViewUnreadPopupMenu ("Popup Menu", node, this); //$NON-NLS-1$
Point point = new Point (x, y);
int realX = Math.abs(point.x - getX())+ 50;
int realY = Math.abs(point.y - getY()) + 20;
if(realX > this.getWidth()){
realX = this.getWidth() - 20;
}
popup.show(tree, realX, realY);
return popup;
}
/**
* Remove all listeners before closing view
*
*/
public void cleanUp(){
for(Enumeration e = htTreeNodes.elements(); e.hasMoreElements();){
Vector nodes = (Vector) e.nextElement();
for(int i =0; i< nodes.size(); i ++){
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) nodes.get(i);
UIViewOutlineTreeNode outlineNode = (UIViewOutlineTreeNode) treeNode.getUserObject();
NodeSummary node = outlineNode.getObject();
if(node.getListenerList().contains(this)){
node.removePropertyChangeListener(this);
}
}
}
}
/**
* The inner class that defines the requirements for an object that displays a tree node
* @author Lakshmi Prabhakaran
*
*/
private class TreeNodeRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 7969295074672629921L;
Icon imageIcon ;
UIViewOutlineTreeNode treeNode = null;
/** Sets the value of the current tree cell to value.
*
* @return the Component that the renderer uses to draw the value
*/
public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component c = super.getTreeCellRendererComponent(tree, value, sel,
expanded, leaf, row, hasFocus);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
treeNode = (UIViewOutlineTreeNode)(node.getUserObject());
String toolTip = treeNode.getLabel();
int type = treeNode.getType();
int state = treeNode.getState();
//set the font
setFont(tree.getFont());
setForeground(SELECTED_TEXT_COLOR);
if (type == ICoreConstants.REFERENCE) {
imageIcon = UINode.getReferenceImageSmall(treeNode.getReference());
} else if (type == -1) {
imageIcon = getOpenIcon();
} else {
imageIcon = UINode.getNodeImageSmall(type);
}
if (treeNode.getObject() != null) {
if(treeNode.getObject().getId().equals(ProjectCompendium.APP.getInBoxID())) {
imageIcon = UIImages.get(IUIConstants.INBOX_SM);
}
}
setIcon(imageIcon);
setToolTipText(toolTip);
// set border color
setBorder(new NodeBorder(state, imageIcon));
return this;
}
public String getToolTipText(MouseEvent e){
if(treeNode.getObject() != null ){
// set status info
setStatus(treeNode.getObject());
} else {
ProjectCompendium.APP.setStatus(""); //$NON-NLS-1$
}
return this.getToolTipText();
}
}
/**
* This border class paints the border for this node.
*/
private class NodeBorder extends AbstractBorder {
int state;
Icon imageIcon;
public NodeBorder(int state, Icon icon){
this.state = state;
imageIcon = icon;
}
public void paintBorder (Component c, Graphics g, int x, int y, int width, int height) {
if (state == ICoreConstants.UNREADSTATE) {
Color oldColor = g.getColor();
g.setColor(UNREAD_BORDER_COLOR);
int iconWidth = imageIcon.getIconWidth();
g.draw3DRect(x + (iconWidth + 3) , y + 1, width - (iconWidth + 5), height-2, true);
g.setColor(oldColor);
}
else if (state == ICoreConstants.MODIFIEDSTATE) {
Color oldColor = g.getColor();
g.setColor(MODIFIED_BORDER_COLOR);
int iconWidth = imageIcon.getIconWidth();
g.draw3DRect(x + (iconWidth +3) , y + 1, width - (iconWidth + 5), height-2, true);
g.setColor(oldColor);
} else {
Color oldColor = g.getColor();
g.setColor(oldColor);
}
}
}
}