added timeline panel

This commit is contained in:
Greg DiCristofaro 2020-11-10 07:59:46 -05:00
parent ea7c03aa1d
commit 011bf82cad
7 changed files with 134 additions and 98 deletions

View File

@ -18,7 +18,6 @@
*/ */
package org.sleuthkit.autopsy.datasourcesummary.datamodel; package org.sleuthkit.autopsy.datasourcesummary.datamodel;
import com.google.common.collect.Sets;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
@ -195,10 +194,10 @@ public class TimelineSummary implements DefaultUpdateGovernor {
private final Date maxDate; private final Date maxDate;
private final List<DailyActivityAmount> histogramActivity; private final List<DailyActivityAmount> histogramActivity;
TimelineSummaryData(Date minDate, Date maxDate, List<DailyActivityAmount> histogramActivity) { TimelineSummaryData(Date minDate, Date maxDate, List<DailyActivityAmount> recentDaysActivity) {
this.minDate = minDate; this.minDate = minDate;
this.maxDate = maxDate; this.maxDate = maxDate;
this.histogramActivity = (histogramActivity == null) ? Collections.emptyList() : Collections.unmodifiableList(histogramActivity); this.histogramActivity = (recentDaysActivity == null) ? Collections.emptyList() : Collections.unmodifiableList(recentDaysActivity);
} }
public Date getMinDate() { public Date getMinDate() {
@ -209,7 +208,7 @@ public class TimelineSummary implements DefaultUpdateGovernor {
return maxDate; return maxDate;
} }
public List<DailyActivityAmount> getHistogramActivity() { public List<DailyActivityAmount> getMostRecentDaysActivity() {
return histogramActivity; return histogramActivity;
} }
} }

View File

@ -42,5 +42,4 @@ RecentFilesPanel.attachmentLabel.text=Recent Attachments
PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable
PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs
DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected. DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected.
TimelinePanel.sameIdLabel.text=Past Cases with the Same Device IDs TimelinePanel.activityRangeLabel.text=Activity Range
TimelinePanel.activityRangeLabel.text=Activity Range:

View File

@ -38,7 +38,8 @@ import org.sleuthkit.datamodel.DataSource;
"DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History", "DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History",
"DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files", "DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files",
"DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases", "DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases",
"DataSourceSummaryTabbedPane_analysisTab_title=Analysis" "DataSourceSummaryTabbedPane_analysisTab_title=Analysis",
"DataSourceSummaryTabbedPane_timelineTab_title=Timeline"
}) })
public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { public class DataSourceSummaryTabbedPane extends javax.swing.JPanel {
@ -123,6 +124,7 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel {
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_analysisTab_title(), new AnalysisPanel()), new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_analysisTab_title(), new AnalysisPanel()),
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_recentFileTab_title(), new RecentFilesPanel()), new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_recentFileTab_title(), new RecentFilesPanel()),
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_pastCasesTab_title(), new PastCasesPanel()), new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_pastCasesTab_title(), new PastCasesPanel()),
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_timelineTab_title(), new TimelinePanel()),
// do nothing on closing // do nothing on closing
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_ingestHistoryTab_title(), ingestHistoryPanel, ingestHistoryPanel::setDataSource, () -> { new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_ingestHistoryTab_title(), ingestHistoryPanel, ingestHistoryPanel::setDataSource, () -> {
}), }),

View File

