/**
* NanoDoA - File based document archive
*
* Copyright (C) 2011-2012 Christian Packenius, christian.packenius@googlemail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.chris_soft.nanodoa.gui.tree;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.JTree;
import javax.swing.filechooser.FileFilter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import de.chris_soft.nanodoa.God;
import de.chris_soft.nanodoa.gui.ZipFileFilter;
import de.chris_soft.nanodoa.gui.actions.ReSearchAction;
import de.chris_soft.nanodoa.gui.tree.path.DocumentPath;
import de.chris_soft.nanodoa.gui.tree.path.LabelPath;
import de.chris_soft.nanodoa.gui.tree.path.SearchPath;
import de.chris_soft.nanodoa.misc.MailKeys;
import de.chris_soft.utilities.AppProperties;
import de.chris_soft.utilities.FileUtils;
import de.chris_soft.utilities.IdUtils;
import de.chris_soft.utilities.LogUtils;
import de.chris_soft.utilities.SendHtmlMailUtils;
import de.chris_soft.utilities.swing.SwingUtils;
/**
* Mouse listener for all document trees.
* @author Christian Packenius.
*/
public class TreeMouseListener implements MouseListener {
/**
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
*/
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) setTreePathFromEventCoordinates(e);
if (node != null) {
Object userObject = node.getUserObject();
JPopupMenu menu = getNewPopupMenu(node);
int menuSize = menu.getComponentCount();
if (userObject instanceof SearchPath) {
rightClickedOnSearchPath(e, node, menu);
}
else if (userObject instanceof DocumentPath) {
rightClickedOnDocumentPath(e, node, menu);
}
else {
rightClickedOnAnyPath(e, node, menu);
}
if (menu.getComponentCount() > menuSize) {
menu.add(new JSeparator(), menuSize);
}
menu.show((JComponent) e.getSource(), e.getX(), e.getY());
}
}
}
private void rightClickedOnSearchPath(MouseEvent e, DefaultMutableTreeNode node, JPopupMenu menu) {
final SearchPath searchPath = (SearchPath) node.getUserObject();
JMenuItem menuItem = new JMenuItem("Re-Search");
menuItem.addActionListener(new ReSearchAction(searchPath.name, God.specialsTree));
menu.add(menuItem);
menu.show((JComponent) e.getSource(), e.getX(), e.getY());
}
private void rightClickedOnDocumentPath(MouseEvent e, DefaultMutableTreeNode node, JPopupMenu menu) {
final DocumentPath documentPath = (DocumentPath) node.getUserObject();
Object parent = ((DefaultMutableTreeNode) node.getParent()).getUserObject();
if (parent instanceof LabelPath) {
final LabelPath labelPath = (LabelPath) parent;
JMenuItem menuItem = new JMenuItem("Remove label '" + labelPath.toString() + "' from this document");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
God.archive.db.removeLabelFromDocument(documentPath.getID(), labelPath.getID());
God.appWindow.refreshLabelList();
}
catch (SQLException exception) {
SwingUtils.showError(God.appWindow.frame, "Couldn't remove label from document!");
}
}
});
menu.add(menuItem);
}
}
private void rightClickedOnAnyPath(MouseEvent e, DefaultMutableTreeNode node, JPopupMenu menu) {
menu.show((JComponent) e.getSource(), e.getX(), e.getY());
}
private JPopupMenu getNewPopupMenu(final DefaultMutableTreeNode node) {
JPopupMenu menu = new JPopupMenu();
addFileExportMenuItemToPopupMenu(node, menu);
addMailExportMenuItemToPopupMenu(node, menu);
menu.add(new JSeparator());
addOpenInStandardViewer(node, menu);
addPrintWithStandardViewer(node, menu);
return menu;
}
private void addFileExportMenuItemToPopupMenu(final DefaultMutableTreeNode node, JPopupMenu menu) {
JMenuItem menuItem = new JMenuItem("Export document(s) to file system");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File zipName = getSaveZipFileName(God.appWindow.frame, null);
List<Long> documentIDs = new ArrayList<Long>();
listAllDocumentsUnderNode(documentIDs, node);
List<File> documentFiles = readAllDocumentsFromDatabase(documentIDs);
if (documentFiles != null) {
try {
FileUtils.saveZipFile(zipName, documentFiles);
}
catch (IOException exception) {
SwingUtils.showError(God.appWindow.frame, "Couldn't write ZIP file! [" + exception.getMessage() + "]");
LogUtils.log(exception);
}
}
}
});
menu.add(menuItem);
}
private void addOpenInStandardViewer(final DefaultMutableTreeNode node, JPopupMenu menu) {
JMenuItem menuItem = new JMenuItem("Open in standard PDF viewer");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<Long> documentIDs = new ArrayList<Long>();
listAllDocumentsUnderNode(documentIDs, node);
List<File> documentFiles = readAllDocumentsFromDatabase(documentIDs);
if (documentFiles != null) {
try {
for (File file : documentFiles) {
Desktop.getDesktop().open(file);
}
}
catch (IOException exception) {
String errmsg = "Couldn't open PDF file(s) in standard viewer! [" + exception.getMessage() + "]";
SwingUtils.showError(God.appWindow.frame, errmsg);
LogUtils.log(exception);
}
}
}
});
menu.add(menuItem);
}
private void addPrintWithStandardViewer(final DefaultMutableTreeNode node, JPopupMenu menu) {
JMenuItem menuItem = new JMenuItem("Print with standard PDF viewer");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<Long> documentIDs = new ArrayList<Long>();
listAllDocumentsUnderNode(documentIDs, node);
List<File> documentFiles = readAllDocumentsFromDatabase(documentIDs);
if (documentFiles != null) {
try {
for (File file : documentFiles) {
Desktop.getDesktop().print(file);
}
}
catch (IOException exception) {
String errmsg = "Couldn't print PDF file(s) with standard viewer! [" + exception.getMessage() + "]";
SwingUtils.showError(God.appWindow.frame, errmsg);
LogUtils.log(exception);
}
}
}
});
menu.add(menuItem);
}
private void addMailExportMenuItemToPopupMenu(final DefaultMutableTreeNode node, JPopupMenu menu) {
JMenuItem menuItem = new JMenuItem("Export document(s) as mail");
if (!Boolean.parseBoolean(AppProperties.getProperty(MailKeys.PROP_KEY_SHALL_SEND_MAIL))) {
menuItem.setEnabled(false);
}
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File zipName = new File("temp/" + IdUtils.getUniqueID() + ".zip");
List<Long> documentIDs = new ArrayList<Long>();
listAllDocumentsUnderNode(documentIDs, node);
List<File> documentFiles = readAllDocumentsFromDatabase(documentIDs);
if (documentFiles != null) {
try {
FileUtils.saveZipFile(zipName, documentFiles);
sendZipFile(zipName);
}
catch (IOException exception) {
String errmsg = "Couldn't write ZIP file for mail export! [" + exception.getMessage() + "]";
SwingUtils.showError(God.appWindow.frame, errmsg);
LogUtils.log(exception);
}
}
}
private void sendZipFile(File zipFile) {
try {
SendHtmlMailUtils mail = new SendHtmlMailUtils();
mail.addAttachment(zipFile);
mail.addTO(AppProperties.getProperty(MailKeys.PROP_KEY_RECEIVER_MAIL_ADDRESS));
mail.setFrom(AppProperties.getProperty(MailKeys.PROP_KEY_SENDER_MAIL_ADDRESS));
mail.setLogin(AppProperties.getProperty(MailKeys.PROP_KEY_SENDER_MAIL_ADDRESS));
mail.setPassword(AppProperties.getProperty(MailKeys.PROP_KEY_SENDER_MAIL_PW));
mail.setPop3Host(AppProperties.getProperty(MailKeys.PROP_KEY_SENDER_POP3_SERVER));
int smptPort = Integer.parseInt(AppProperties.getProperty(MailKeys.PROP_KEY_SENDER_SMTP_PORT));
mail.setSmtp(AppProperties.getProperty(MailKeys.PROP_KEY_SENDER_SMTP_SERVER), smptPort);
mail.setSubject("Your zipped documents");
mail.setText("");
mail.sendMail();
}
catch (Exception e) {
LogUtils.log(e);
SwingUtils.showError(God.appWindow.frame, "Problems when sending documents mail! [" + e.getMessage() + "]");
}
}
});
menu.add(menuItem);
}
void listAllDocumentsUnderNode(List<Long> documents, DefaultMutableTreeNode node) {
Object userObject = node.getUserObject();
if (userObject instanceof DocumentPath) {
DocumentPath docPath = (DocumentPath) userObject;
documents.add(docPath.docID);
}
Enumeration<?> children = node.children();
while (children.hasMoreElements()) {
DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
listAllDocumentsUnderNode(documents, child);
}
}
List<File> readAllDocumentsFromDatabase(List<Long> documentIDs) {
List<File> documentFiles = new ArrayList<File>();
for (Long docID : documentIDs) {
try {
File documentFile = God.archive.getDocumentFileFromDocID(docID);
documentFiles.add(documentFile);
}
catch (Exception exception) {
SwingUtils.showError(God.appWindow.frame, "Error on reading document " + docID + " / no writing zip file!");
LogUtils.log(exception);
return null;
}
}
return documentFiles;
}
/**
* Let the user set a directory over dialog.
* @param parent Parent window.
* @param initialPath First directory to show.
* @return New directory choice or <i>null</i> if aborted.
*/
File getSaveZipFileName(Component parent, File initialPath) {
JFileChooser fileChooser = new JFileChooser();
if (initialPath == null) {
fileChooser.setCurrentDirectory(initialPath);
}
fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
fileChooser.setDialogTitle("Save document(s) as ZIP file");
fileChooser.setSelectedFile(new File("documents.zip"));
FileFilter zipFileFilter = new ZipFileFilter();
fileChooser.setFileFilter(zipFileFilter);
if (fileChooser.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) {
return fileChooser.getSelectedFile();
}
return null;
}
private TreeNode setTreePathFromEventCoordinates(MouseEvent e) {
JTree tree = (JTree) e.getSource();
TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
if (selPath != null) {
tree.setSelectionPath(selPath);
return (TreeNode) selPath.getLastPathComponent();
}
return null;
}
/**
* @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
*/
@Override
public void mousePressed(MouseEvent e) {
// Ignore.
}
/**
* @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
*/
@Override
public void mouseReleased(MouseEvent e) {
// Ignore.
}
/**
* @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
*/
@Override
public void mouseEntered(MouseEvent e) {
// Ignore.
}
/**
* @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
*/
@Override
public void mouseExited(MouseEvent e) {
// Ignore.
}
}