Autopsy  4.16.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DiscoveryTopComponent.java
Go to the documentation of this file.
1 /*
2  * Autopsy
3  *
4  * Copyright 2019-2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.discovery.ui;
20 
22 import com.google.common.eventbus.Subscribe;
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Graphics;
26 import java.beans.PropertyChangeEvent;
27 import java.beans.PropertyChangeListener;
28 import java.util.List;
29 import java.util.stream.Collectors;
30 import javax.swing.JSplitPane;
31 import javax.swing.plaf.basic.BasicSplitPaneDivider;
32 import javax.swing.plaf.basic.BasicSplitPaneUI;
33 import org.openide.util.NbBundle;
34 import org.openide.util.NbBundle.Messages;
35 import org.openide.windows.Mode;
36 import org.openide.windows.RetainLocation;
37 import org.openide.windows.TopComponent;
38 import org.openide.windows.WindowManager;
43 
47 @TopComponent.Description(preferredID = "DiscoveryTc", persistenceType = TopComponent.PERSISTENCE_NEVER)
48 @TopComponent.Registration(mode = "discovery", openAtStartup = false)
49 @RetainLocation("discovery")
50 @NbBundle.Messages("DiscoveryTopComponent.name= Discovery")
51 public final class DiscoveryTopComponent extends TopComponent {
52 
53  private static final long serialVersionUID = 1L;
54  private static final String PREFERRED_ID = "DiscoveryTc"; // NON-NLS
55  private static final int ANIMATION_INCREMENT = 30;
56  private volatile static int resultsAreaSize = 250;
57  private final GroupListPanel groupListPanel;
58  private final DetailsPanel detailsPanel;
59  private final ResultsPanel resultsPanel;
60  private Type searchType;
61  private int dividerLocation = -1;
62  private SwingAnimator animator = null;
63 
70  setName(Bundle.DiscoveryTopComponent_name());
71  groupListPanel = new GroupListPanel();
72  resultsPanel = new ResultsPanel();
73  detailsPanel = new DetailsPanel();
74  mainSplitPane.setLeftComponent(groupListPanel);
75  rightSplitPane.setTopComponent(resultsPanel);
76  rightSplitPane.setBottomComponent(detailsPanel);
77  //set color of divider
78  rightSplitPane.setUI(new BasicSplitPaneUI() {
79  @Override
80  public BasicSplitPaneDivider createDefaultDivider() {
81  return new BasicSplitPaneDividerImpl(this);
82 
83  }
84  });
85  rightSplitPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
86  @Override
87  public void propertyChange(PropertyChangeEvent evt) {
88  if (evt.getPropertyName().equalsIgnoreCase(JSplitPane.DIVIDER_LOCATION_PROPERTY)) {
89  //Only change the saved location when it was a manual change by the user and not the animation or the window opening initially
90  if ((animator == null || !animator.isRunning()) && evt.getNewValue() instanceof Integer
91  && ((int) evt.getNewValue() + 5) < (rightSplitPane.getHeight() - rightSplitPane.getDividerSize())) {
92  resultsAreaSize = (int) evt.getNewValue();
93 
94  }
95  }
96  }
97  });
98  }
99 
103  private final class BasicSplitPaneDividerImpl extends BasicSplitPaneDivider {
104 
111  BasicSplitPaneDividerImpl(BasicSplitPaneUI ui) {
112  super(ui);
113  this.setLayout(new BorderLayout());
114  this.add(new ResultsSplitPaneDivider());
115  }
116 
117  private static final long serialVersionUID = 1L;
118  }
119 
126  return (DiscoveryTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID);
127  }
128 
132  public void resetTopComponent() {
133  resultsPanel.resetResultViewer();
134  groupListPanel.resetGroupList();
135  }
136 
137  @Override
138  public void componentOpened() {
139  super.componentOpened();
140  WindowManager.getDefault().setTopComponentFloating(this, true);
141  DiscoveryEventUtils.getDiscoveryEventBus().register(this);
142  DiscoveryEventUtils.getDiscoveryEventBus().register(resultsPanel);
143  DiscoveryEventUtils.getDiscoveryEventBus().register(groupListPanel);
144  DiscoveryEventUtils.getDiscoveryEventBus().register(detailsPanel);
145  }
146 
147  @Override
148  protected void componentClosed() {
149  DiscoveryDialog.getDiscoveryDialogInstance().cancelSearch();
151  DiscoveryEventUtils.getDiscoveryEventBus().unregister(this);
152  DiscoveryEventUtils.getDiscoveryEventBus().unregister(groupListPanel);
153  DiscoveryEventUtils.getDiscoveryEventBus().unregister(resultsPanel);
154  DiscoveryEventUtils.getDiscoveryEventBus().unregister(detailsPanel);
155  super.componentClosed();
156  }
157 
163  @SuppressWarnings("unchecked")
164  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
165  private void initComponents() {
166 
167  mainSplitPane = new javax.swing.JSplitPane();
169  javax.swing.JPanel searchDetailsPanel = new javax.swing.JPanel();
170  newSearchButton = new javax.swing.JButton();
171  javax.swing.JScrollPane progressMessageScrollPane = new javax.swing.JScrollPane();
172  progressMessageTextArea = new javax.swing.JTextArea();
173 
174  setMinimumSize(new java.awt.Dimension(199, 200));
175  setPreferredSize(new java.awt.Dimension(1100, 700));
176  setLayout(new java.awt.BorderLayout());
177 
178  mainSplitPane.setDividerLocation(250);
179  mainSplitPane.setPreferredSize(new java.awt.Dimension(1100, 700));
180 
181  rightSplitPane.setDividerSize(35);
182  rightSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
183  rightSplitPane.setResizeWeight(1.0);
184  rightSplitPane.setPreferredSize(new java.awt.Dimension(800, 700));
185  mainSplitPane.setRightComponent(rightSplitPane);
186 
187  add(mainSplitPane, java.awt.BorderLayout.CENTER);
188 
189  org.openide.awt.Mnemonics.setLocalizedText(newSearchButton, Bundle.DiscoveryTopComponent_cancelButton_text());
190  newSearchButton.setMaximumSize(new java.awt.Dimension(110, 26));
191  newSearchButton.setMinimumSize(new java.awt.Dimension(110, 26));
192  newSearchButton.setPreferredSize(new java.awt.Dimension(110, 26));
193  newSearchButton.addActionListener(new java.awt.event.ActionListener() {
194  public void actionPerformed(java.awt.event.ActionEvent evt) {
196  }
197  });
198 
199  progressMessageScrollPane.setBorder(null);
200 
201  progressMessageTextArea.setBackground(new java.awt.Color(240, 240, 240));
202  progressMessageTextArea.setColumns(20);
203  progressMessageTextArea.setLineWrap(true);
204  progressMessageTextArea.setRows(2);
205  progressMessageTextArea.setWrapStyleWord(true);
206  progressMessageTextArea.setBorder(null);
207  progressMessageScrollPane.setViewportView(progressMessageTextArea);
208 
209  javax.swing.GroupLayout searchDetailsPanelLayout = new javax.swing.GroupLayout(searchDetailsPanel);
210  searchDetailsPanel.setLayout(searchDetailsPanelLayout);
211  searchDetailsPanelLayout.setHorizontalGroup(
212  searchDetailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
213  .addGroup(searchDetailsPanelLayout.createSequentialGroup()
214  .addContainerGap()
215  .addComponent(newSearchButton, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE)
216  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
217  .addComponent(progressMessageScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 954, Short.MAX_VALUE)
218  .addContainerGap())
219  );
220  searchDetailsPanelLayout.setVerticalGroup(
221  searchDetailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
222  .addGroup(searchDetailsPanelLayout.createSequentialGroup()
223  .addGroup(searchDetailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
224  .addGroup(searchDetailsPanelLayout.createSequentialGroup()
225  .addGap(8, 8, 8)
226  .addComponent(progressMessageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE))
227  .addGroup(searchDetailsPanelLayout.createSequentialGroup()
228  .addGap(17, 17, 17)
229  .addComponent(newSearchButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
230  .addContainerGap())
231  );
232 
233  add(searchDetailsPanel, java.awt.BorderLayout.PAGE_START);
234  }// </editor-fold>//GEN-END:initComponents
235 
236  private void newSearchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newSearchButtonActionPerformed
237  close();
238  final DiscoveryDialog discDialog = DiscoveryDialog.getDiscoveryDialogInstance();
239  discDialog.cancelSearch();
240  discDialog.setVisible(true);
241  discDialog.validateDialog();
242  }//GEN-LAST:event_newSearchButtonActionPerformed
243 
244  @Override
245  public List<Mode> availableModes(List<Mode> modes) {
246  /*
247  * This looks like the right thing to do, but online discussions seems
248  * to indicate this method is effectively deprecated. A break point
249  * placed here was never hit.
250  */
251  return modes.stream().filter(mode -> mode.getName().equals("discovery"))
252  .collect(Collectors.toList());
253  }
254 
262  @Subscribe
263  void handleDetailsVisibleEvent(DiscoveryEventUtils.DetailsVisibleEvent detailsVisibleEvent) {
264  if (resultsPanel.getActiveType() != DOMAIN) {
265  if (animator != null && animator.isRunning()) {
266  animator.stop();
267  animator = null;
268  }
269  dividerLocation = rightSplitPane.getDividerLocation();
270  if (detailsVisibleEvent.isShowDetailsArea()) {
271  animator = new SwingAnimator(new ShowDetailsAreaCallback());
272  } else {
273  animator = new SwingAnimator(new HideDetailsAreaCallback());
274  }
275  animator.start();
276  }
277  }
278 
285  @Messages({"DiscoveryTopComponent.cancelButton.text=Cancel Search",
286  "# {0} - searchType",
287  "DiscoveryTopComponent.searchInProgress.text=Performing search for results of type {0}. Please wait.",
288  "DiscoveryTopComponent.searchError.text=Error no type specified for search."})
289  @Subscribe
290  void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) {
291  newSearchButton.setText(Bundle.DiscoveryTopComponent_cancelButton_text());
292  progressMessageTextArea.setForeground(Color.red);
293  searchType = searchStartedEvent.getType();
294  progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchInProgress_text(searchType.name()));
295  rightSplitPane.getComponent(1).setVisible(searchStartedEvent.getType() != DOMAIN);
296  rightSplitPane.getComponent(2).setVisible(searchStartedEvent.getType() != DOMAIN);
297  }
298 
305  @Subscribe
306  @Messages({"DiscoveryTopComponent.newSearch.text=New Search",
307  "# {0} - search",
308  "DiscoveryTopComponent.searchComplete.text=Results with {0}",
309  "DiscoveryTopComponent.domainSearch.text=Type: Domain",
310  "DiscoveryTopComponent.additionalFilters.text=; "})
311  void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) {
312  newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text());
313  progressMessageTextArea.setForeground(Color.black);
314  String descriptionText = "";
315  if (searchType == DOMAIN) {
316  //domain does not have a file type filter to add the type information so it is manually added
317  descriptionText = Bundle.DiscoveryTopComponent_domainSearch_text();
318  if (!searchCompleteEvent.getFilters().isEmpty()) {
319  descriptionText += Bundle.DiscoveryTopComponent_additionalFilters_text();
320  }
321  }
322  descriptionText += searchCompleteEvent.getFilters().stream().map(AbstractFilter::getDesc).collect(Collectors.joining("; "));
323  progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchComplete_text(descriptionText));
324  progressMessageTextArea.setCaretPosition(0);
325  }
326 
333  @Messages({"DiscoveryTopComponent.searchCancelled.text=Search has been cancelled."})
334  @Subscribe
335  void handleSearchCancelledEvent(DiscoveryEventUtils.SearchCancelledEvent searchCancelledEvent) {
336  newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text());
337  progressMessageTextArea.setForeground(Color.red);
338  progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchCancelled_text());
339 
340  }
341 
345  private final class ShowDetailsAreaCallback implements SwingAnimatorCallback {
346 
347  @Override
348  public void callback(Object caller) {
349  dividerLocation -= ANIMATION_INCREMENT;
350  repaint();
351  }
352 
353  @Override
354  public boolean hasTerminated() {
355  if (dividerLocation != JSplitPane.UNDEFINED_CONDITION && dividerLocation < resultsAreaSize) {
356  dividerLocation = resultsAreaSize;
357  animator = null;
358  return true;
359  }
360  return false;
361  }
362 
363  }
364 
368  private final class HideDetailsAreaCallback implements SwingAnimatorCallback {
369 
370  @Override
371  public void callback(Object caller) {
372  dividerLocation += ANIMATION_INCREMENT;
373  repaint();
374  }
375 
376  @Override
377  public boolean hasTerminated() {
378  if (dividerLocation > rightSplitPane.getHeight() || dividerLocation == JSplitPane.UNDEFINED_CONDITION) {
379  dividerLocation = rightSplitPane.getHeight();
380  animator = null;
381  return true;
382  }
383  return false;
384  }
385 
386  }
387  // Variables declaration - do not modify//GEN-BEGIN:variables
388  private javax.swing.JSplitPane mainSplitPane;
389  private javax.swing.JButton newSearchButton;
390  private javax.swing.JTextArea progressMessageTextArea;
391  private javax.swing.JSplitPane rightSplitPane;
392  // End of variables declaration//GEN-END:variables
393 
397  private final class AnimatedSplitPane extends JSplitPane {
398 
399  private static final long serialVersionUID = 1L;
400 
401  @Override
402  public void paintComponent(Graphics g) {
403  if (animator != null && animator.isRunning() && (dividerLocation == JSplitPane.UNDEFINED_CONDITION
404  || (dividerLocation <= getHeight() && dividerLocation >= resultsAreaSize))) {
405  setDividerLocation(dividerLocation);
406  }
407  super.paintComponent(g);
408  }
409 
410  }
411 
412 }
void newSearchButtonActionPerformed(java.awt.event.ActionEvent evt)

Copyright © 2012-2020 Basis Technology. Generated on: Tue Sep 22 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.