@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.function.Function;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleFactory; import org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleFactory;
@ -28,7 +27,6 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult; import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer.DefaultCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer.DefaultCellModel;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel;
@ -103,32 +101,11 @@ public class PastCasesPanel extends BaseDataSourceSummaryPanel {
* @param result The result. * @param result The result.
*/ */
private void handleResult(DataFetchResult<PastCasesResult> result) { private void handleResult(DataFetchResult<PastCasesResult> result) {
showResultWithModuleCheck(notableFileTable, getSubResult(result, (res) -> res.getTaggedNotable()), CR_FACTORY, CR_NAME); showResultWithModuleCheck(notableFileTable, DataFetchResult.getSubResult(result, (res) -> res.getTaggedNotable()), CR_FACTORY, CR_NAME);
showResultWithModuleCheck(sameIdTable, getSubResult(result, (res) -> res.getSameIdsResults()), CR_FACTORY, CR_NAME); showResultWithModuleCheck(sameIdTable, DataFetchResult.getSubResult(result, (res) -> res.getSameIdsResults()), CR_FACTORY, CR_NAME);
} }
/**
* Given an input data fetch result, creates an error result if the original
* is an error. Otherwise, uses the getSubResult function on the underlying
* data to create a new DataFetchResult.
*
* @param inputResult The input result.
* @param getSubComponent The means of getting the data given the original
* data.
*
* @return The new result with the error of the original or the processed
* data.
*/
private <O> DataFetchResult<O> getSubResult(DataFetchResult<PastCasesResult> inputResult, Function<PastCasesResult, O> getSubResult) {
if (inputResult == null) {
return null;
} else if (inputResult.getResultType() == ResultType.SUCCESS) {
O innerData = (inputResult.getData() == null) ? null : getSubResult.apply(inputResult.getData());
return DataFetchResult.getSuccessResult(innerData);
} else {
return DataFetchResult.getErrorResult(inputResult.getException());
}
}
@Override @Override
protected void fetchInformation(DataSource dataSource) { protected void fetchInformation(DataSource dataSource) {

View File

@ -74,6 +74,9 @@
</Container> </Container>
<Component class="javax.swing.JLabel" name="activityRangeLabel"> <Component class="javax.swing.JLabel" name="activityRangeLabel">
<Properties> <Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Segoe UI" size="12" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="TimelinePanel.activityRangeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="TimelinePanel.activityRangeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
@ -107,21 +110,42 @@
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/> <AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues> </AuxValues>
</Component> </Component>
<Container class="javax.swing.JPanel" name="notableFilePanel"> <Container class="javax.swing.JPanel" name="earliestLabelPanel">
<Properties> <Properties>
<Property name="alignmentX" type="float" value="0.0"/> <Property name="alignmentX" type="float" value="0.0"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 106]"/> <Dimension value="[32767, 20]"/>
</Property> </Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 106]"/> <Dimension value="[100, 20]"/>
</Property> </Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 106]"/> <Dimension value="[32767, 20]"/>
</Property> </Property>
</Properties> </Properties>
<AuxValues> <AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="notableFileTable"/> <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="earliestLabel"/>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="latestLabelPanel">
<Properties>
<Property name="alignmentX" type="float" value="0.0"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 20]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 20]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 20]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="latestLabel"/>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/> <AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/> <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues> </AuxValues>
@ -147,51 +171,22 @@
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/> <AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues> </AuxValues>
</Component> </Component>
<Component class="javax.swing.JLabel" name="sameIdLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="TimelinePanel.sameIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.Box$Filler" name="filler3">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 2]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 2]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 2]"/>
</Property>
<Property name="alignmentX" type="float" value="0.0"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues>
</Component>
<Container class="javax.swing.JPanel" name="sameIdPanel"> <Container class="javax.swing.JPanel" name="sameIdPanel">
<Properties> <Properties>
<Property name="alignmentX" type="float" value="0.0"/> <Property name="alignmentX" type="float" value="0.0"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 106]"/> <Dimension value="[600, 300]"/>
</Property> </Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 106]"/> <Dimension value="[600, 300]"/>
</Property> </Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 106]"/> <Dimension value="[600, 300]"/>
</Property> </Property>
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
</Properties> </Properties>
<AuxValues> <AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="sameIdTable"/> <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="last30DaysChart"/>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/> <AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/> <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues> </AuxValues>

View File

