diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index f00a02cf9d..a71d34bb61 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -50,3 +50,6 @@ VisualizationPanel.backButton.toolTipText=Click to go back VisualizationPanel.forwardButton.toolTipText=Click to go forward VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart +FiltersPanel.limitHeaderLabel.text=Communications Limit: +FiltersPanel.mostRecentLabel.text=Most Recent: +FiltersPanel.limitErrorMsgLabel.text=Invalid integer value. diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index c9f38865a8..6fb582ed97 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -94,6 +94,9 @@ VisualizationPanel.backButton.toolTipText=Click to go back VisualizationPanel.forwardButton.toolTipText=Click to go forward VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart +FiltersPanel.limitHeaderLabel.text=Communications Limit: +FiltersPanel.mostRecentLabel.text=Most Recent: +FiltersPanel.limitErrorMsgLabel.text=Invalid integer value. VisualizationPanel_action_dialogs_title=Communications VisualizationPanel_action_name_text=Snapshot Report VisualizationPanel_module_name=Communications diff --git a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.form b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.form index 38a3e7adbf..e7d5d7c820 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.form +++ b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.form @@ -16,8 +16,8 @@ - - + + @@ -25,11 +25,12 @@ - + + @@ -44,12 +45,14 @@ - - - - - - + + + + + + + + @@ -78,7 +81,7 @@ - + @@ -91,16 +94,14 @@ + + - - - - - - - - - + + + + + @@ -115,7 +116,7 @@ - + @@ -156,11 +157,11 @@ - + - + @@ -184,7 +185,7 @@ - + @@ -195,16 +196,14 @@ + + - - - - - - - - - + + + + + @@ -216,7 +215,7 @@ - + @@ -258,7 +257,7 @@ - + @@ -268,7 +267,7 @@ - + @@ -297,7 +296,7 @@ - + @@ -406,5 +405,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java index 56c8be50a7..fab152fcd4 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java @@ -50,6 +50,7 @@ import org.sleuthkit.datamodel.CommunicationsFilter; import org.sleuthkit.datamodel.CommunicationsFilter.AccountTypeFilter; import org.sleuthkit.datamodel.CommunicationsFilter.DateRangeFilter; import org.sleuthkit.datamodel.CommunicationsFilter.DeviceFilter; +import org.sleuthkit.datamodel.CommunicationsFilter.MostRecentFilter; import org.sleuthkit.datamodel.DataSource; import static org.sleuthkit.datamodel.Relationship.Type.CALL_LOG; import static org.sleuthkit.datamodel.Relationship.Type.MESSAGE; @@ -161,14 +162,30 @@ final public class FiltersPanel extends JPanel { private void validateFilters() { boolean someDevice = devicesMap.values().stream().anyMatch(JCheckBox::isSelected); boolean someAccountType = accountTypeMap.values().stream().anyMatch(JCheckBox::isSelected); + boolean validLimit = validateLimitValue(); deviceRequiredLabel.setVisible(someDevice == false); accountTypeRequiredLabel.setVisible(someAccountType == false); + limitErrorMsgLabel.setVisible(!validLimit); - applyFiltersButton.setEnabled(someDevice && someAccountType); - refreshButton.setEnabled(someDevice && someAccountType && needsRefresh); + applyFiltersButton.setEnabled(someDevice && someAccountType && validLimit); + refreshButton.setEnabled(someDevice && someAccountType && needsRefresh && validLimit); needsRefreshLabel.setVisible(needsRefresh); } + + private boolean validateLimitValue() { + String selectedValue = (String)limitComboBox.getSelectedItem(); + if(selectedValue.trim().toLowerCase().equals("all")) { + return true; + } else { + try{ + int value = Integer.parseInt(selectedValue); + return value > 0; + } catch( NumberFormatException ex) { + return false; + } + } + } /** * Update the filter widgets, and apply them. @@ -197,7 +214,7 @@ final public class FiltersPanel extends JPanel { Case.addEventTypeSubscriber(EnumSet.of(CURRENT_CASE), evt -> { //clear the device filter widget when the case changes. devicesMap.clear(); - devicesPane.removeAll(); + devicesListPane.removeAll(); }); } @@ -229,7 +246,7 @@ final public class FiltersPanel extends JPanel { true ); jCheckBox.addItemListener(validationListener); - accountTypePane.add(jCheckBox); + accountTypeListPane.add(jCheckBox); if (t.equals(Account.Type.DEVICE)) { //Deveice type filter is enabled based on whether we are in table or graph view. jCheckBox.setEnabled(deviceAccountTypeEnabled); @@ -253,7 +270,7 @@ final public class FiltersPanel extends JPanel { devicesMap.computeIfAbsent(dataSource.getDeviceId(), ds -> { final JCheckBox jCheckBox = new JCheckBox(dsName, initialState); jCheckBox.addItemListener(validationListener); - devicesPane.add(jCheckBox); + devicesListPane.add(jCheckBox); return jCheckBox; }); } @@ -277,6 +294,8 @@ final public class FiltersPanel extends JPanel { setDeviceFilter((DeviceFilter)subFilter); } else if( subFilter instanceof AccountTypeFilter) { setAccountTypeFilter((AccountTypeFilter) subFilter); + } else if (subFilter instanceof MostRecentFilter ) { + setMostRecentFilter((MostRecentFilter)subFilter); } }); } @@ -329,6 +348,15 @@ final public class FiltersPanel extends JPanel { endDatePicker.setEnabled(state.isEnabled()); } + private void setMostRecentFilter(MostRecentFilter filter) { + int limit = filter.getLimit(); + if(limit > 0) { + limitComboBox.setSelectedItem(filter.getLimit()); + } else { + limitComboBox.setSelectedItem("All"); + } + } + @Subscribe void filtersBack(CVTEvents.StateChangeEvent event) { if(event.getCommunicationsState().getCommunicationsFilter() != null){ @@ -373,45 +401,44 @@ final public class FiltersPanel extends JPanel { } }); - accountTypePane.setLayout(new javax.swing.BoxLayout(accountTypePane, javax.swing.BoxLayout.Y_AXIS)); - jScrollPane3.setViewportView(accountTypePane); + accountTypeListPane.setLayout(new javax.swing.BoxLayout(accountTypeListPane, javax.swing.BoxLayout.Y_AXIS)); + accountTypesScrollPane.setViewportView(accountTypeListPane); accountTypeRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N accountTypeRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypeRequiredLabel.text")); // NOI18N accountTypeRequiredLabel.setForeground(new java.awt.Color(255, 0, 0)); accountTypeRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT); - javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); - jPanel2.setLayout(jPanel2Layout); - jPanel2Layout.setHorizontalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(jPanel2Layout.createSequentialGroup() + javax.swing.GroupLayout accountTypesPaneLayout = new javax.swing.GroupLayout(accountTypesPane); + accountTypesPane.setLayout(accountTypesPaneLayout); + accountTypesPaneLayout.setHorizontalGroup( + accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, accountTypesPaneLayout.createSequentialGroup() + .addGroup(accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(accountTypesPaneLayout.createSequentialGroup() .addComponent(accountTypesLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(accountTypeRequiredLabel)) - .addGroup(jPanel2Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jScrollPane3) - .addGroup(jPanel2Layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(unCheckAllAccountTypesButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(checkAllAccountTypesButton))))) + .addGroup(accountTypesPaneLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(unCheckAllAccountTypesButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(checkAllAccountTypesButton)) + .addGroup(accountTypesPaneLayout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(accountTypesScrollPane))) .addGap(0, 0, 0)) ); - jPanel2Layout.setVerticalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + accountTypesPaneLayout.setVerticalGroup( + accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(accountTypesPaneLayout.createSequentialGroup() + .addGroup(accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(accountTypesLabel) .addComponent(accountTypeRequiredLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 243, Short.MAX_VALUE) + .addComponent(accountTypesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 243, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addGroup(accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(checkAllAccountTypesButton) .addComponent(unCheckAllAccountTypesButton))) ); @@ -433,46 +460,45 @@ final public class FiltersPanel extends JPanel { } }); - jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - jScrollPane2.setMinimumSize(new java.awt.Dimension(27, 75)); + devicesScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + devicesScrollPane.setMinimumSize(new java.awt.Dimension(27, 75)); - devicesPane.setMinimumSize(new java.awt.Dimension(4, 100)); - devicesPane.setLayout(new javax.swing.BoxLayout(devicesPane, javax.swing.BoxLayout.Y_AXIS)); - jScrollPane2.setViewportView(devicesPane); + devicesListPane.setMinimumSize(new java.awt.Dimension(4, 100)); + devicesListPane.setLayout(new javax.swing.BoxLayout(devicesListPane, javax.swing.BoxLayout.Y_AXIS)); + devicesScrollPane.setViewportView(devicesListPane); deviceRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N deviceRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.deviceRequiredLabel.text")); // NOI18N deviceRequiredLabel.setForeground(new java.awt.Color(255, 0, 0)); deviceRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT); - javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); - jPanel3.setLayout(jPanel3Layout); - jPanel3Layout.setHorizontalGroup( - jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel3Layout.createSequentialGroup() + javax.swing.GroupLayout devicesPaneLayout = new javax.swing.GroupLayout(devicesPane); + devicesPane.setLayout(devicesPaneLayout); + devicesPaneLayout.setHorizontalGroup( + devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(devicesPaneLayout.createSequentialGroup() .addComponent(devicesLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(deviceRequiredLabel)) - .addGroup(jPanel3Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel3Layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(unCheckAllDevicesButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(checkAllDevicesButton)) - .addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addGroup(devicesPaneLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(unCheckAllDevicesButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(checkAllDevicesButton)) + .addGroup(devicesPaneLayout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(devicesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); - jPanel3Layout.setVerticalGroup( - jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel3Layout.createSequentialGroup() - .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + devicesPaneLayout.setVerticalGroup( + devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(devicesPaneLayout.createSequentialGroup() + .addGroup(devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(devicesLabel) .addComponent(deviceRequiredLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 94, Short.MAX_VALUE) + .addComponent(devicesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 94, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addGroup(devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(checkAllDevicesButton) .addComponent(unCheckAllDevicesButton)) .addGap(5, 5, 5)) @@ -499,38 +525,39 @@ final public class FiltersPanel extends JPanel { endDatePicker.setEnabled(false); - javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); - jPanel4.setLayout(jPanel4Layout); - jPanel4Layout.setHorizontalGroup( - jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() - .addComponent(dateRangeLabel) + javax.swing.GroupLayout dateRangePaneLayout = new javax.swing.GroupLayout(dateRangePane); + dateRangePane.setLayout(dateRangePaneLayout); + dateRangePaneLayout.setHorizontalGroup( + dateRangePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(dateRangePaneLayout.createSequentialGroup() + .addGroup(dateRangePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(dateRangeLabel) + .addGroup(dateRangePaneLayout.createSequentialGroup() + .addContainerGap() + .addGroup(dateRangePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, dateRangePaneLayout.createSequentialGroup() + .addComponent(endCheckBox) + .addGap(12, 12, 12) + .addComponent(endDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(dateRangePaneLayout.createSequentialGroup() + .addComponent(startCheckBox) + .addGap(12, 12, 12) + .addComponent(startDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))) .addGap(0, 0, Short.MAX_VALUE)) - .addGroup(jPanel4Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup() - .addComponent(endCheckBox) - .addGap(12, 12, 12) - .addComponent(endDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(jPanel4Layout.createSequentialGroup() - .addComponent(startCheckBox) - .addGap(12, 12, 12) - .addComponent(startDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) ); - jPanel4Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {endCheckBox, startCheckBox}); + dateRangePaneLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {endCheckBox, startCheckBox}); - jPanel4Layout.setVerticalGroup( - jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() + dateRangePaneLayout.setVerticalGroup( + dateRangePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(dateRangePaneLayout.createSequentialGroup() .addComponent(dateRangeLabel) .addGap(6, 6, 6) - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addGroup(dateRangePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(startDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(startCheckBox)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addGroup(dateRangePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(endDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(endCheckBox))) ); @@ -541,22 +568,70 @@ final public class FiltersPanel extends JPanel { needsRefreshLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.needsRefreshLabel.text")); // NOI18N needsRefreshLabel.setForeground(new java.awt.Color(255, 0, 0)); + limitHeaderLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitHeaderLabel.text")); // NOI18N + + mostRecentLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.mostRecentLabel.text")); // NOI18N + + limitComboBox.setEditable(true); + limitComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "All", "10000", "5000", "1000", "500", "100" })); + limitComboBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + limitComboBoxActionPerformed(evt); + } + }); + + limitErrorMsgLabel.setForeground(new java.awt.Color(255, 0, 0)); + limitErrorMsgLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N + limitErrorMsgLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitErrorMsgLabel.text")); // NOI18N + limitErrorMsgLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); + + javax.swing.GroupLayout limitPaneLayout = new javax.swing.GroupLayout(limitPane); + limitPane.setLayout(limitPaneLayout); + limitPaneLayout.setHorizontalGroup( + limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(limitPaneLayout.createSequentialGroup() + .addComponent(limitHeaderLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(limitErrorMsgLabel) + .addContainerGap()) + .addGroup(limitPaneLayout.createSequentialGroup() + .addContainerGap() + .addComponent(mostRecentLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(limitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + limitPaneLayout.setVerticalGroup( + limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(limitPaneLayout.createSequentialGroup() + .addContainerGap() + .addGroup(limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(limitHeaderLabel) + .addComponent(limitErrorMsgLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(mostRecentLabel) + .addComponent(limitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 32, Short.MAX_VALUE)) + ); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(devicesPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(accountTypesPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(filtersTitleLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(applyFiltersButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(refreshButton)) - .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(dateRangePane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(needsRefreshLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(limitPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -569,12 +644,14 @@ final public class FiltersPanel extends JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(needsRefreshLabel) .addGap(4, 4, 4) - .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(18, 18, 18) - .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(18, 18, 18) - .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(19, Short.MAX_VALUE)) + .addComponent(devicesPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(accountTypesPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(dateRangePane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(limitPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(62, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -599,6 +676,7 @@ final public class FiltersPanel extends JPanel { commsFilter.addAndFilter(getDateRangeFilter()); commsFilter.addAndFilter(new CommunicationsFilter.RelationshipTypeFilter( ImmutableSet.of(CALL_LOG, MESSAGE))); + commsFilter.addAndFilter(getMostRecentFilter()); return commsFilter; } @@ -642,6 +720,20 @@ final public class FiltersPanel extends JPanel { endCheckBox.isSelected() ? endDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0); } + private MostRecentFilter getMostRecentFilter() { + String value = (String)limitComboBox.getSelectedItem(); + if(value.trim().toLowerCase().equals("all")){ + return new MostRecentFilter(-1); + } else{ + try { + int count = Integer.parseInt(value); + return new MostRecentFilter(count); + } catch(NumberFormatException ex) { + return null; + } + } + } + private DateControlState getStartControlState() { return new DateControlState (startDatePicker.getDate(), startCheckBox.isSelected()); } @@ -715,12 +807,18 @@ final public class FiltersPanel extends JPanel { private void startCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_startCheckBoxStateChanged startDatePicker.setEnabled(startCheckBox.isSelected()); + validateFilters(); }//GEN-LAST:event_startCheckBoxStateChanged private void endCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_endCheckBoxStateChanged endDatePicker.setEnabled(endCheckBox.isSelected()); + validateFilters(); }//GEN-LAST:event_endCheckBoxStateChanged + private void limitComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_limitComboBoxActionPerformed + validateFilters(); + }//GEN-LAST:event_limitComboBoxActionPerformed + /** * A class to wrap the state of the date controls that consist of a date picker * and a checkbox. @@ -763,24 +861,29 @@ final public class FiltersPanel extends JPanel { } // Variables declaration - do not modify//GEN-BEGIN:variables - private final javax.swing.JPanel accountTypePane = new javax.swing.JPanel(); + private final javax.swing.JPanel accountTypeListPane = new javax.swing.JPanel(); private final javax.swing.JLabel accountTypeRequiredLabel = new javax.swing.JLabel(); private final javax.swing.JLabel accountTypesLabel = new javax.swing.JLabel(); + private final javax.swing.JPanel accountTypesPane = new javax.swing.JPanel(); + private final javax.swing.JScrollPane accountTypesScrollPane = new javax.swing.JScrollPane(); private final javax.swing.JButton applyFiltersButton = new javax.swing.JButton(); private final javax.swing.JButton checkAllAccountTypesButton = new javax.swing.JButton(); private final javax.swing.JButton checkAllDevicesButton = new javax.swing.JButton(); private final javax.swing.JLabel dateRangeLabel = new javax.swing.JLabel(); + private final javax.swing.JPanel dateRangePane = new javax.swing.JPanel(); private final javax.swing.JLabel deviceRequiredLabel = new javax.swing.JLabel(); private final javax.swing.JLabel devicesLabel = new javax.swing.JLabel(); + private final javax.swing.JPanel devicesListPane = new javax.swing.JPanel(); private final javax.swing.JPanel devicesPane = new javax.swing.JPanel(); + private final javax.swing.JScrollPane devicesScrollPane = new javax.swing.JScrollPane(); private final javax.swing.JCheckBox endCheckBox = new javax.swing.JCheckBox(); private final com.github.lgooddatepicker.components.DatePicker endDatePicker = new com.github.lgooddatepicker.components.DatePicker(); private final javax.swing.JLabel filtersTitleLabel = new javax.swing.JLabel(); - private final javax.swing.JPanel jPanel2 = new javax.swing.JPanel(); - private final javax.swing.JPanel jPanel3 = new javax.swing.JPanel(); - private final javax.swing.JPanel jPanel4 = new javax.swing.JPanel(); - private final javax.swing.JScrollPane jScrollPane2 = new javax.swing.JScrollPane(); - private final javax.swing.JScrollPane jScrollPane3 = new javax.swing.JScrollPane(); + private final javax.swing.JComboBox limitComboBox = new javax.swing.JComboBox<>(); + private final javax.swing.JLabel limitErrorMsgLabel = new javax.swing.JLabel(); + private final javax.swing.JLabel limitHeaderLabel = new javax.swing.JLabel(); + private final javax.swing.JPanel limitPane = new javax.swing.JPanel(); + private final javax.swing.JLabel mostRecentLabel = new javax.swing.JLabel(); private final javax.swing.JLabel needsRefreshLabel = new javax.swing.JLabel(); private final javax.swing.JButton refreshButton = new javax.swing.JButton(); private final javax.swing.JCheckBox startCheckBox = new javax.swing.JCheckBox();