19 package org.sleuthkit.autopsy.communications;
 
   21 import com.google.common.eventbus.Subscribe;
 
   22 import com.mxgraph.layout.hierarchical.mxHierarchicalLayout;
 
   23 import com.mxgraph.layout.mxCircleLayout;
 
   24 import com.mxgraph.layout.mxFastOrganicLayout;
 
   25 import com.mxgraph.layout.mxIGraphLayout;
 
   26 import com.mxgraph.layout.mxOrganicLayout;
 
   27 import com.mxgraph.model.mxCell;
 
   28 import com.mxgraph.model.mxICell;
 
   29 import com.mxgraph.swing.handler.mxRubberband;
 
   30 import com.mxgraph.swing.mxGraphComponent;
 
   31 import com.mxgraph.util.mxEvent;
 
   32 import com.mxgraph.util.mxEventObject;
 
   33 import com.mxgraph.util.mxEventSource;
 
   34 import com.mxgraph.util.mxPoint;
 
   35 import com.mxgraph.util.mxRectangle;
 
   36 import com.mxgraph.util.mxUndoManager;
 
   37 import com.mxgraph.util.mxUndoableEdit;
 
   38 import com.mxgraph.view.mxCellState;
 
   39 import com.mxgraph.view.mxGraph;
 
   40 import com.mxgraph.view.mxGraphView;
 
   41 import java.awt.BorderLayout;
 
   42 import java.awt.Color;
 
   43 import java.awt.Cursor;
 
   44 import java.awt.Dimension;
 
   46 import java.awt.Frame;
 
   47 import java.awt.Graphics;
 
   48 import java.awt.event.ActionEvent;
 
   49 import java.awt.event.ActionListener;
 
   50 import java.awt.event.MouseAdapter;
 
   51 import java.awt.event.MouseEvent;
 
   52 import java.awt.event.MouseWheelEvent;
 
   53 import java.beans.PropertyChangeEvent;
 
   54 import java.beans.PropertyVetoException;
 
   55 import java.text.DecimalFormat;
 
   56 import java.util.Arrays;
 
   57 import java.util.EnumSet;
 
   58 import java.util.HashMap;
 
   59 import java.util.HashSet;
 
   60 import java.util.List;
 
   63 import java.util.concurrent.ExecutionException;
 
   64 import java.util.concurrent.Future;
 
   65 import java.util.function.BiConsumer;
 
   66 import java.util.logging.Level;
 
   67 import java.util.stream.Collectors;
 
   68 import java.util.stream.Stream;
 
   69 import javafx.application.Platform;
 
   70 import javafx.embed.swing.JFXPanel;
 
   71 import javafx.scene.Scene;
 
   72 import javafx.scene.layout.Pane;
 
   73 import javax.swing.AbstractAction;
 
   74 import javax.swing.ImageIcon;
 
   75 import javax.swing.JButton;
 
   76 import javax.swing.JLabel;
 
   77 import javax.swing.JMenuItem;
 
   78 import javax.swing.JPanel;
 
   79 import javax.swing.JPopupMenu;
 
   80 import javax.swing.JSplitPane;
 
   81 import javax.swing.JTextArea;
 
   82 import javax.swing.JToolBar;
 
   83 import javax.swing.SwingConstants;
 
   84 import javax.swing.SwingUtilities;
 
   85 import javax.swing.SwingWorker;
 
   86 import org.controlsfx.control.Notifications;
 
   87 import org.jdesktop.layout.GroupLayout;
 
   88 import org.jdesktop.layout.LayoutStyle;
 
   89 import org.openide.explorer.ExplorerManager;
 
   90 import org.openide.explorer.ExplorerUtils;
 
   91 import org.openide.nodes.Node;
 
   92 import org.openide.util.Lookup;
 
   93 import org.openide.util.NbBundle;
 
   94 import org.openide.util.lookup.ProxyLookup;
 
  115 @SuppressWarnings(
"PMD.SingularField") 
 
  118     private static final long serialVersionUID = 1L;
 
  120     private static final String BASE_IMAGE_PATH = 
