diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java new file mode 100644 index 0000000000..0b5c96993d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java @@ -0,0 +1,203 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * 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 org.sleuthkit.autopsy.coreutils; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.URL; +import java.util.logging.Level; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.awt.NotificationDisplayer; +import org.openide.util.ImageUtilities; + +/** + * Utility for displaying messages and notifications in status area. Wraps + * around NB RCP NotificationDisplayer. + * + * Messages can optionally contain click-able Actions. + * + * Based on: + * http://qbeukes.blogspot.com/2009/11/netbeans-platform-notifications.html + * + * @license Apache License 2.0 + */ +public class MessageNotifyUtil { + + private MessageNotifyUtil() { + } + + public enum MessageType { + + INFO(NotifyDescriptor.INFORMATION_MESSAGE, "info-icon-16.png"), + ERROR(NotifyDescriptor.ERROR_MESSAGE, "error-icon-16.png"), + WARNING(NotifyDescriptor.WARNING_MESSAGE, "warning-icon-16.png"); + private int notifyDescriptorType; + private Icon icon; + + private MessageType(int notifyDescriptorType, String resourceName) { + this.notifyDescriptorType = notifyDescriptorType; + if (resourceName == null) { + icon = new ImageIcon(); + } else { + icon = loadIcon(resourceName); + } + } + + private static Icon loadIcon(String resourceName) { + Icon icon = ImageUtilities.loadImageIcon("org/sleuthkit/autopsy/images/" + resourceName, false); + if (icon == null) { + Logger logger = Logger.getLogger(org.sleuthkit.autopsy.coreutils.MessageNotifyUtil.MessageType.class.getName()); + logger.log(Level.SEVERE, "Failed to load icon resource: " + resourceName + ". Using blank image."); + icon = new ImageIcon(); + } + return icon; + } + + int getNotifyDescriptorType() { + return notifyDescriptorType; + } + + Icon getIcon() { + return icon; + } + } + + /** + * Utility to display messages + */ + public static class Message { + + private Message() { + } + + /** + * @return The dialog displayer used to show message boxes + */ + public static DialogDisplayer getDialogDisplayer() { + return DialogDisplayer.getDefault(); + } + + /** + * Show a message of the specified type + * + * @param message message to show + * @param messageType message type to show + */ + public static void show(String message, MessageType messageType) { + getDialogDisplayer().notify(new NotifyDescriptor.Message(message, + messageType.getNotifyDescriptorType())); + } + + /** + * Show an information dialog + * + * @param message message to show + */ + public static void info(String message) { + show(message, MessageType.INFO); + } + + /** + * Show an error dialog + * + * @param message message to shpw + */ + public static void error(String message) { + show(message, MessageType.ERROR); + } + + /** + * Show an warning dialog + * + * @param message message to show + */ + public static void warn(String message) { + show(message, MessageType.WARNING); + } + } + + /** + * Utility to display notifications with baloons + */ + public static class Notify { + + private Notify() { + } + + /** + * Show message with the specified type and action listener + */ + public static void show(String title, String message, MessageType type, ActionListener actionListener) { + NotificationDisplayer.getDefault().notify(title, type.getIcon(), message, actionListener); + } + + /** + * Show message with the specified type and a default action which + * displays the message using MessageNotifyUtil.Message with the same + * message type + * + * @param title message title + * @param message message text + * @param type type of the message + */ + public static void show(String title, final String message, final MessageType type) { + ActionListener actionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + MessageNotifyUtil.Message.show(message, type); + } + }; + + show(title, message, type, actionListener); + } + + /** + * Show an information notification + * + * @param title message title + * @param message message text + */ + public static void info(String title, String message) { + show(title, message, MessageType.INFO); + } + + /** + * Show an error notification + * + * @param title message title + * @param message message text + */ + public static void error(String title, String message) { + show(title, message, MessageType.ERROR); + } + + /** + * Show an warning notification + * + * @param title message title + * @param message message text + */ + public static void warn(String title, String message) { + show(title, message, MessageType.WARNING); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/images/error-icon-16.png b/Core/src/org/sleuthkit/autopsy/images/error-icon-16.png new file mode 100644 index 0000000000..54ef8cefac Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/images/error-icon-16.png differ diff --git a/Core/src/org/sleuthkit/autopsy/images/info-icon-16.png b/Core/src/org/sleuthkit/autopsy/images/info-icon-16.png new file mode 100644 index 0000000000..a9e499782c Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/images/info-icon-16.png differ diff --git a/Core/src/org/sleuthkit/autopsy/images/warning-icon-16.png b/Core/src/org/sleuthkit/autopsy/images/warning-icon-16.png new file mode 100644 index 0000000000..42a1625a37 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/images/warning-icon-16.png differ diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java index 1a17dfe19a..6fb37791e4 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.ingest; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; @@ -33,6 +35,8 @@ import org.openide.windows.Mode; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType; import org.sleuthkit.datamodel.Image; /** @@ -45,6 +49,7 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing private IngestMessageMainPanel messagePanel; private IngestManager manager; private static String PREFERRED_ID = "IngestMessageTopComponent"; + private ActionListener showIngestInboxAction; public IngestMessageTopComponent() { initComponents(); @@ -54,6 +59,13 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing setToolTipText(NbBundle.getMessage(IngestMessageTopComponent.class, "HINT_IngestMessageTopComponent")); //putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE); + showIngestInboxAction = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + IngestMessagesToolbar.getDefault().showIngestMessages(); + } + }; + } private static synchronized IngestMessageTopComponent getDefault() { @@ -79,13 +91,11 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing protected String preferredID() { return PREFERRED_ID; } - - - /** 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 Form Editor. + /** + * 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 Form Editor. */ // //GEN-BEGIN:initComponents private void initComponents() { @@ -124,11 +134,11 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing super.componentClosed(); /* - Mode mode = WindowManager.getDefault().findMode("dockedBottom"); - if (mode != null) { - mode.dockInto(this); - this.open(); - } + Mode mode = WindowManager.getDefault().findMode("dockedBottom"); + if (mode != null) { + mode.dockInto(this); + this.open(); + } * */ //this.close(); @@ -204,7 +214,6 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing private void registerListeners() { //handle case change Case.addPropertyChangeListener(new PropertyChangeListener() { - @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals(Case.CASE_CURRENT_CASE)) { @@ -219,8 +228,7 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing } try { manager.stopAll(); - } - finally { + } finally { //clear inbox clearMessages(); } @@ -257,7 +265,7 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing final String reportActionName = "org.sleuthkit.autopsy.report.ReportAction"; Action reportAction = null; - + //find action by name from action lookup, without introducing cyclic dependency if (choice == JOptionPane.NO_OPTION) { List actions = Utilities.actionsForPath("Toolbars/File"); @@ -270,11 +278,13 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing } } } - - if (reportAction == null) + + if (reportAction == null) { logger.log(Level.SEVERE, "Could not locate Action: " + reportActionName); - else reportAction.actionPerformed(null); - + } else { + reportAction.actionPerformed(null); + } + } } @@ -285,6 +295,24 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing @Override public void displayMessage(IngestMessage ingestMessage) { messagePanel.addMessage(ingestMessage); + + + //post special messages to notification area + MessageType ingestMessageType = ingestMessage.getMessageType(); + if (ingestMessageType.equals(MessageType.ERROR) + || ingestMessageType.equals(MessageType.WARNING)) { + MessageNotifyUtil.MessageType notifyMessageType = + ingestMessageType.equals(MessageType.ERROR) + ? MessageNotifyUtil.MessageType.ERROR + : MessageNotifyUtil.MessageType.WARNING; + + String details = ingestMessage.getDetails(); + if (details == null) { + details = ""; + } + MessageNotifyUtil.Notify.show(ingestMessage.getSubject(), details, + notifyMessageType, showIngestInboxAction); + } } @Override @@ -292,8 +320,6 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing return messagePanel.getMessagesCount(); } - - @Override public void clearMessages() { messagePanel.clearMessages(); @@ -302,9 +328,9 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing @Override public void displayIngestDialog(final Image image) { /* - final IngestDialog ingestDialog = new IngestDialog(); - ingestDialog.setImage(image); - ingestDialog.display(); + final IngestDialog ingestDialog = new IngestDialog(); + ingestDialog.setImage(image); + ingestDialog.display(); */ } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java index ef4a89777d..51167f8ef9 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java @@ -130,7 +130,10 @@ public class IngestMessagesToolbar extends javax.swing.JPanel { }); } - private void showIngestMessages() { + /** + * Pop up and show ingest messages window + */ + void showIngestMessages() { IngestMessageTopComponent tc = IngestMessageTopComponent.findInstance(); Mode mode = WindowManager.getDefault().findMode("floatingLeftBottom");