19 package org.sleuthkit.autopsy.discovery.ui;
 
   22 import com.google.common.eventbus.Subscribe;
 
   23 import java.awt.Cursor;
 
   24 import java.awt.Graphics2D;
 
   25 import java.awt.font.FontRenderContext;
 
   26 import java.util.List;
 
   28 import javax.swing.DefaultListCellRenderer;
 
   29 import javax.swing.DefaultListModel;
 
   30 import javax.swing.JList;
 
   31 import javax.swing.JOptionPane;
 
   32 import javax.swing.SwingUtilities;
 
   33 import org.openide.util.NbBundle.Messages;
 
   46 final class GroupListPanel 
extends javax.swing.JPanel {
 
   48     private static final long serialVersionUID = 1L;
 
   49     private Type type = null;
 
   50     private Map<GroupKey, Integer> groupMap = null;
 
   51     private List<AbstractFilter> searchfilters;
 
   52     private DiscoveryAttributes.AttributeType groupingAttribute;
 
   53     private Group.GroupSortingAlgorithm groupSort;
 
   54     private ResultsSorter.SortingMethod resultSortMethod;
 
   55     private GroupKey selectedGroupKey;
 
   60     @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
 
   71     void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) {
 
   72         type = searchStartedEvent.getType();
 
   73         groupKeyList.setListData(
new GroupKey[0]);
 
   76     @Messages({
"GroupsListPanel.noFileResults.message.text=No files were found for the selected filters.\n\n" 
   78         + 
"  -The File Type Identification module must be run on each data source you want to find results in.\n" 
   79         + 
"  -The Hash Lookup module must be run on each data source if you want to filter by past occurrence.\n" 
   80         + 
"  -The Picture Analyzer module must be run on each data source if you are filtering by User Created content.",
 
   81         "GroupsListPanel.noDomainResults.message.text=No domains were found for the selected filters.\n\n" 
   83         + 
"  -The Recent Activity module must be run on each data source you want to find results in.\n" 
   84         + 
"  -The Central Repository module must be run on each data source if you want to filter or sort by past occurrences.\n" 
   85         + 
"  -The iOS Analyzer (iLEAPP) module must be run on each data source which contains data from an iOS device.\n",
 
   86         "GroupsListPanel.noResults.title.text=No results found"})
 
   94     void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) {
 
   95         groupMap = searchCompleteEvent.getGroupMap();
 
   96         searchfilters = searchCompleteEvent.getFilters();
 
   97         groupingAttribute = searchCompleteEvent.getGroupingAttr();
 
   98         groupSort = searchCompleteEvent.getGroupSort();
 
   99         resultSortMethod = searchCompleteEvent.getResultSort();
 
  100         groupKeyList.setListData(groupMap.keySet().toArray(
new GroupKey[groupMap.keySet().size()]));
 
  101         SwingUtilities.invokeLater(() -> {
 
  102             if (groupKeyList.getModel().getSize() > 0) {
 
  103                 groupKeyList.setSelectedIndex(0);
 
  104             } 
else if (type == DOMAIN) {
 
  105                 JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(),
 
  106                         Bundle.GroupsListPanel_noDomainResults_message_text(),
 
  107                         Bundle.GroupsListPanel_noResults_title_text(),
 
  108                         JOptionPane.PLAIN_MESSAGE);
 
  110                 JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(),
 
  111                         Bundle.GroupsListPanel_noFileResults_message_text(),
 
  112                         Bundle.GroupsListPanel_noResults_title_text(),
 
  113                         JOptionPane.PLAIN_MESSAGE);
 
  115             setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
 
  125     void handleSearchCancelledEvent(DiscoveryEventUtils.SearchCancelledEvent searchCancelledEvent) {
 
  126         SwingUtilities.invokeLater(() -> {
 
  127             setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
 
  136     @SuppressWarnings(
"unchecked")
 
  138     private 
void initComponents() {
 
  140         javax.swing.JScrollPane groupListScrollPane = 
new javax.swing.JScrollPane();
 
  141         groupKeyList = 
new javax.swing.JList<>();
 
  143         groupKeyList.setBorder(javax.swing.BorderFactory.createTitledBorder(
org.openide.util.NbBundle.getMessage(GroupListPanel.class, 
"GroupListPanel.groupKeyList.border.title"))); 
 
  144         groupKeyList.setModel(
new DefaultListModel<GroupKey>());
 
  145         groupKeyList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
 
  146         groupKeyList.setCellRenderer(
new GroupListRenderer());
 
  147         groupKeyList.addListSelectionListener(
new javax.swing.event.ListSelectionListener() {
 
  148             public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
 
  152         groupListScrollPane.setViewportView(groupKeyList);
 
  154         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  155         this.setLayout(layout);
 
  156         layout.setHorizontalGroup(
 
  157             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  158             .addGap(0, 144, Short.MAX_VALUE)
 
  159             .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  160                 .addComponent(groupListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 144, Short.MAX_VALUE))
 
  162         layout.setVerticalGroup(
 
  163             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  164             .addGap(0, 300, Short.MAX_VALUE)
 
  165             .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  166                 .addComponent(groupListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE))
 
  173     @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
 
  174     void resetGroupList() {
 
  175         setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  176         groupKeyList.setListData(
new GroupKey[0]);
 
  184     private void groupSelected(javax.swing.event.ListSelectionEvent evt) {
 
  185         if (!evt.getValueIsAdjusting()) {
 
  186             if (groupKeyList.getSelectedValue() != null) {
 
  187                 GroupKey selectedGroup = groupKeyList.getSelectedValue();
 
  188                 for (GroupKey groupKey : groupMap.keySet()) {
 
  189                     if (selectedGroup.equals(groupKey)) {
 
  190                         selectedGroupKey = groupKey;
 
  191                         DiscoveryEventUtils.getDiscoveryEventBus().post(
new DiscoveryEventUtils.GroupSelectedEvent(
 
  192                                 searchfilters, groupingAttribute, groupSort, resultSortMethod, selectedGroupKey, groupMap.get(selectedGroupKey), type));
 
  197                 DiscoveryEventUtils.getDiscoveryEventBus().post(
new DiscoveryEventUtils.NoResultsEvent());
 
  204     private javax.swing.JList<GroupKey> groupKeyList;
 
  213         private static final long serialVersionUID = 1L;
 
  222                 boolean cellHasFocus) {
 
  223             Object newValue = value;
 
  225                 String valueString = newValue.toString();
 
  226                 setToolTipText(valueString);
 
  227                 valueString += 
" (" + groupMap.get(newValue) + 
")";
 
  232                     FontRenderContext context = ((Graphics2D) list.getGraphics()).getFontRenderContext();
 
  235                     double stringWidth = getFont().getStringBounds(valueString, context).getWidth();
 
  237                     int listWidth = list.getWidth() - 10;
 
  239                     if (stringWidth > listWidth) {
 
  240                         double avgCharWidth = Math.floor(stringWidth / valueString.length());
 
  243                         int charToRemove = (int) Math.ceil((stringWidth - listWidth) / avgCharWidth) + 5;
 
  244                         int charactersToShow = (int) Math.ceil((valueString.length() - charToRemove) / 2);
 
  245                         valueString = valueString.substring(0, charactersToShow) + 
" ... " + valueString.substring(valueString.length() - charactersToShow);
 
  248                 newValue = valueString;
 
  250             super.getListCellRendererComponent(list, newValue, index, isSelected, cellHasFocus);
 
java.awt.Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus)