/* Copyright 2004-2014 Jim Voris
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.qumasoft.guitools.qwin;
import com.qumasoft.guitools.qwin.dialog.DefineWorkfileLocationDialog;
import com.qumasoft.guitools.qwin.operation.OperationAddDirectory;
import com.qumasoft.guitools.qwin.operation.OperationAddServer;
import com.qumasoft.guitools.qwin.operation.OperationAutoAddFiles;
import com.qumasoft.guitools.qwin.operation.OperationBaseClass;
import com.qumasoft.guitools.qwin.operation.OperationDefineView;
import com.qumasoft.guitools.qwin.operation.OperationDeleteDirectory;
import com.qumasoft.guitools.qwin.operation.OperationDeleteView;
import com.qumasoft.guitools.qwin.operation.OperationEditServerProperties;
import com.qumasoft.guitools.qwin.operation.OperationGetDirectory;
import com.qumasoft.guitools.qwin.operation.OperationLabelDirectory;
import com.qumasoft.guitools.qwin.operation.OperationMaintainView;
import com.qumasoft.guitools.qwin.operation.OperationPromoteFilesFromChildBranch;
import com.qumasoft.guitools.qwin.operation.OperationRemoveServer;
import com.qumasoft.guitools.qwin.operation.OperationUnLabelDirectory;
import com.qumasoft.qvcslib.AbstractProjectProperties;
import com.qumasoft.qvcslib.ArchiveDirManagerProxy;
import com.qumasoft.qvcslib.requestdata.ClientRequestMoveFileData;
import com.qumasoft.qvcslib.ClientTransactionManager;
import com.qumasoft.qvcslib.DirectoryCoordinate;
import com.qumasoft.qvcslib.DirectoryManagerFactory;
import com.qumasoft.qvcslib.DirectoryManagerInterface;
import com.qumasoft.qvcslib.QVCSConstants;
import com.qumasoft.qvcslib.QVCSException;
import com.qumasoft.qvcslib.RemoteViewProperties;
import com.qumasoft.qvcslib.ServerProperties;
import com.qumasoft.qvcslib.TransportProxyFactory;
import com.qumasoft.qvcslib.TransportProxyInterface;
import com.qumasoft.qvcslib.Utility;
import com.qumasoft.qvcslib.WorkfileDirectoryManagerInterface;
import java.awt.Component;
import java.awt.Font;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.MenuElement;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.event.MouseInputAdapter;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
/**
* Project tree control. JPanel container of our tree control. This is a singleton.
*
* @author Jim Voris
*/
public final class ProjectTreeControl extends javax.swing.JPanel {
private static final long serialVersionUID = 5244866537942643753L;
private static final ProjectTreeControl PROJECT_TREE_CONTROL = new ProjectTreeControl();
private DefaultMutableTreeNode lastSelectedNode;
private final ProjectTreeModel projectTreeModel;
private AbstractProjectProperties activeProject;
private String activeView;
private ServerProperties serverProperties;
private final ImageIcon serversIcon;
private final ImageIcon serverIcon;
private final ImageIcon projectIcon;
private final ImageIcon readOnlyViewIcon;
private final ImageIcon readWriteViewIcon;
// Popup menu items.
private final ActionDefineWorkfileLocation actionDefineWorkfileLocation;
private final ActionAddDirectory actionAddDirectory;
private final ActionDeleteDirectory actionDeleteDirectory;
private final ActionAutoAddFiles actionAutoAddFiles;
private final ActionGetDirectory actionGetDirectory;
private final ActionLabelDirectory actionLabelDirectory;
private final ActionUnLabelDirectory actionUnLabelDirectory;
private final ActionDefineView actionDefineView;
private final ActionMaintainView actionMaintainView;
private final ActionDeleteView actionDeleteView;
private final ActionExpandTree actionExpandTree;
private final ActionCollapseTree actionCollapseTree;
private final ActionPromoteFromChild actionPromoteFromChild;
// Other popup menu items.
private final ActionAddServer actionAddServer;
private final ActionRemoveServer actionRemoveServer;
private final ActionServerProperties actionServerProperties;
/**
* Get the singleton instance of the project tree control.
*
* @return the singleton instance of the project tree control.
*/
public static ProjectTreeControl getInstance() {
return PROJECT_TREE_CONTROL;
}
/**
* Creates new form ProjectTreeControl.
*/
private ProjectTreeControl() {
this.actionServerProperties = new ActionServerProperties("Server Properties...");
this.actionRemoveServer = new ActionRemoveServer("Remove Server...");
this.actionAddServer = new ActionAddServer("Add Server...");
this.actionPromoteFromChild = new ActionPromoteFromChild("Promote changes from child branch");
this.actionCollapseTree = new ActionCollapseTree("Collapse Tree");
this.actionExpandTree = new ActionExpandTree("Expand Tree");
this.actionDeleteView = new ActionDeleteView("Delete View...");
this.actionMaintainView = new ActionMaintainView("View Properties...");
this.actionDefineView = new ActionDefineView("Define View...");
this.actionUnLabelDirectory = new ActionUnLabelDirectory("Remove Label...");
this.actionLabelDirectory = new ActionLabelDirectory("Apply Label...");
this.actionGetDirectory = new ActionGetDirectory("Get...");
this.actionAutoAddFiles = new ActionAutoAddFiles("Auto-Add Files/Directories...");
this.actionDeleteDirectory = new ActionDeleteDirectory("Delete Directory...");
this.actionAddDirectory = new ActionAddDirectory("Add Directory...");
this.actionDefineWorkfileLocation = new ActionDefineWorkfileLocation("Define Workfile Location...");
this.readWriteViewIcon = new ImageIcon(ClassLoader.getSystemResource("images/readwriteview.png"), "Read Write View");
this.readOnlyViewIcon = new ImageIcon(ClassLoader.getSystemResource("images/readonlyview.png"), "Read Only View");
this.projectIcon = new ImageIcon(ClassLoader.getSystemResource("images/project.png"), "Project");
this.serverIcon = new ImageIcon(ClassLoader.getSystemResource("images/server.png"), "Server");
this.serversIcon = new ImageIcon(ClassLoader.getSystemResource("images/servers.png"), "Servers");
initComponents();
addPopupMenuItems();
projectTreeModel = new ProjectTreeModel();
m_ProjectTree.setModel(projectTreeModel.getTreeModel());
m_ProjectTree.setShowsRootHandles(true);
m_ProjectTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
addListeners();
// Set the tree model so others can easily find it.
QWinFrame.getQWinFrame().setTreeModel(projectTreeModel);
// Set the tree control so others can easily find it.
QWinFrame.getQWinFrame().setTreeControl(this);
// Enable the tree as a drop target.
initDragAndDrop();
m_ProjectTree.setFont(QWinFrame.getQWinFrame().getFont(QWinFrame.getQWinFrame().getFontSize()));
}
JTree getProjectJTreeControl() {
return m_ProjectTree;
}
/**
* Set the font size that we'll use.
*
* @param fontSize the font size.
*/
public void setFontSize(int fontSize) {
m_ProjectTree.setFont(QWinFrame.getQWinFrame().getFont(fontSize + 1));
setMenusFontSize(fontSize + 1);
}
private void setMenusFontSize(int fontSize) {
setMenuFontSize(fontSize, m_DirectoryPopupMenu);
setMenuFontSize(fontSize, m_ProjectPopupMenu);
setMenuFontSize(fontSize, m_RootServerPopupMenu);
setMenuFontSize(fontSize, m_ServerPopupMenu);
setMenuFontSize(fontSize, m_ViewPopupMenu);
}
private void setMenuFontSize(int fontSize, JPopupMenu popupMenu) {
Font font = QWinFrame.getQWinFrame().getFont(fontSize);
MenuElement[] menuElements = popupMenu.getSubElements();
for (MenuElement menuElement : menuElements) {
menuElement.getComponent().setFont(font);
}
}
/**
* This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always regenerated
* by the FormEditor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
m_ProjectPopupMenu = new javax.swing.JPopupMenu();
m_RootServerPopupMenu = new javax.swing.JPopupMenu();
m_ServerPopupMenu = new javax.swing.JPopupMenu();
m_DirectoryPopupMenu = new javax.swing.JPopupMenu();
m_ViewPopupMenu = new javax.swing.JPopupMenu();
m_ScrollPane = new javax.swing.JScrollPane();
m_ProjectTree = new javax.swing.JTree();
m_ProjectPopupMenu.setFont(new java.awt.Font("Arial", 0, 12)); // NOI18N
m_RootServerPopupMenu.setFont(new java.awt.Font("Arial", 0, 12)); // NOI18N
m_ServerPopupMenu.setFont(new java.awt.Font("Arial", 0, 12)); // NOI18N
m_DirectoryPopupMenu.setFont(new java.awt.Font("Arial", 0, 12)); // NOI18N
m_ViewPopupMenu.setFont(new java.awt.Font("Arial", 0, 12)); // NOI18N
setLayout(new java.awt.BorderLayout());
m_ProjectTree.setFont(new java.awt.Font("Arial", 0, 12)); // NOI18N
EnterpriseTreeCellRenderer renderer = new EnterpriseTreeCellRenderer(serversIcon, serverIcon, projectIcon, readOnlyViewIcon, readWriteViewIcon);
renderer.setLeafIcon(renderer.getClosedIcon());
m_ProjectTree.setCellRenderer(renderer);
m_ScrollPane.setViewportView(m_ProjectTree);
add(m_ScrollPane);
}// </editor-fold>//GEN-END:initComponents
private void addPopupMenuItems() {
Font menuFont = QWinFrame.getQWinFrame().getFont(QWinFrame.getQWinFrame().getFontSize() + 1);
// The root popup menu
JMenuItem menuItem = m_RootServerPopupMenu.add(actionAddServer);
menuItem.setFont(menuFont);
// The server popup menu
menuItem = m_ServerPopupMenu.add(actionServerProperties);
menuItem.setFont(menuFont);
menuItem = m_ServerPopupMenu.add(actionRemoveServer);
menuItem.setFont(menuFont);
// =====================================================================
// =====================================================================
// The project popup menu
menuItem = m_ProjectPopupMenu.add(actionDefineView);
menuItem.setFont(menuFont);
// =====================================================================
// =====================================================================
// The view popup menu
menuItem = m_ViewPopupMenu.add(actionDefineWorkfileLocation);
menuItem.setFont(menuFont);
menuItem = m_ViewPopupMenu.add(actionMaintainView);
menuItem.setFont(menuFont);
menuItem = m_ViewPopupMenu.add(actionDeleteView);
menuItem.setFont(menuFont);
// =====================================================================
m_ViewPopupMenu.add(new javax.swing.JSeparator());
// =====================================================================
menuItem = m_ViewPopupMenu.add(actionExpandTree);
menuItem.setFont(menuFont);
menuItem = m_ViewPopupMenu.add(actionCollapseTree);
menuItem.setFont(menuFont);
// =====================================================================
m_ViewPopupMenu.add(new javax.swing.JSeparator());
// =====================================================================
menuItem = m_ViewPopupMenu.add(actionAddDirectory);
menuItem.setFont(menuFont);
menuItem = m_ViewPopupMenu.add(actionAutoAddFiles);
menuItem.setFont(menuFont);
// =====================================================================
m_ViewPopupMenu.add(new javax.swing.JSeparator());
// =====================================================================
menuItem = m_ViewPopupMenu.add(actionGetDirectory);
menuItem.setFont(menuFont);
menuItem = m_ViewPopupMenu.add(actionLabelDirectory);
menuItem.setFont(menuFont);
menuItem = m_ViewPopupMenu.add(actionUnLabelDirectory);
menuItem.setFont(menuFont);
// =====================================================================
m_ViewPopupMenu.add(new javax.swing.JSeparator());
// =====================================================================
menuItem = m_ViewPopupMenu.add(actionPromoteFromChild);
menuItem.setFont(menuFont);
// =====================================================================
// =====================================================================
// The directory popup menu
menuItem = m_DirectoryPopupMenu.add(actionAddDirectory);
menuItem.setFont(menuFont);
menuItem = m_DirectoryPopupMenu.add(actionDeleteDirectory);
menuItem.setFont(menuFont);
menuItem = m_DirectoryPopupMenu.add(actionAutoAddFiles);
menuItem.setFont(menuFont);
// =====================================================================
m_DirectoryPopupMenu.add(new javax.swing.JSeparator());
// =====================================================================
menuItem = m_DirectoryPopupMenu.add(actionExpandTree);
menuItem.setFont(menuFont);
menuItem = m_DirectoryPopupMenu.add(actionCollapseTree);
menuItem.setFont(menuFont);
// =====================================================================
m_DirectoryPopupMenu.add(new javax.swing.JSeparator());
// =====================================================================
menuItem = m_DirectoryPopupMenu.add(actionGetDirectory);
menuItem.setFont(menuFont);
menuItem = m_DirectoryPopupMenu.add(actionLabelDirectory);
menuItem.setFont(menuFont);
menuItem = m_DirectoryPopupMenu.add(actionUnLabelDirectory);
menuItem.setFont(menuFont);
}
private void enableAllPopUpOperations() {
actionAddDirectory.setEnabled(true);
actionAutoAddFiles.setEnabled(true);
}
private void disableAllDirectoryOperations() {
actionAddDirectory.setEnabled(false);
actionAutoAddFiles.setEnabled(false);
}
private AbstractProjectProperties getProjectProperties() {
AbstractProjectProperties projectProperties = null;
if (lastSelectedNode instanceof DirectoryTreeNode) {
DirectoryTreeNode directoryNode = (DirectoryTreeNode) lastSelectedNode;
projectProperties = directoryNode.getProjectProperties();
} else if (lastSelectedNode instanceof ProjectTreeNode) {
ProjectTreeNode projectTreeNode = (ProjectTreeNode) lastSelectedNode;
projectProperties = projectTreeNode.getProjectProperties();
} else if (lastSelectedNode instanceof ViewTreeNode) {
ViewTreeNode viewTreeNode = (ViewTreeNode) lastSelectedNode;
projectProperties = viewTreeNode.getProjectProperties();
}
return projectProperties;
}
private String getAppendedPath() {
String retVal = "";
if (lastSelectedNode instanceof DirectoryTreeNode) {
DirectoryTreeNode directoryNode = (DirectoryTreeNode) lastSelectedNode;
retVal = directoryNode.getAppendedPath();
}
return retVal;
}
private String getViewName() {
String retVal = QVCSConstants.QVCS_TRUNK_VIEW;
if (lastSelectedNode instanceof DirectoryTreeNode) {
DirectoryTreeNode directoryNode = (DirectoryTreeNode) lastSelectedNode;
retVal = directoryNode.getViewName();
} else if (lastSelectedNode instanceof ViewTreeNode) {
ViewTreeNode viewTreeNode = (ViewTreeNode) lastSelectedNode;
retVal = viewTreeNode.getViewName();
}
return retVal;
}
/**
* Get the selected node.
* @return the selected node.
*/
public DefaultMutableTreeNode getSelectedNode() {
return (DefaultMutableTreeNode) m_ProjectTree.getLastSelectedPathComponent();
}
/**
* Get the active view node.
* @return the active view node.
*/
public ViewTreeNode getActiveViewNode() {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) m_ProjectTree.getLastSelectedPathComponent();
while (!(node instanceof ViewTreeNode)) {
node = (DefaultMutableTreeNode) node.getParent();
}
ViewTreeNode viewTreeNode = (ViewTreeNode) node;
return viewTreeNode;
}
/**
* Get an Enumeration of the views for the active project.
* @return an Enumeration of the views for the active project. This may return null if the user is not within a project (e.g. maybe they have the server node selected).
*/
public Enumeration getCurrentViews() {
TreeNode projectTreeNode;
DefaultMutableTreeNode node = getSelectedNode();
if (node instanceof ViewTreeNode) {
projectTreeNode = node.getParent();
} else if (node instanceof ProjectTreeNode) {
projectTreeNode = node;
} else {
return null;
}
return projectTreeNode.children();
}
void addServerMenuItems(javax.swing.JMenu menu) {
Font menuFont = new Font("Arial", 0, 12);
menu.removeAll();
JMenuItem menuItem = menu.add(actionAddServer);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_A);
if ((lastSelectedNode != null)
&& (lastSelectedNode instanceof ServerTreeNode)) {
menuItem = menu.add(actionRemoveServer);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_R);
menuItem = menu.add(actionServerProperties);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_P);
} else {
menuItem = menu.add(actionRemoveServer);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_R);
menuItem.setEnabled(false);
menuItem = menu.add(actionServerProperties);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_P);
menuItem.setEnabled(false);
}
}
void addProjectMenuItems(javax.swing.JMenu menu) {
Font menuFont = new Font("Arial", 0, 12);
menu.removeAll();
if (lastSelectedNode != null) {
if (lastSelectedNode instanceof ProjectTreeNode) {
JMenuItem menuItem = menu.add(actionDefineView);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_D);
} else if (lastSelectedNode instanceof ViewTreeNode) {
JMenuItem menuItem = menu.add(actionDefineWorkfileLocation);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_D);
menuItem.setEnabled(false);
menuItem = menu.add(actionAddDirectory);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_A);
menuItem = menu.add(actionAutoAddFiles);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_U);
menuItem = menu.add(actionPromoteFromChild);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_P);
} else if (lastSelectedNode instanceof DirectoryTreeNode) {
JMenuItem menuItem = menu.add(actionDefineWorkfileLocation);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_D);
menuItem.setEnabled(false);
menuItem = menu.add(actionAddDirectory);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_A);
menuItem = menu.add(actionAutoAddFiles);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_U);
} else {
JMenuItem menuItem = menu.add(actionDefineWorkfileLocation);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_D);
menuItem.setEnabled(false);
menuItem = menu.add(actionAddDirectory);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_A);
menuItem.setEnabled(false);
menuItem = menu.add(actionAutoAddFiles);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_U);
menuItem.setEnabled(false);
}
} else {
JMenuItem menuItem = menu.add(actionDefineView);
menuItem.setFont(menuFont);
menuItem.setMnemonic(java.awt.event.KeyEvent.VK_D);
}
}
private void addListeners() {
m_ProjectTree.addTreeSelectionListener(
new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
lastSelectedNode = (DefaultMutableTreeNode) m_ProjectTree.getLastSelectedPathComponent();
if (lastSelectedNode != null) {
if (lastSelectedNode instanceof ServerTreeNode) {
ServerTreeNode serverTreeNode = (ServerTreeNode) lastSelectedNode;
serverProperties = serverTreeNode.getServerProperties();
// There is no active project or view.
activeProject = null;
activeView = null;
// See if we are already logged in to this server...
boolean loggedInAlreadyFlag = TransportProxyFactory.getInstance().getTransportProxy(serverProperties) != null;
QWinFrame.getQWinFrame().setActiveServer(serverProperties);
if (loggedInAlreadyFlag) {
// If we are already logged in, then the user is manually
// navigating to the server node.... so we clear the
// data model with the following call.
//
// If the user is not already logged in, then the login
// process will try to restore the project tree so that
// the selected node will be the one the user had
// selected when last using the application. In that
// case, we need to skip this next line of code.
QWinFrame.getQWinFrame().setCurrentAppendedPath(QVCSConstants.QWIN_DEFAULT_PROJECT_NAME, QVCSConstants.QVCS_TRUNK_VIEW, "", QVCSConstants.QVCS_REMOTE_PROJECT_TYPE, true);
}
} else if (lastSelectedNode instanceof ProjectTreeNode) {
ProjectTreeNode projectTreeNode = (ProjectTreeNode) lastSelectedNode;
activeProject = projectTreeNode.getProjectProperties();
activeView = null;
String projectName = projectTreeNode.getProjectName();
TransportProxyFactory.getInstance().requestViewList(serverProperties, projectName);
QWinFrame.getQWinFrame().setCurrentAppendedPath(QVCSConstants.QWIN_DEFAULT_PROJECT_NAME, QVCSConstants.QVCS_TRUNK_VIEW, "", QVCSConstants.QVCS_REMOTE_PROJECT_TYPE, true);
} else if (lastSelectedNode instanceof ViewTreeNode) {
ViewTreeNode viewTreeNode = (ViewTreeNode) lastSelectedNode;
activeProject = viewTreeNode.getProjectProperties();
activeView = viewTreeNode.getViewName();
serverProperties = findServerProperties();
QWinFrame.getQWinFrame().setCurrentAppendedPath(viewTreeNode.getProjectProperties().getProjectName(), viewTreeNode.getViewName(), "", activeProject.getProjectType(), false);
} else if (lastSelectedNode instanceof DefaultProjectTreeNode) {
QWinFrame.getQWinFrame().setCurrentAppendedPath(QVCSConstants.QWIN_DEFAULT_PROJECT_NAME, QVCSConstants.QVCS_TRUNK_VIEW, "", QVCSConstants.QVCS_REMOTE_PROJECT_TYPE, true);
activeProject = null;
activeView = null;
} else if (lastSelectedNode instanceof DefaultServerTreeNode) {
QWinFrame.getQWinFrame().setCurrentAppendedPath(QVCSConstants.QWIN_DEFAULT_PROJECT_NAME, QVCSConstants.QVCS_TRUNK_VIEW, "", QVCSConstants.QVCS_REMOTE_PROJECT_TYPE, true);
activeProject = null;
activeView = null;
} else if (lastSelectedNode instanceof DirectoryTreeNode) {
DirectoryTreeNode directoryNode = (DirectoryTreeNode) lastSelectedNode;
activeProject = directoryNode.getProjectProperties();
activeView = directoryNode.getViewName();
serverProperties = findServerProperties();
// Expand the new selection...
Enumeration expandEnumeration = directoryNode.children();
while (expandEnumeration.hasMoreElements()) {
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) expandEnumeration.nextElement();
TreePath childTreePath = treeSelectionEvent.getNewLeadSelectionPath().pathByAddingChild(childNode);
getProjectJTreeControl().makeVisible(childTreePath);
}
// Collapse the old selection only if the new selection is not a child of the old selection...
if (treeSelectionEvent.getOldLeadSelectionPath() != null) {
if (!treeSelectionEvent.getOldLeadSelectionPath().isDescendant(treeSelectionEvent.getNewLeadSelectionPath())) {
DefaultMutableTreeNode oldSelection = projectTreeModel.findNode(treeSelectionEvent.getOldLeadSelectionPath());
if (oldSelection instanceof DirectoryTreeNode) {
DirectoryTreeNode oldDirectoryTreeNode = (DirectoryTreeNode) oldSelection;
if (0 == activeProject.getProjectName().compareTo(oldDirectoryTreeNode.getProjectProperties().getProjectName())
&& (0 == activeView.compareTo(oldDirectoryTreeNode.getViewName()))) {
getProjectJTreeControl().collapsePath(treeSelectionEvent.getOldLeadSelectionPath());
}
}
}
}
QWinFrame.getQWinFrame().setCurrentAppendedPath(directoryNode.getProjectProperties().getProjectName(), directoryNode.getViewName(), directoryNode.getAppendedPath(),
activeProject.getProjectType(), false);
}
}
}
});
m_ProjectTree.addMouseListener(new MouseInputAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger() || ((e.getButton() == MouseEvent.BUTTON3) && (0 != (e.getModifiers() & MouseEvent.MOUSE_RELEASED)))) {
// Make sure the node under the mouse is the one
// that is selected.
TreePath selPath = m_ProjectTree.getPathForLocation(e.getX(), e.getY());
m_ProjectTree.setSelectionPath(selPath);
// Turn on all popups, and then figure out which ones
// to turn off
enableAllPopUpOperations();
if (lastSelectedNode != null) {
if (lastSelectedNode instanceof ProjectTreeNode) {
m_ProjectPopupMenu.show(m_ProjectTree, e.getX(), e.getY());
} else if (lastSelectedNode instanceof ViewTreeNode) {
m_ViewPopupMenu.show(m_ProjectTree, e.getX(), e.getY());
} else if (lastSelectedNode instanceof DirectoryTreeNode) {
m_DirectoryPopupMenu.show(m_ProjectTree, e.getX(), e.getY());
} else if (lastSelectedNode instanceof DefaultProjectTreeNode) {
disableAllDirectoryOperations();
} else if (lastSelectedNode instanceof DefaultServerTreeNode) {
m_RootServerPopupMenu.show(m_ProjectTree, e.getX(), e.getY());
} else if (lastSelectedNode instanceof ServerTreeNode) {
m_ServerPopupMenu.show(m_ProjectTree, e.getX(), e.getY());
}
}
}
}
});
}
/**
* Get the active project.
*
* @return the project properties for the active project.
*/
public AbstractProjectProperties getActiveProject() {
return activeProject;
}
/**
* Get the active view.
*
* @return the name of the active view.
*/
public String getActiveView() {
return activeView;
}
String getProjectName() {
String projectName = null;
if (getActiveProject() != null) {
projectName = getActiveProject().getProjectName();
}
return projectName;
}
/**
* Get the string for the active server. The active server is the server node that is the parent (or ancestor) of the currently selected node.
*
* @return the name of the active server, i.e. the one that is the ancestor of the currently selected node.
*/
public String getActiveServerName() {
String serverName = null;
ServerProperties serverProps = getActiveServer();
if (serverProps != null) {
serverName = serverProps.getServerName();
}
return serverName;
}
/**
* Get the server properties for the active server. The active server is the server node that is the parent (or ancestor) of the currently selected node.
*
* @return the server properties for the current server; i.e. the server properties for the server node that is the ancestor of the currently selected node.
*/
public ServerProperties getActiveServer() {
return serverProperties;
}
private ServerProperties findServerProperties() {
ServerProperties serverProps = null;
if (lastSelectedNode != null) {
DefaultMutableTreeNode node = lastSelectedNode;
while (node != null) {
if (node instanceof ServerTreeNode) {
ServerTreeNode serverTreeNode = (ServerTreeNode) node;
serverProps = serverTreeNode.getServerProperties();
break;
}
node = (DefaultMutableTreeNode) node.getParent();
}
}
return serverProps;
}
/**
* Force selection of the root node.
*/
public void selectRootNode() {
// Select the root node -- there is no active project.
m_ProjectTree.setSelectionPath(new TreePath(m_ProjectTree.getModel().getRoot()));
}
/**
* Select a given node on the tree control.
*
* @param nodeToSelect the node to select.
*/
public void selectNode(TreeNode nodeToSelect) {
// First, figure out the depth of the node
if (nodeToSelect != null) {
int depth = 0;
TreeNode parent = nodeToSelect;
while ((parent = parent.getParent()) != null) {
depth++;
}
Object[] path = new Object[depth + 1];
parent = nodeToSelect;
for (int i = depth; i >= 0; i--) {
path[depth--] = parent;
parent = parent.getParent();
}
// Select the node and make it visible.
TreePath treePath = new TreePath(path);
m_ProjectTree.setSelectionPath(treePath);
m_ProjectTree.scrollPathToVisible(treePath);
}
}
File getCurrentWorkfileDirectory() {
File currentWorkfileDirectory = null;
// Get the current array of directory managers. The first directory manager is the one
// associated with the currently selected node on the tree...
DirectoryManagerInterface directoryManagers[] = QWinFrame.getQWinFrame().getCurrentDirectoryManagers();
if (directoryManagers != null) {
DirectoryManagerInterface directoryManager = directoryManagers[0];
WorkfileDirectoryManagerInterface workfileDirectoryManager = directoryManager.getWorkfileDirectoryManager();
currentWorkfileDirectory = new File(workfileDirectoryManager.getWorkfileDirectory());
}
return currentWorkfileDirectory;
}
private void initDragAndDrop() {
m_ProjectTree.setDragEnabled(true);
m_ProjectTree.setTransferHandler(new MyTreeTransferHandler());
}
class MyTreeTransferHandler extends TransferHandler {
private static final long serialVersionUID = 10L;
@Override
protected Transferable createTransferable(JComponent c) {
// We are a drop target only. The user cannot drag from the tree
// control
return null;
}
@Override
public boolean canImport(JComponent c, DataFlavor[] flavors) {
for (DataFlavor flavor : flavors) {
if (flavor.equals(QWinFrame.getQWinFrame().getRightFilePane().getDropDataFlavor())) {
return true;
}
}
return false;
}
@Override
public int getSourceActions(JComponent c) {
// We are a drop target only.
return NONE;
}
@Override
public boolean importData(JComponent comp, Transferable t) {
try {
if ((lastSelectedNode instanceof DirectoryTreeNode)
|| (lastSelectedNode instanceof ViewTreeNode)) {
final DropTransferData dropTransferData = (DropTransferData) t.getTransferData(QWinFrame.getQWinFrame().getRightFilePane().getDropDataFlavor());
// Make sure we're dropping on the same project/view
if ((0 == getActiveProject().getProjectName().compareTo(dropTransferData.getProjectName()))
&& (0 == getActiveView().compareTo(dropTransferData.getViewName()))
&& (0 != getAppendedPath().compareTo(QVCSConstants.QVCS_CEMETERY_DIRECTORY))
&& (0 != getAppendedPath().compareTo(QVCSConstants.QVCS_BRANCH_ARCHIVES_DIRECTORY))) {
Runnable later = new Runnable() {
@Override
public void run() {
TransportProxyInterface transportProxy = null;
int transactionID = 0;
// Verify that the user wants to drop here...
int answer = JOptionPane.showConfirmDialog(QWinFrame.getQWinFrame(), "Do you want to move " + dropTransferData.getShortWorkfileName() + " to this directory?\n"
+ getAppendedPath(), "Confirm File Move", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
if (answer == JOptionPane.YES_OPTION) {
ClientRequestMoveFileData clientRequestMoveFileData = new ClientRequestMoveFileData();
clientRequestMoveFileData.setOriginalAppendedPath(dropTransferData.getAppendedPath());
clientRequestMoveFileData.setProjectName(dropTransferData.getProjectName());
clientRequestMoveFileData.setViewName(dropTransferData.getViewName());
clientRequestMoveFileData.setShortWorkfileName(dropTransferData.getShortWorkfileName());
clientRequestMoveFileData.setNewAppendedPath(getAppendedPath());
String serverName = QWinFrame.getQWinFrame().getServerName();
String fullWorkfilePath = QWinFrame.getQWinFrame().getUserWorkfileDirectory();
try {
DirectoryCoordinate directoryCoordinate = new DirectoryCoordinate(dropTransferData.getProjectName(), getViewName(), getAppendedPath());
DirectoryManagerInterface directoryManager = DirectoryManagerFactory.getInstance().getDirectoryManager(serverName, directoryCoordinate,
getActiveProject().getProjectType(), getActiveProject(), fullWorkfilePath, null, false);
ArchiveDirManagerProxy archiveDirManagerProxy = (ArchiveDirManagerProxy) directoryManager.getArchiveDirManager();
transportProxy = archiveDirManagerProxy.getTransportProxy();
// Make sure this is synchronized
synchronized (transportProxy) {
transactionID = ClientTransactionManager.getInstance().sendBeginTransaction(transportProxy);
transportProxy.write(clientRequestMoveFileData);
}
} catch (QVCSException e) {
QWinUtility.logProblem(Level.WARNING, "importData caught exception: " + e.getClass().toString() + " " + e.getLocalizedMessage());
QWinUtility.logProblem(Level.WARNING, Utility.expandStackTraceToString(e));
} finally {
ClientTransactionManager.getInstance().sendEndTransaction(transportProxy, transactionID);
}
}
}
};
SwingUtilities.invokeLater(later);
} else {
if (0 != getActiveProject().getProjectName().compareTo(dropTransferData.getProjectName())) {
QWinUtility.logProblem(Level.INFO, "Cannot move a file from one project to another.");
} else if (0 != getActiveView().compareTo(dropTransferData.getViewName())) {
QWinUtility.logProblem(Level.INFO, "Cannot move a file from one view to another.");
} else if (0 == getAppendedPath().compareTo(QVCSConstants.QVCS_CEMETERY_DIRECTORY)) {
QWinUtility.logProblem(Level.INFO, "Cannot move a file to the cemetery.");
} else if (0 == getAppendedPath().compareTo(QVCSConstants.QVCS_BRANCH_ARCHIVES_DIRECTORY)) {
QWinUtility.logProblem(Level.INFO, "Cannot move a file to the branch archives directory.");
}
return false;
}
} else {
return false;
}
} catch (UnsupportedFlavorException | IOException e) {
return false;
}
return true;
}
@Override
protected void exportDone(JComponent c, Transferable data, int action) {
switch (action) {
case MOVE: {
break;
}
default: {
// Don't do anything else.
break;
}
}
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPopupMenu m_DirectoryPopupMenu;
private javax.swing.JPopupMenu m_ProjectPopupMenu;
private javax.swing.JTree m_ProjectTree;
private javax.swing.JPopupMenu m_RootServerPopupMenu;
private javax.swing.JScrollPane m_ScrollPane;
private javax.swing.JPopupMenu m_ServerPopupMenu;
private javax.swing.JPopupMenu m_ViewPopupMenu;
// End of variables declaration//GEN-END:variables
static class ActionDefineWorkfileLocation extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionDefineWorkfileLocation(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
QWinFrame qWinFrame = QWinFrame.getQWinFrame();
DefineWorkfileLocationDialog defineWorkfileLocationDialog = new DefineWorkfileLocationDialog(qWinFrame);
defineWorkfileLocationDialog.setVisible(true);
if (defineWorkfileLocationDialog.getIsOK()) {
qWinFrame.getUserLocationProperties().setWorkfileLocation(qWinFrame.getServerName(), qWinFrame.getProjectName(), qWinFrame.getViewName(),
defineWorkfileLocationDialog.getWorkfileLocation());
qWinFrame.getUserLocationProperties().saveProperties();
qWinFrame.setUserWorkfileDirectory(defineWorkfileLocationDialog.getWorkfileLocation());
qWinFrame.setRefreshRequired(true);
qWinFrame.setCurrentAppendedPath(qWinFrame.getProjectName(), qWinFrame.getViewName(), qWinFrame.getAppendedPath(), qWinFrame.getProjectType(), false);
}
}
}
class ActionAddDirectory extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionAddDirectory(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationBaseClass addDirectoryOperation = new OperationAddDirectory(QWinFrame.getQWinFrame().getServerName(), QWinFrame.getQWinFrame().getProjectName(), getViewName(),
getAppendedPath(), QWinFrame.getQWinFrame().getUserLocationProperties(), getProjectProperties(), getCurrentWorkfileDirectory());
addDirectoryOperation.executeOperation();
}
}
class ActionDeleteDirectory extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionDeleteDirectory(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationDeleteDirectory deleteDirectoryOperation = new OperationDeleteDirectory(QWinFrame.getQWinFrame().getActiveServerProperties(), getProjectName(), getViewName(), getAppendedPath());
deleteDirectoryOperation.executeOperation();
}
}
class ActionAutoAddFiles extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionAutoAddFiles(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationBaseClass autoAddFilesOperation = new OperationAutoAddFiles(QWinFrame.getQWinFrame().getServerName(), QWinFrame.getQWinFrame().getProjectName(), getViewName(),
getAppendedPath(), QWinFrame.getQWinFrame().getUserLocationProperties(), getProjectProperties(), getCurrentWorkfileDirectory());
autoAddFilesOperation.executeOperation();
}
}
class ActionGetDirectory extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionGetDirectory(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationBaseClass getDirectoryOperation = new OperationGetDirectory(QWinFrame.getQWinFrame().getServerName(), QWinFrame.getQWinFrame().getProjectName(), getViewName(),
getAppendedPath(), QWinFrame.getQWinFrame().getUserLocationProperties(), getProjectProperties(), getCurrentWorkfileDirectory());
getDirectoryOperation.executeOperation();
}
}
class ActionLabelDirectory extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionLabelDirectory(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationBaseClass labelDirectoryOperation = new OperationLabelDirectory(QWinFrame.getQWinFrame().getServerName(), QWinFrame.getQWinFrame().getProjectName(), getViewName(),
getAppendedPath(), QWinFrame.getQWinFrame().getUserLocationProperties(), getProjectProperties(), getCurrentWorkfileDirectory());
labelDirectoryOperation.executeOperation();
}
}
class ActionUnLabelDirectory extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionUnLabelDirectory(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationBaseClass unlabelDirectoryOperation = new OperationUnLabelDirectory(QWinFrame.getQWinFrame().getServerName(), QWinFrame.getQWinFrame().getProjectName(), getViewName(),
getAppendedPath(), QWinFrame.getQWinFrame().getUserLocationProperties(), getProjectProperties(), getCurrentWorkfileDirectory());
unlabelDirectoryOperation.executeOperation();
}
}
static class ActionAddServer extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionAddServer(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationBaseClass addServerOperation = new OperationAddServer(QWinFrame.getQWinFrame().getUserLocationProperties());
addServerOperation.executeOperation();
}
}
static class ActionServerProperties extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionServerProperties(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationBaseClass editServerPropertiesOperation = new OperationEditServerProperties(QWinFrame.getQWinFrame().getServerName(), QWinFrame.getQWinFrame().getUserLocationProperties());
editServerPropertiesOperation.executeOperation();
}
}
static class ActionRemoveServer extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionRemoveServer(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationBaseClass removeServerOperation = new OperationRemoveServer(QWinFrame.getQWinFrame().getServerName(), QWinFrame.getQWinFrame().getUserLocationProperties());
removeServerOperation.executeOperation();
}
}
class ActionDefineView extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionDefineView(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationDefineView defineViewOperation = new OperationDefineView(QWinFrame.getQWinFrame().getActiveServerProperties(), getProjectName());
defineViewOperation.executeOperation();
}
}
class ActionMaintainView extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionMaintainView(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationMaintainView maintainViewOperation = new OperationMaintainView(QWinFrame.getQWinFrame().getActiveServerProperties(), getProjectName(), getViewName(),
(RemoteViewProperties) getProjectProperties());
maintainViewOperation.executeOperation();
}
}
class ActionDeleteView extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionDeleteView(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationDeleteView deleteViewOperation = new OperationDeleteView(QWinFrame.getQWinFrame().getActiveServerProperties(), getProjectName(), getViewName());
deleteViewOperation.executeOperation();
}
}
class ActionExpandTree extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionExpandTree(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
TreePath selectionPath = getProjectJTreeControl().getSelectionPath();
getProjectJTreeControl().expandPath(selectionPath);
expandNode(selectionPath, lastSelectedNode);
}
/**
* Recursive method used to expand a node (and all its children).
*
* @param node the node to expand.
*/
private void expandNode(TreePath anchorTreePath, DefaultMutableTreeNode node) {
Enumeration enumeration = node.children();
while (enumeration.hasMoreElements()) {
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) enumeration.nextElement();
TreePath childTreePath = anchorTreePath.pathByAddingChild(childNode);
getProjectJTreeControl().makeVisible(childTreePath);
if (!childNode.isLeaf()) {
expandNode(childTreePath, childNode);
}
}
}
}
class ActionCollapseTree extends AbstractAction {
private static final long serialVersionUID = 10L;
ActionCollapseTree(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
TreePath selectionPath = getProjectJTreeControl().getSelectionPath();
collapseNode(selectionPath);
}
/**
* Recursive method used to expand a node (and all its children).
*
* @param node the node to expand.
*/
private void collapseNode(TreePath anchorTreePath) {
TreeMap<String, TreePath> map = new TreeMap<>();
Enumeration<TreePath> enumeration = getProjectJTreeControl().getExpandedDescendants(anchorTreePath);
while (enumeration.hasMoreElements()) {
TreePath childTreePath = enumeration.nextElement();
// Subtract the path count from 10,000 so the deeper children will sort first -- i.e.
// we want to collapse the deepest children first, which will happen as a consequence of
// subtracting the path count from 10,000.
String mapKey = String.format("%010d%s", 10000 - childTreePath.getPathCount(), childTreePath.toString());
map.put(mapKey, childTreePath);
}
// Collapse the deepest children first.
Iterator<TreePath> it = map.values().iterator();
while (it.hasNext()) {
TreePath childPath = it.next();
getProjectJTreeControl().collapsePath(childPath);
}
getProjectJTreeControl().collapsePath(anchorTreePath);
}
}
class ActionPromoteFromChild extends AbstractAction {
private static final long serialVersionUID = 1L;
ActionPromoteFromChild(String actionName) {
super(actionName);
}
@Override
public void actionPerformed(ActionEvent e) {
OperationBaseClass promoteFromChildBranchOperation = new OperationPromoteFilesFromChildBranch(QWinFrame.getQWinFrame().getServerName(), QWinFrame.getQWinFrame().getProjectName(),
getViewName(), QWinFrame.getQWinFrame().getUserLocationProperties(), getCurrentWorkfileDirectory());
promoteFromChildBranchOperation.executeOperation();
}
}
static class EnterpriseTreeCellRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 3531447549589503366L;
private final ImageIcon iconServers;
private final ImageIcon iconServer;
private final ImageIcon iconProject;
private final ImageIcon iconReadOnlyView;
private final ImageIcon iconReadWriteView;
EnterpriseTreeCellRenderer(ImageIcon servers, ImageIcon server, ImageIcon project, ImageIcon readOnlyView, ImageIcon readWriteView) {
iconServers = servers;
iconServer = server;
iconProject = project;
iconReadOnlyView = readOnlyView;
iconReadWriteView = readWriteView;
}
@Override
public Component getTreeCellRendererComponent(JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if (value instanceof DefaultServerTreeNode) {
setIcon(iconServers);
} else if (value instanceof ServerTreeNode) {
setIcon(iconServer);
} else if (value instanceof ProjectTreeNode) {
setIcon(iconProject);
} else if (value instanceof ReadOnlyViewNode) {
ReadOnlyViewNode viewNode = (ReadOnlyViewNode) value;
setText(viewNode.getViewName());
setIcon(iconReadOnlyView);
} else if (value instanceof ReadWriteViewNode) {
ReadWriteViewNode viewNode = (ReadWriteViewNode) value;
setText(viewNode.getViewName());
setIcon(iconReadWriteView);
}
return this;
}
}
}