@ -18,12 +18,22 @@
*/ */
package org.sleuthkit.autopsy.datasourcesummary.ui; package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.awt.Color;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale;
import org.apache.commons.collections.CollectionUtils;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.BarChartItem;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.BarChartSeries;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents;
@ -44,6 +54,9 @@ import org.sleuthkit.datamodel.DataSource;
public class TimelinePanel extends BaseDataSourceSummaryPanel { public class TimelinePanel extends BaseDataSourceSummaryPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final DateFormat EARLIEST_LATEST_FORMAT = new SimpleDateFormat("MMM d, yyyy", Locale.getDefault());
private static final DateFormat CHART_FORMAT = new SimpleDateFormat("MMM d", Locale.getDefault());
private static final Color CHART_COLOR = Color.BLUE;
private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title());
private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title());
@ -71,6 +84,34 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel {
initComponents(); initComponents();
} }
private static String parseEarliestLatest(Date date) {
return date == null ? null : EARLIEST_LATEST_FORMAT.format(date);
}
private BarChartSeries parseChartData(List<DailyActivityAmount> recentDaysActivity) {
if (CollectionUtils.isEmpty(recentDaysActivity)) {
return null;
}
List<BarChartItem> items = new ArrayList<>();
for (int i = 0; i < recentDaysActivity.size(); i++) {
DailyActivityAmount curItem = recentDaysActivity.get(i);
long amount = curItem.getArtifactActivityCount() * 1000 + curItem.getFileActivityCount();
if (i == 0 || i == recentDaysActivity.size() - 1) {
String formattedDate = curItem.getDay() == null ? "" : CHART_FORMAT.format(curItem.getDay());
items.add(new BarChartItem(formattedDate, amount));
} else {
items.add(new BarChartItem("", amount));
}
}
return new BarChartSeries(CHART_COLOR, items);
}
/** /**
* Handles displaying the result for each table by breaking apart subdata * Handles displaying the result for each table by breaking apart subdata
* items into seperate results for each table. * items into seperate results for each table.
@ -78,11 +119,9 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel {
* @param result The result. * @param result The result.
*/ */
private void handleResult(DataFetchResult<TimelineSummaryData> result) { private void handleResult(DataFetchResult<TimelineSummaryData> result) {
if (result == null) { earliestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseEarliestLatest(r.getMinDate())));
// TODO latestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseEarliestLatest(r.getMaxDate())));
} else { last30DaysChart.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseChartData(r.getMostRecentDaysActivity())));
// TODO
}
} }
@Override @Override
@ -115,11 +154,10 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel {
javax.swing.JPanel ingestRunningPanel = ingestRunningLabel; javax.swing.JPanel ingestRunningPanel = ingestRunningLabel;
javax.swing.JLabel activityRangeLabel = new javax.swing.JLabel(); javax.swing.JLabel activityRangeLabel = new javax.swing.JLabel();
javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2)); javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2));
javax.swing.JPanel notableFilePanel = notableFileTable; javax.swing.JPanel earliestLabelPanel = earliestLabel;
javax.swing.JPanel latestLabelPanel = latestLabel;
javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20)); javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20));
javax.swing.JLabel sameIdLabel = new javax.swing.JLabel(); javax.swing.JPanel sameIdPanel = last30DaysChart;
javax.swing.Box.Filler filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2));
javax.swing.JPanel sameIdPanel = sameIdTable;
javax.swing.Box.Filler filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); javax.swing.Box.Filler filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10)); mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
@ -131,6 +169,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel {
ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25)); ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25));
mainContentPanel.add(ingestRunningPanel); mainContentPanel.add(ingestRunningPanel);
activityRangeLabel.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.activityRangeLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.activityRangeLabel.text")); // NOI18N
mainContentPanel.add(activityRangeLabel); mainContentPanel.add(activityRangeLabel);
activityRangeLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TimelinePanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N activityRangeLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TimelinePanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N
@ -138,25 +177,26 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel {
filler1.setAlignmentX(0.0F); filler1.setAlignmentX(0.0F);
mainContentPanel.add(filler1); mainContentPanel.add(filler1);
notableFilePanel.setAlignmentX(0.0F); earliestLabelPanel.setAlignmentX(0.0F);
notableFilePanel.setMaximumSize(new java.awt.Dimension(32767, 106)); earliestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20));
notableFilePanel.setMinimumSize(new java.awt.Dimension(100, 106)); earliestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20));
notableFilePanel.setPreferredSize(new java.awt.Dimension(100, 106)); earliestLabelPanel.setPreferredSize(new java.awt.Dimension(32767, 20));
mainContentPanel.add(notableFilePanel); mainContentPanel.add(earliestLabelPanel);
latestLabelPanel.setAlignmentX(0.0F);
latestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20));
latestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20));
latestLabelPanel.setPreferredSize(new java.awt.Dimension(32767, 20));
mainContentPanel.add(latestLabelPanel);
filler2.setAlignmentX(0.0F); filler2.setAlignmentX(0.0F);
mainContentPanel.add(filler2); mainContentPanel.add(filler2);
org.openide.awt.Mnemonics.setLocalizedText(sameIdLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.sameIdLabel.text")); // NOI18N
mainContentPanel.add(sameIdLabel);
filler3.setAlignmentX(0.0F);
mainContentPanel.add(filler3);
sameIdPanel.setAlignmentX(0.0F); sameIdPanel.setAlignmentX(0.0F);
sameIdPanel.setMaximumSize(new java.awt.Dimension(32767, 106)); sameIdPanel.setMaximumSize(new java.awt.Dimension(600, 300));
sameIdPanel.setMinimumSize(new java.awt.Dimension(100, 106)); sameIdPanel.setMinimumSize(new java.awt.Dimension(600, 300));
sameIdPanel.setPreferredSize(new java.awt.Dimension(100, 106)); sameIdPanel.setPreferredSize(new java.awt.Dimension(600, 300));
sameIdPanel.setVerifyInputWhenFocusTarget(false);
mainContentPanel.add(sameIdPanel); mainContentPanel.add(sameIdPanel);
filler5.setAlignmentX(0.0F); filler5.setAlignmentX(0.0F);

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datasourcesummary.uiutils; package org.sleuthkit.autopsy.datasourcesummary.uiutils;
import java.util.function.Function;
/** /**
* The result of a loading process. * The result of a loading process.
*/ */
@ -30,6 +32,29 @@ public final class DataFetchResult<R> {
SUCCESS, ERROR SUCCESS, ERROR
} }
/**
* A utility method that, given an input data fetch result, creates an error
* result if the original is an error. Otherwise, uses the getSubResult
* function on the underlying data to create a new DataFetchResult.
*
* @param inputResult The input result.
* @param getSubComponent The means of getting the data given the original
* data.
*
* @return The new result with the error of the original or the processed
* data.
*/
public static <I, O> DataFetchResult<O> getSubResult(DataFetchResult<I> inputResult, Function<I, O> getSubResult) {
if (inputResult == null) {
return null;
} else if (inputResult.getResultType() == ResultType.SUCCESS) {
O innerData = (inputResult.getData() == null) ? null : getSubResult.apply(inputResult.getData());
return DataFetchResult.getSuccessResult(innerData);
} else {
return DataFetchResult.getErrorResult(inputResult.getException());
}
}
/** /**
* Creates a DataFetchResult of loaded data including the data. * Creates a DataFetchResult of loaded data including the data.
* *
@ -60,8 +85,7 @@ public final class DataFetchResult<R> {
* Main constructor for the DataLoadingResult. * Main constructor for the DataLoadingResult.
* *
* @param state The state of the result. * @param state The state of the result.
* @param data If the result is SUCCESS, the data related to this * @param data If the result is SUCCESS, the data related to this result.
* result.
* @param exception If the result is ERROR, the related exception. * @param exception If the result is ERROR, the related exception.
*/ */
private DataFetchResult(ResultType state, R data, Throwable exception) { private DataFetchResult(ResultType state, R data, Throwable exception) {