"/org/sleuthkit/autopsy/communications/images";
 
  121     static final private ImageIcon unlockIcon
 
  123     static final private ImageIcon lockIcon
 
  126     @NbBundle.Messages(
"VisualizationPanel.cancelButton.text=Cancel")
 
  127     private static final String CANCEL = Bundle.VisualizationPanel_cancelButton_text();
 
  129     private final ExplorerManager vizEM = 
new ExplorerManager();
 
  130     private final ExplorerManager gacEM = 
new ExplorerManager();
 
  138     private final CommunicationsGraph 
graph;
 
  140     private final mxUndoManager undoManager = 
new mxUndoManager();
 
  144     private SwingWorker<?, ?> worker;
 
  145     private final PinnedAccountModel pinnedAccountModel = new PinnedAccountModel();
 
  146     private final LockedVertexModel lockedVertexModel = new LockedVertexModel();
 
  149     private NamedGraphLayout currentLayout;
 
  151     @NbBundle.Messages("VisalizationPanel.paintingError=Problem painting visualization.")
 
  155         notificationsJFXPanel.setScene(
new Scene(
new Pane()));
 
  157         graph = 
new CommunicationsGraph(pinnedAccountModel, lockedVertexModel);
 
  165         graphComponent = 
new mxGraphComponent(graph) {
 
  167             protected mxGraphComponent.mxGraphControl createGraphControl() {
 
  169                 return new mxGraphControl() {
 
  172                     public void paint(Graphics graphics) {
 
  174                             super.paint(graphics);
 
  175                         } 
catch (NullPointerException ex) { 
 
  181                             logger.log(Level.WARNING, 
"There was a NPE while painting the VisualizationPanel", ex);
 
  188         graphComponent.setAutoExtend(
true);
 
  189         graphComponent.setAutoScroll(
true);
 
  190         graphComponent.setAutoscrolls(
true);
 
  191         graphComponent.setConnectable(
false);
 
  192         graphComponent.setDragEnabled(
false);
 
  193         graphComponent.setKeepSelectionVisibleOnZoom(
true);
 
  194         graphComponent.setOpaque(
true);
 
  195         graphComponent.setToolTips(
true);
 
  196         graphComponent.setBackground(Color.WHITE);
 
  197         borderLayoutPanel.add(graphComponent, BorderLayout.CENTER);
 
  200         rubberband = 
new mxRubberband(graphComponent);
 
  202         lockedVertexModel.registerhandler(
this);
 
  204         final mxEventSource.mxIEventListener scaleListener = (Object sender, mxEventObject evt)
 
  205                 -> zoomLabel.setText(DecimalFormat.getPercentInstance().format(graph.getView().getScale()));
 
  206         graph.getView().addListener(mxEvent.SCALE, scaleListener);
 
  207         graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, scaleListener);
 
  210         graphComponent.getGraphControl().addMouseWheelListener(graphMouseListener);
 
  211         graphComponent.getGraphControl().addMouseListener(graphMouseListener);
 
  214         splitPane.setRightComponent(messageBrowser);
 
  215         proxyLookup = 
new ProxyLookup(
 
  216                 ExplorerUtils.createLookup(vizEM, getActionMap()),
 
  222         final mxEventSource.mxIEventListener undoListener = (Object sender, mxEventObject evt)
 
  223                 -> undoManager.undoableEditHappened((mxUndoableEdit) evt.getProperty(
"edit"));
 
  225         graph.getModel().addListener(mxEvent.UNDO, undoListener);
 
  226         graph.getView().addListener(mxEvent.UNDO, undoListener);
 
  231         organicLayout.setMaxIterations(10);
 
  235         BiConsumer<JButton, NamedGraphLayout> configure = (layoutButton, layout) -> {
 
  236             layoutButtons.put(layout, layoutButton);
 
  237             layoutButton.addActionListener(event -> applyLayout(layout));
 
  240         configure.accept(circleLayoutButton, circleLayout);
 
  241         configure.accept(organicLayoutButton, organicLayout);
 
  242         configure.accept(fastOrganicLayoutButton, fastOrganicLayout);
 
  243         configure.accept(hierarchyLayoutButton, hierarchyLayout);
 
  245         applyLayout(fastOrganicLayout);
 
  254     void handle(LockedVertexModel.VertexLockEvent event) {
 
  255         final Set<mxCell> vertices = 
event.getVertices();
 
  256         mxGraphView view = graph.getView();
 
  257         vertices.forEach(vertex -> {
 
  258             final mxCellState state = view.getState(vertex, 
true);
 
  259             view.updateLabel(state);
 
  260             view.updateLabelBounds(state);
 
  261             view.updateBoundingBox(state);
 
  262             graphComponent.redraw(state);
 
  267     void handle(
final CVTEvents.UnpinAccountsEvent pinEvent) {
 
  268         graph.getModel().beginUpdate();
 
  269         pinnedAccountModel.unpinAccount(pinEvent.getAccountDeviceInstances());
 
  273         graph.getModel().endUpdate();
 
  277     void handle(
final CVTEvents.PinAccountsEvent pinEvent) {
 
  278         graph.getModel().beginUpdate();
 
  279         if (pinEvent.isReplace()) {
 
  282         pinnedAccountModel.pinAccount(pinEvent.getAccountDeviceInstances());
 
  285         graph.getModel().endUpdate();
 
  289     void handle(
final CVTEvents.FilterChangeEvent filterChangeEvent) {
 
  290         graph.getModel().beginUpdate();
 
  292         currentFilter = filterChangeEvent.getNewFilter();
 
  295         graph.getModel().endUpdate();
 
  298     @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
 
  299     private 
void rebuildGraph() {
 
  300         if (pinnedAccountModel.isEmpty()) {
 
  301             borderLayoutPanel.remove(graphComponent);
 
  302             borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
 
  305             borderLayoutPanel.remove(placeHolderPanel);
 
  306             borderLayoutPanel.add(graphComponent, BorderLayout.CENTER);
 
  307             if (worker != null) {
 
  313             worker = graph.rebuild(progress, commsManager, currentFilter);
 
  314             cancelationListener.configure(worker, progress);
 
  315             worker.addPropertyChangeListener((
final PropertyChangeEvent evt) -> {
 
  316                 if (worker.isDone()) {
 
  317                     if (worker.isCancelled()) {
 
  321                     applyLayout(currentLayout);
 
  332         windowAncestor = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, 
this);
 
  336         } 
catch (TskCoreException ex) {
 
  337             logger.log(Level.SEVERE, 
"Error getting CommunicationsManager for the current case.", ex);
 
  339             logger.log(Level.SEVERE, 
"Can't get CommunicationsManager when there is no case open.", ex);
 
  343             graph.getModel().beginUpdate();
 
  347                 graph.getModel().endUpdate();
 
  349             if (evt.getNewValue() == null) {
 
  352                 Case currentCase = (
Case) evt.getNewValue();
 
  355                 } 
catch (TskCoreException ex) {
 
  356                     logger.log(Level.SEVERE, 
"Error getting CommunicationsManager for the current case.", ex);
 
  367     @SuppressWarnings(
"unchecked")
 
  369     private 
void initComponents() {
 
  371         splitPane = 
new JSplitPane();
 
  372         borderLayoutPanel = 
new JPanel();
 
  373         placeHolderPanel = 
new JPanel();
 
  374         jTextArea1 = 
new JTextArea();
 
  375         toolbar = 
new JPanel();
 
  376         jLabel1 = 
new JLabel();
 
  377         hierarchyLayoutButton = 
new JButton();
 
  378         fastOrganicLayoutButton = 
new JButton();
 
  379         organicLayoutButton = 
new JButton();
 
  380         circleLayoutButton = 
new JButton();
 
  381         jSeparator1 = 
new JToolBar.Separator();
 
  382         zoomOutButton = 
new JButton();
 
  383         zoomInButton = 
new JButton();
 
  384         zoomActualButton = 
new JButton();
 
  385         fitZoomButton = 
new JButton();
 
  386         jLabel2 = 
new JLabel();
 
  387         zoomLabel = 
new JLabel();
 
  388         clearVizButton = 
new JButton();
 
  389         jSeparator2 = 
new JToolBar.Separator();
 
  390         notificationsJFXPanel = 
new JFXPanel();
 
  392         setLayout(
new BorderLayout());
 
  394         splitPane.setDividerLocation(800);
 
  395         splitPane.setResizeWeight(0.5);
 
  397         borderLayoutPanel.setLayout(
new BorderLayout());
 
  399         jTextArea1.setBackground(
new Color(240, 240, 240));
 
  400         jTextArea1.setColumns(20);
 
  401         jTextArea1.setLineWrap(
true);
 
  402         jTextArea1.setRows(5);
 
  403         jTextArea1.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.jTextArea1.text")); 
 
  405         GroupLayout placeHolderPanelLayout = 
new GroupLayout(placeHolderPanel);
 
  406         placeHolderPanel.setLayout(placeHolderPanelLayout);
 
  407         placeHolderPanelLayout.setHorizontalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
 
  408             .add(placeHolderPanelLayout.createSequentialGroup()
 
  409                 .addContainerGap(71, Short.MAX_VALUE)
 
  410                 .add(jTextArea1, GroupLayout.PREFERRED_SIZE, 424, GroupLayout.PREFERRED_SIZE)
 
  411                 .addContainerGap(248, Short.MAX_VALUE))
 
  413         placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
 
  414             .add(placeHolderPanelLayout.createSequentialGroup()
 
  415                 .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  416                 .add(jTextArea1, GroupLayout.PREFERRED_SIZE, 47, GroupLayout.PREFERRED_SIZE)
 
  417                 .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  420         borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
 
  422         jLabel1.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.jLabel1.text")); 
 
  424         hierarchyLayoutButton.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.hierarchyLayoutButton.text")); 
 
  425         hierarchyLayoutButton.setFocusable(
false);
 
  426         hierarchyLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER);
 
  427         hierarchyLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM);
 
  429         fastOrganicLayoutButton.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.fastOrganicLayoutButton.text")); 
 
  430         fastOrganicLayoutButton.setFocusable(
false);
 
  431         fastOrganicLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER);
 
  432         fastOrganicLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM);
 
  434         organicLayoutButton.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.organicLayoutButton.text")); 
 
  435         organicLayoutButton.setFocusable(
false);
 
  436         organicLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER);
 
  437         organicLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM);
 
  439         circleLayoutButton.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.circleLayoutButton.text")); 
 
  440         circleLayoutButton.setFocusable(
false);
 
  441         circleLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER);
 
  442         circleLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM);
 
  444         jSeparator1.setOrientation(SwingConstants.VERTICAL);
 
  446         zoomOutButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/magnifier-zoom-out-red.png"))); 
 
  447         zoomOutButton.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.zoomOutButton.text")); 
 
  448         zoomOutButton.setToolTipText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.zoomOutButton.toolTipText")); 
 
  449         zoomOutButton.setFocusable(
false);
 
  450         zoomOutButton.setHorizontalTextPosition(SwingConstants.CENTER);
 
  451         zoomOutButton.setVerticalTextPosition(SwingConstants.BOTTOM);
 
  452         zoomOutButton.addActionListener(
new ActionListener() {
 
  453             public void actionPerformed(ActionEvent evt) {
 
  454                 zoomOutButtonActionPerformed(evt);
 
  458         zoomInButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/magnifier-zoom-in-green.png"))); 
 
  459         zoomInButton.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.zoomInButton.text")); 
 
  460         zoomInButton.setToolTipText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.zoomInButton.toolTipText")); 
 
  461         zoomInButton.setFocusable(
false);
 
  462         zoomInButton.setHorizontalTextPosition(SwingConstants.CENTER);
 
  463         zoomInButton.setVerticalTextPosition(SwingConstants.BOTTOM);
 
  464         zoomInButton.addActionListener(
new ActionListener() {
 
  465             public void actionPerformed(ActionEvent evt) {
 
  466                 zoomInButtonActionPerformed(evt);
 
  470         zoomActualButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/magnifier-zoom-actual.png"))); 
 
  471         zoomActualButton.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.zoomActualButton.text")); 
 
  472         zoomActualButton.setToolTipText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.zoomActualButton.toolTipText")); 
 
  473         zoomActualButton.setFocusable(
false);
 
  474         zoomActualButton.setHorizontalTextPosition(SwingConstants.CENTER);
 
  475         zoomActualButton.setVerticalTextPosition(SwingConstants.BOTTOM);
 
  476         zoomActualButton.addActionListener(
new ActionListener() {
 
  477             public void actionPerformed(ActionEvent evt) {
 
  478                 zoomActualButtonActionPerformed(evt);
 
  482         fitZoomButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/magnifier-zoom-fit.png"))); 
 
  483         fitZoomButton.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.fitZoomButton.text")); 
 
  484         fitZoomButton.setToolTipText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.fitZoomButton.toolTipText")); 
 
  485         fitZoomButton.setFocusable(
false);
 
  486         fitZoomButton.setHorizontalTextPosition(SwingConstants.CENTER);
 
  487         fitZoomButton.setVerticalTextPosition(SwingConstants.BOTTOM);
 
  488         fitZoomButton.addActionListener(
new ActionListener() {
 
  489             public void actionPerformed(ActionEvent evt) {
 
  490                 fitZoomButtonActionPerformed(evt);
 
  494         jLabel2.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.jLabel2.text")); 
 
  496         zoomLabel.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.zoomLabel.text")); 
 
  498         clearVizButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/broom.png"))); 
 
  499         clearVizButton.setText(NbBundle.getMessage(
VisualizationPanel.class, 
"VisualizationPanel.clearVizButton.text_1")); 
 
  500         clearVizButton.addActionListener(
new ActionListener() {
 
  501             public void actionPerformed(ActionEvent evt) {
 
  502                 clearVizButtonActionPerformed(evt);
 
  506         jSeparator2.setOrientation(SwingConstants.VERTICAL);
 
  508         GroupLayout toolbarLayout = 
new GroupLayout(toolbar);
 
  509         toolbar.setLayout(toolbarLayout);
 
  510         toolbarLayout.setHorizontalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING)
 
  511             .add(toolbarLayout.createSequentialGroup()
 
  515                 .add(jSeparator1, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
 
  518                 .addPreferredGap(LayoutStyle.RELATED)
 
  519                 .add(fastOrganicLayoutButton)
 
  520                 .addPreferredGap(LayoutStyle.RELATED)
 
  521                 .add(organicLayoutButton)
 
  522                 .addPreferredGap(LayoutStyle.RELATED)
 
  523                 .add(hierarchyLayoutButton)
 
  524                 .addPreferredGap(LayoutStyle.RELATED)
 
  525                 .add(circleLayoutButton)
 
  526                 .addPreferredGap(LayoutStyle.RELATED)
 
  527                 .add(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
 
  528                 .addPreferredGap(LayoutStyle.RELATED)
 
  530                 .addPreferredGap(LayoutStyle.RELATED)
 
  532                 .addPreferredGap(LayoutStyle.RELATED)
 
  533                 .add(zoomOutButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
 
  534                 .addPreferredGap(LayoutStyle.RELATED)
 
  535                 .add(zoomInButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
 
  536                 .addPreferredGap(LayoutStyle.RELATED)
 
  537                 .add(zoomActualButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)
 
  538                 .addPreferredGap(LayoutStyle.RELATED)
 
  539                 .add(fitZoomButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
 
  540                 .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  542         toolbarLayout.setVerticalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING)
 
  543             .add(toolbarLayout.createSequentialGroup()
 
  545                 .add(toolbarLayout.createParallelGroup(GroupLayout.CENTER)
 
  546                     .add(jLabel1, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
 
  547                     .add(hierarchyLayoutButton)
 
  548                     .add(fastOrganicLayoutButton)
 
  549                     .add(organicLayoutButton)
 
  550                     .add(circleLayoutButton)
 
  551                     .add(jSeparator1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  553                     .add(zoomInButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  554                     .add(zoomActualButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  555                     .add(fitZoomButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  559                     .add(jSeparator2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  563         borderLayoutPanel.add(toolbar, BorderLayout.PAGE_START);
 
  564         borderLayoutPanel.add(notificationsJFXPanel, BorderLayout.PAGE_END);
 
  566         splitPane.setLeftComponent(borderLayoutPanel);
 
  568         add(splitPane, BorderLayout.CENTER);
 
  576         graphComponent.zoomActual();
 
  580         graphComponent.zoomIn();
 
  584         graphComponent.zoomOut();
 
  593     @NbBundle.Messages({
"VisualizationPanel.computingLayout=Computing Layout",
 
  594         "# {0} - layout name",
 
  595         "VisualizationPanel.layoutFailWithLockedVertices.text={0} layout failed with locked vertices. Unlock some vertices or try a different layout.",
 
  596         "# {0} -  layout name",
 
  597         "VisualizationPanel.layoutFail.text={0} layout failed. Try a different layout."})
 
  599         currentLayout = layout;
 
  600         layoutButtons.forEach((layoutKey, button)
 
  601                 -> button.setFont(button.getFont().deriveFont(layoutKey == layout ? Font.BOLD : Font.PLAIN)));
 
  604         progressIndicator.
start(Bundle.VisualizationPanel_computingLayout());
 
  606         new SwingWorker<Void, Void>() {
 
  608             protected Void doInBackground() {
 
  609                 graph.getModel().beginUpdate();
 
  611                     layout.execute(graph.getDefaultParent());
 
  614                     graph.getModel().endUpdate();
 
  615                     progressIndicator.
finish();
 
  621             protected void done() {
 
  624                 } 
catch (InterruptedException | ExecutionException ex) {
 
  625                     logger.log(Level.WARNING, 
"CVT graph layout failed.", ex);
 
  626                     String message = (lockedVertexModel.isEmpty())
 
  627                             ? Bundle.VisualizationPanel_layoutFail_text(layout.
getDisplayName())
 
  628                             : Bundle.VisualizationPanel_layoutFailWithLockedVertices_text(layout.
getDisplayName());
 
  631                             -> Notifications.create().owner(notificationsJFXPanel.getScene().getWindow())
 
  641         setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  642         graph.getModel().beginUpdate();
 
  643         pinnedAccountModel.clear();
 
  647         graph.getModel().endUpdate();
 
  648         setCursor(Cursor.getDefaultCursor());
 
  652         graphComponent.zoomTo(1, 
true);
 
  653         mxPoint translate = graph.getView().getTranslate();
 
  654         if (translate == null || Double.isNaN(translate.getX()) || Double.isNaN(translate.getY())) {
 
  655             translate = 
new mxPoint();
 
  658         mxRectangle boundsForCells = graph.getCellBounds(graph.getDefaultParent(), 
true, 
true, 
true);
 
  659         if (boundsForCells == null || Double.isNaN(boundsForCells.getWidth()) || Double.isNaN(boundsForCells.getHeight())) {
 
  660             boundsForCells = 
new mxRectangle(0, 0, 1, 1);
 
  662         final mxPoint mxPoint = 
new mxPoint(translate.getX() - boundsForCells.getX(), translate.getY() - boundsForCells.getY());
 
  664         graph.cellsMoved(graph.getChildCells(graph.getDefaultParent()), mxPoint.getX(), mxPoint.getY(), 
false, 
false);
 
  666         boundsForCells = graph.getCellBounds(graph.getDefaultParent(), 
true, 
true, 
true);
 
  667         if (boundsForCells == null || Double.isNaN(boundsForCells.getWidth()) || Double.isNaN(boundsForCells.getHeight())) {
 
  668             boundsForCells = 
new mxRectangle(0, 0, 1, 1);
 
  671         final Dimension size = graphComponent.getSize();
 
  672         final double widthFactor = size.getWidth() / boundsForCells.getWidth();
 
  673         final double heightFactor = size.getHeight() / boundsForCells.getHeight();
 
  675         graphComponent.zoom((heightFactor + widthFactor) / 2.0);
 
  708         @SuppressWarnings(
"unchecked")
 
  710         public void invoke(Object sender, mxEventObject evt) {
 
  711             Object[] selectionCells = graph.getSelectionCells();
 
  712             Node rootNode = Node.EMPTY;
 
  713             Node[] selectedNodes = 
new Node[0];
 
  714             if (selectionCells.length > 0) {
 
  715                 mxICell[] selectedCells = Arrays.asList(selectionCells).toArray(
new mxCell[selectionCells.length]);
 
  716                 HashSet<Content> relationshipSources = 
new HashSet<>();
 
  717                 HashSet<AccountDeviceInstanceKey> adis = 
new HashSet<>();
 
  718                 for (mxICell cell : selectedCells) {
 
  720                         mxICell source = (mxICell) graph.getModel().getTerminal(cell, 
true);
 
  721                         AccountDeviceInstanceKey account1 = (AccountDeviceInstanceKey) source.getValue();
 
  722                         mxICell target = (mxICell) graph.getModel().getTerminal(cell, 
false);
 
  723                         AccountDeviceInstanceKey account2 = (AccountDeviceInstanceKey) target.getValue();
 
  725                             final List<Content> relationshipSources1 = commsManager.getRelationshipSources(
 
  726                                     account1.getAccountDeviceInstance(),
 
  727                                     account2.getAccountDeviceInstance(),
 
  729                             relationshipSources.addAll(relationshipSources1);
 
  730                         } 
catch (TskCoreException tskCoreException) {
 
  731                             logger.log(Level.SEVERE, 
" Error getting relationsips....", tskCoreException);
 
  733                     } 
else if (cell.isVertex()) {
 
  734                         adis.add((AccountDeviceInstanceKey) cell.getValue());
 
  738                 rootNode = SelectionNode.createFromAccountsAndRelationships(relationshipSources, adis, currentFilter, commsManager);
 
  739                 selectedNodes = 
new Node[]{rootNode};
 
  741             vizEM.setRootContext(rootNode);
 
  743                 vizEM.setSelectedNodes(selectedNodes);
 
  744             } 
catch (PropertyVetoException ex) {
 
  745                 logger.log(Level.SEVERE, 
"Selection vetoed.", ex);
 
  755         String getDisplayName();
 
  769             return super.isVertexIgnored(vertex)
 
  770                    || lockedVertexModel.isVertexLocked((mxCell) vertex);
 
  775             if (isVertexIgnored(vertex)) {
 
  776                 return getVertexBounds(vertex);
 
  778                 return super.setVertexLocation(vertex, x, y);
 
  784             return "Fast Organic";
 
  800             return super.isVertexIgnored(vertex)
 
  801                    || lockedVertexModel.isVertexLocked((mxCell) vertex);
 
  806             if (isVertexIgnored(vertex)) {
 
  807                 return getVertexBounds(vertex);
 
  809                 return super.setVertexLocation(vertex, x, y);
 
  831             return super.isVertexIgnored(vertex)
 
  832                    || lockedVertexModel.isVertexLocked((mxCell) vertex);
 
  837             if (isVertexIgnored(vertex)) {
 
  838                 return getVertexBounds(vertex);
 
  840                 return super.setVertexLocation(vertex, x, y);
 
  861             return super.isVertexIgnored(vertex)
 
  862                    || lockedVertexModel.isVertexLocked((mxCell) vertex);
 
  867             if (isVertexIgnored(vertex)) {
 
  868                 return getVertexBounds(vertex);
 
  870                 return super.setVertexLocation(vertex, x, y);
 
  876             return "Hierarchical";
 
  890             this.cancellable = cancellable;
 
  891             this.progress = progress;
 
  897             cancellable.cancel(
true);
 
  915             super.mouseWheelMoved(event);
 
  916             if (event.getPreciseWheelRotation() < 0) {
 
  917                 graphComponent.zoomIn();
 
  918             } 
else if (event.getPreciseWheelRotation() > 0) {
 
  919                 graphComponent.zoomOut();
 
  930             super.mouseClicked(event);
 
  931             if (SwingUtilities.isRightMouseButton(event)) {
 
  932                 final mxCell cellAt = (mxCell) graphComponent.getCellAt(event.getX(), 
event.getY());
 
  933                 if (cellAt != null && cellAt.isVertex()) {
 
  934                     final JPopupMenu jPopupMenu = 
new JPopupMenu();
 
  935                     final AccountDeviceInstanceKey adiKey = (AccountDeviceInstanceKey) cellAt.getValue();
 
  937                     Set<mxCell> selectedVertices
 
  938                             = Stream.of(graph.getSelectionModel().getCells())
 
  939                                     .map(mxCell.class::cast)
 
  940                                     .filter(mxCell::isVertex)
 
  941                                     .collect(Collectors.toSet());
 
  943                     if (lockedVertexModel.isVertexLocked(cellAt)) {
 
  944                         jPopupMenu.add(
new JMenuItem(
new UnlockAction(selectedVertices)));
 
  946                         jPopupMenu.add(
new JMenuItem(
new LockAction(selectedVertices)));
 
  948                     if (pinnedAccountModel.isAccountPinned(adiKey)) {
 
  949                         jPopupMenu.add(UnpinAccountsAction.getInstance().getPopupPresenter());
 
  951                         jPopupMenu.add(PinAccountsAction.getInstance().getPopupPresenter());
 
  952                         jPopupMenu.add(ResetAndPinAccountsAction.getInstance().getPopupPresenter());
 
  954                     jPopupMenu.show(graphComponent.getGraphControl(), 
event.getX(), 
event.getY());
 
  964         "VisualizationPanel.unlockAction.singularText=Unlock Selected Account",
 
  965         "VisualizationPanel.unlockAction.pluralText=Unlock Selected Accounts",})
 
  971             super(selectedVertices.size() > 1 ? Bundle.VisualizationPanel_unlockAction_pluralText() : Bundle.VisualizationPanel_unlockAction_singularText(),
 
  973             this.selectedVertices = selectedVertices;
 
  979             lockedVertexModel.unlock(selectedVertices);
 
  987         "VisualizationPanel.lockAction.singularText=Lock Selected Account",
 
  988         "VisualizationPanel.lockAction.pluralText=Lock Selected Accounts"})
 
  994             super(selectedVertices.size() > 1 ? Bundle.VisualizationPanel_lockAction_pluralText() : Bundle.VisualizationPanel_lockAction_singularText(),
 
  996             this.selectedVertices = selectedVertices;
 
 1001             lockedVertexModel.lock(selectedVertices);
 
void zoomOutButtonActionPerformed(ActionEvent evt)
 
final Set< mxCell > selectedVertices
 
boolean isVertexIgnored(Object vertex)
 
void invoke(Object sender, mxEventObject evt)
 
JFXPanel notificationsJFXPanel
 
void mouseClicked(final MouseEvent event)
 
CommunicationsManager commsManager
 
boolean isVertexIgnored(Object vertex)
 
void applyLayout(NamedGraphLayout layout)
 
void actionPerformed(final ActionEvent event)
 
final mxRubberband rubberband
 
JToolBar.Separator jSeparator2
 
ModalDialogProgressIndicator progress
 
mxRectangle setVertexLocation(Object vertex, double x, double y)
 
JButton hierarchyLayoutButton
 
synchronized void start(String message, int totalWorkUnits)
 
JButton organicLayoutButton
 
final ProxyLookup proxyLookup
 
synchronized void setCancelling(String cancellingMessage)
 
final CommunicationsGraph graph
 
void actionPerformed(final ActionEvent event)
 
boolean isVertexIgnored(Object vertex)
 
CommunicationsFilter currentFilter
 
void fitZoomButtonActionPerformed(ActionEvent evt)
 
SleuthkitCase getSleuthkitCase()
 
void mouseWheelMoved(final MouseWheelEvent event)
 
JButton circleLayoutButton
 
JToolBar.Separator jSeparator1
 
mxRectangle setVertexLocation(Object vertex, double x, double y)
 
boolean isVertexIgnored(Object vertex)
 
mxRectangle setVertexLocation(Object vertex, double x, double y)
 
final mxGraphComponent graphComponent
 
synchronized static Logger getLogger(String name)
 
static Case getCurrentCaseThrows()
 
void actionPerformed(ActionEvent event)
 
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
 
mxRectangle setVertexLocation(Object vertex, double x, double y)
 
JButton fastOrganicLayoutButton
 
void zoomInButtonActionPerformed(ActionEvent evt)
 
final Set< mxCell > selectedVertices
 
void zoomActualButtonActionPerformed(ActionEvent evt)
 
void clearVizButtonActionPerformed(ActionEvent evt)
 
synchronized void finish()