cleanup of layout and commenting

This commit is contained in:
Greg DiCristofaro 2020-09-04 09:14:54 -04:00
parent 17644fe664
commit cd74274c44
10 changed files with 261 additions and 182 deletions

View File

@ -18,7 +18,6 @@
*/
package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.text.DecimalFormat;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.table.DefaultTableModel;
@ -140,8 +139,6 @@ class DataSourceSummaryDetailsPanel extends BaseDataSourceSummaryPanel {
}
}
/**
* Update the visibility of all fields and their labels based on whether
* they have contents. Empty fields have them and their contents hidden.

View File

@ -1,7 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datasourcesummary.ui;
@ -11,8 +24,8 @@ import java.util.List;
import org.openide.util.NbBundle;
/**
*
* @author gregd
* This class provides utilities for representing storage size in most relevant
* units (i.e. bytes, megabytes, etc.).
*/
public class SizeRepresentationUtil {
@ -31,16 +44,26 @@ public class SizeRepresentationUtil {
/**
* Get a long size in bytes as a string formated to be read by users.
*
* @param size Long value representing a size in bytes
* @param size Long value representing a size in bytes.
*
* @return return a string formated with a user friendly version of the size
* as a string, returns empty String when provided empty size
* @return Return a string formated with a user friendly version of the size
* as a string, returns empty String when provided empty size.
*/
public static String getSizeString(Long size) {
return getSizeString(size, APPROXIMATE_SIZE_FORMAT, true);
}
/**
* Get a long size in bytes as a string formated to be read by users.
*
* @param size Long value representing a size in byte.s
* @param format The means of formatting the number.
* @param showFullSize Optionally show the number of bytes in the
* datasource.
*
* @return Return a string formated with a user friendly version of the size
* as a string, returns empty String when provided empty size.
*/
@NbBundle.Messages({
"SizeRepresentationUtil_units_bytes= bytes",
"SizeRepresentationUtil_units_kilobytes= kB",
@ -62,10 +85,10 @@ public class SizeRepresentationUtil {
approximateSize /= SIZE_CONVERSION_CONSTANT;
}
}
String fullSize = String.valueOf(size) + UNITS.get(0);
String closestUnitSize = format.format(approximateSize) + UNITS.get(unitsIndex);
if (unitsIndex == 0) {
return fullSize;
} else if (showFullSize) {

View File

@ -40,7 +40,10 @@
<Dimension value="[32787, 32787]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[650, 510]"/>
<Dimension value="[400, 300]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[400, 300]"/>
</Property>
</Properties>
<AuxValues>
@ -116,73 +119,31 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="pieChartRow">
<Container class="javax.swing.JPanel" name="fileMimeTypesPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
<EmptyBorder bottom="5" left="5" right="5" top="5"/>
</Border>
</Property>
<Property name="alignmentX" type="float" value="0.0"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[1170, 895]"/>
<Dimension value="[400, 300]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="null"/>
<Dimension value="[400, 300]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="null"/>
<Dimension value="[400, 300]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="fileMimeTypesChart"/>
<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"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="fileMimeTypesPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
<EmptyBorder bottom="5" left="5" right="5" top="5"/>
</Border>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[500, 375]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[500, 375]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[500, 375]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="fileMimeTypesChart"/>
<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="artifactTypesPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
<EmptyBorder bottom="5" left="5" right="5" top="5"/>
</Border>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[650, 500]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[650, 500]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[650, 500]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="artifactTypesChart"/>
<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>
</SubComponents>
</Container>
<Component class="javax.swing.Box$Filler" name="filler2">
<Properties>
@ -252,6 +213,16 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
</Container>
<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, 32767]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
</SubComponents>

View File

@ -22,7 +22,6 @@ import java.awt.BorderLayout;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -46,13 +45,12 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel.ColumnModel;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartPanel;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartPanel.PieChartItem;
import org.sleuthkit.autopsy.guiutils.WrapLayout;
import org.sleuthkit.datamodel.DataSource;
/**
* Panel for displaying summary information on the known files present in the
* specified DataSource
* specified DataSource.
*/
@Messages({
"TypesPanel_artifactsTypesPieChart_title=Artifact Types",
@ -77,13 +75,23 @@ import org.sleuthkit.datamodel.DataSource;
"TypesPanel_sizeLabel_title=Size"})
class TypesPanel extends BaseDataSourceSummaryPanel {
/**
* A label that allows for displaying loading messages and can be used with
* a DataFetchResult. Text displays as "<key>:<value | message>".
*/
private static class LoadableLabel extends AbstractLoadableComponent<String> {
private static final long serialVersionUID = 1L;
private final JLabel label = new JLabel();
private final String key;
public LoadableLabel(String key) {
/**
* Main constructor for the label.
*
* @param key The key to be displayed.
*/
LoadableLabel(String key) {
this.key = key;
setLayout(new BorderLayout());
add(label, BorderLayout.CENTER);
@ -96,7 +104,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
String htmlFormattedValue = (italicize) ? String.format("<i>%s</i>", formattedValue) : formattedValue;
label.setText(String.format("<html><div style='text-align: center;'>%s: %s</div></html>", formattedKey, htmlFormattedValue));
}
@Override
protected void setMessage(boolean visible, String message) {
setValue(message, true);
@ -107,11 +115,11 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
setValue(data, false);
}
}
private static final long serialVersionUID = 1L;
private static final DecimalFormat INTEGER_SIZE_FORMAT = new DecimalFormat("#");
// All file type categories.
private static final List<Pair<String, FileTypeCategory>> FILE_MIME_TYPE_CATEGORIES = Arrays.asList(
Pair.of(Bundle.TypesPanel_fileMimeTypesChart_images_title(), FileTypeCategory.IMAGE),
Pair.of(Bundle.TypesPanel_fileMimeTypesChart_videos_title(), FileTypeCategory.VIDEO),
@ -120,43 +128,44 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
Pair.of(Bundle.TypesPanel_fileMimeTypesChart_executables_title(), FileTypeCategory.EXECUTABLE)
);
// The mime types in those categories.
private static final Set<String> CATEGORY_MIME_TYPES = FILE_MIME_TYPE_CATEGORIES
.stream()
.flatMap((cat) -> cat.getRight().getMediaTypes().stream())
.collect(Collectors.toSet());
private final PieChartPanel fileMimeTypesChart = new PieChartPanel(Bundle.TypesPanel_fileMimeTypesChart_title());
private final PieChartPanel artifactTypesChart = new PieChartPanel(Bundle.TypesPanel_artifactsTypesPieChart_title());
private final JTablePanel<Pair<String, Long>> filesByCategoryTable
= JTablePanel.getJTablePanel(Arrays.asList(
// title column
new ColumnModel<>(
Bundle.TypesPanel_filesByCategoryTable_labelColumn_title(),
(pair) -> new DefaultCellModel(pair.getLeft()),
250
),
// count column
new ColumnModel<>(
Bundle.TypesPanel_filesByCategoryTable_countColumn_title(),
(pair) -> new DefaultCellModel(Long.toString(pair.getRight() == null ? 0 : pair.getRight())),
150
)
));
private final LoadableLabel usageLabel = new LoadableLabel(Bundle.TypesPanel_usageLabel_title());
private final LoadableLabel osLabel = new LoadableLabel(Bundle.TypesPanel_osLabel_title());
private final LoadableLabel sizeLabel = new LoadableLabel(Bundle.TypesPanel_sizeLabel_title());
// all loadable components
private final List<LoadableComponent<?>> loadables = Arrays.asList(
usageLabel,
osLabel,
sizeLabel,
fileMimeTypesChart,
artifactTypesChart,
filesByCategoryTable
);
// all of the means for obtaining data for the gui components.
private final List<DataFetchComponents<DataSource, ?>> dataFetchComponents = Arrays.asList(
// usage label worker
new DataFetchWorker.DataFetchComponents<>(
@ -177,23 +186,17 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
new DataFetchWorker.DataFetchComponents<>(
this::getMimeTypeCategoriesModel,
fileMimeTypesChart::showDataFetchResult),
// artifact counts worker
new DataFetchWorker.DataFetchComponents<>(
this::getArtifactCountsModel,
artifactTypesChart::showDataFetchResult),
// files by category worker
new DataFetchWorker.DataFetchComponents<>(
this::getFileCategoryModel,
filesByCategoryTable::showDataFetchResult)
);
/**
* Main constructor.
*/
public TypesPanel() {
initComponents();
customizeComponents();
}
private void customizeComponents() {
this.pieChartRow.setLayout(new WrapLayout(0,5));
}
@Override
@ -219,13 +222,19 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
}
}
/**
* Retrieves data for the file category table.
*
* @param selectedDataSource The datasource.
*
* @return The key value pairs to be displayed.
*/
private List<Pair<String, Long>> getFileCategoryModel(DataSource selectedDataSource) {
if (selectedDataSource == null) {
return null;
}
List<Pair<String, Function<DataSource, Long>>> itemsAndRetrievers = Arrays.asList(
Pair.of(Bundle.TypesPanel_filesByCategoryTable_allRow_title(), DataSourceCountsSummary::getCountOfFiles),
List<Pair<String, Function<DataSource, Long>>> itemsAndRetrievers = Arrays.asList(Pair.of(Bundle.TypesPanel_filesByCategoryTable_allRow_title(), DataSourceCountsSummary::getCountOfFiles),
Pair.of(Bundle.TypesPanel_filesByCategoryTable_allocatedRow_title(), DataSourceCountsSummary::getCountOfAllocatedFiles),
Pair.of(Bundle.TypesPanel_filesByCategoryTable_unallocatedRow_title(), DataSourceCountsSummary::getCountOfUnallocatedFiles),
Pair.of(Bundle.TypesPanel_filesByCategoryTable_slackRow_title(), DataSourceCountsSummary::getCountOfSlackFiles),
@ -241,17 +250,26 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
.collect(Collectors.toList());
}
/**
* Gets all the data for the file type pie chart.
*
* @param dataSource
*
* @return
*/
private List<PieChartItem> getMimeTypeCategoriesModel(DataSource dataSource) {
if (dataSource == null) {
return null;
}
// for each category of file types, get the counts of files
Stream<Pair<String, Long>> fileCategoryItems = FILE_MIME_TYPE_CATEGORIES
.stream()
.map((strCat)
-> Pair.of(strCat.getLeft(),
DataSourceMimeTypeSummary.getCountOfFilesForMimeTypes(dataSource, strCat.getRight().getMediaTypes())));
// also get counts for other and not analayzed
Stream<Pair<String, Long>> otherItems = Stream.of(
Pair.of(Bundle.TypesPanel_fileMimeTypesChart_other_title(),
DataSourceMimeTypeSummary.getCountOfFilesNotInMimeTypes(dataSource, CATEGORY_MIME_TYPES)),
@ -259,35 +277,13 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
DataSourceMimeTypeSummary.getCountOfFilesWithNoMimeType(dataSource))
);
// create pie chart items to provide to pie chart
return Stream.concat(fileCategoryItems, otherItems)
.filter(keyCount -> keyCount.getRight() != null && keyCount.getRight() > 0)
.map(keyCount -> new PieChartItem(keyCount.getLeft(), keyCount.getRight()))
.collect(Collectors.toList());
}
/**
* The counts of different artifact types found in a DataSource.
*
* @param selectedDataSource The DataSource.
*
* @return The JTable data model of counts of artifact types.
*/
private List<PieChartItem> getArtifactCountsModel(DataSource selectedDataSource) {
Map<String, Long> artifactMapping = DataSourceCountsSummary.getCountsOfArtifactsByType(selectedDataSource);
if (artifactMapping == null) {
return null;
}
return artifactMapping.entrySet().stream()
.filter((entrySet) -> entrySet != null)
.sorted((a, b) -> a.getKey().compareTo(b.getKey()))
.map((entrySet) -> new PieChartItem(entrySet.getKey(), entrySet.getValue()))
.collect(Collectors.toList());
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
@ -302,19 +298,19 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
javax.swing.JPanel usagePanel = usageLabel;
javax.swing.JPanel osPanel = osLabel;
javax.swing.JPanel sizePanel = sizeLabel;
pieChartRow = new javax.swing.JPanel();
javax.swing.JPanel fileMimeTypesPanel = fileMimeTypesChart;
javax.swing.JPanel artifactTypesPanel = artifactTypesChart;
javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(32767, 5));
javax.swing.JLabel filesByCategoryLabel = 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(32767, 2));
javax.swing.JPanel filesByCategoryPanel = filesByCategoryTable;
filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
setLayout(new java.awt.BorderLayout());
contentParent.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
contentParent.setMaximumSize(new java.awt.Dimension(32787, 32787));
contentParent.setMinimumSize(new java.awt.Dimension(650, 510));
contentParent.setMinimumSize(new java.awt.Dimension(400, 300));
contentParent.setPreferredSize(new java.awt.Dimension(400, 300));
contentParent.setLayout(new javax.swing.BoxLayout(contentParent, javax.swing.BoxLayout.PAGE_AXIS));
usagePanel.setAlignmentX(0.0F);
@ -336,24 +332,12 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
sizePanel.setPreferredSize(new java.awt.Dimension(800, 20));
contentParent.add(sizePanel);
pieChartRow.setAlignmentX(0.0F);
pieChartRow.setMaximumSize(new java.awt.Dimension(1170, 895));
pieChartRow.setMinimumSize(null);
pieChartRow.setPreferredSize(null);
fileMimeTypesPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
fileMimeTypesPanel.setMaximumSize(new java.awt.Dimension(500, 375));
fileMimeTypesPanel.setMinimumSize(new java.awt.Dimension(500, 375));
fileMimeTypesPanel.setPreferredSize(new java.awt.Dimension(500, 375));
pieChartRow.add(fileMimeTypesPanel);
artifactTypesPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
artifactTypesPanel.setMaximumSize(new java.awt.Dimension(650, 500));
artifactTypesPanel.setMinimumSize(new java.awt.Dimension(650, 500));
artifactTypesPanel.setPreferredSize(new java.awt.Dimension(650, 500));
pieChartRow.add(artifactTypesPanel);
contentParent.add(pieChartRow);
fileMimeTypesPanel.setAlignmentX(0.0F);
fileMimeTypesPanel.setMaximumSize(new java.awt.Dimension(400, 300));
fileMimeTypesPanel.setMinimumSize(new java.awt.Dimension(400, 300));
fileMimeTypesPanel.setPreferredSize(new java.awt.Dimension(400, 300));
contentParent.add(fileMimeTypesPanel);
contentParent.add(filler2);
org.openide.awt.Mnemonics.setLocalizedText(filesByCategoryLabel, org.openide.util.NbBundle.getMessage(TypesPanel.class, "TypesPanel.filesByCategoryLabel.text")); // NOI18N
@ -365,6 +349,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
filesByCategoryPanel.setMinimumSize(new java.awt.Dimension(10, 107));
filesByCategoryPanel.setPreferredSize(new java.awt.Dimension(400, 107));
contentParent.add(filesByCategoryPanel);
contentParent.add(filler3);
scrollParent.setViewportView(contentParent);
@ -373,6 +358,6 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel pieChartRow;
private javax.swing.Box.Filler filler3;
// End of variables declaration//GEN-END:variables
}

View File

@ -1,7 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datasourcesummary.uiutils;
@ -12,18 +25,27 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
*
* @author gregd
* Abstract class for common methods of a loadable component.
*/
@NbBundle.Messages({
"AbstractLoadableComponent_loadingMessage_defaultText=Loading results...",
"AbstractLoadableComponent_errorMessage_defaultText=There was an error loading results.",
"AbstractLoadableComponent_noDataExists_defaultText=No data exists.",
})
"AbstractLoadableComponent_noDataExists_defaultText=No data exists.",})
public abstract class AbstractLoadableComponent<T> extends JPanel implements LoadableComponent<T> {
/**
* The default loading message.
*/
public static final String DEFAULT_LOADING_MESSAGE = Bundle.AbstractLoadableComponent_loadingMessage_defaultText();
/**
* The default error message.
*/
public static final String DEFAULT_ERROR_MESSAGE = Bundle.AbstractLoadableComponent_errorMessage_defaultText();
/**
* The default 'no results' message.
*/
public static final String DEFAULT_NO_RESULTS_MESSAGE = Bundle.AbstractLoadableComponent_noDataExists_defaultText();
private static final Logger logger = Logger.getLogger(AbstractLoadableComponent.class.getName());

View File

@ -1,7 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datasourcesummary.uiutils;
@ -9,10 +22,11 @@ import java.awt.Graphics;
import javax.swing.JLabel;
/**
*
* @author gregd
* Base class for drawing a message overlay. Contains a paint method for
* painting a JLabel using a java.awt.Graphics object.
*/
public class BaseMessageOverlay {
private final JLabel label;
private boolean visible = false;
@ -54,6 +68,13 @@ public class BaseMessageOverlay {
message == null ? "" : message));
}
/**
* Paints the jlabel at full width and height with the graphics object.
*
* @param g The graphics object.
* @param width The width.
* @param height The height.
*/
public void paintOverlay(Graphics g, int width, int height) {
if (!visible) {
return;

View File

@ -242,7 +242,6 @@ public class JTablePanel<T> extends AbstractLoadableComponent<List<T>> {
return this;
}
@Override
protected void setResults(List<T> data) {
// set the list of data to be shown as either the data or an empty list

View File

@ -25,8 +25,8 @@ import javax.swing.table.TableModel;
* An interface to be used with the JTablePanel that specifies a TableModel to
* be used with the underlying JTable based on a list of object type T.
*/
public interface ListTableModel<T> extends TableModel {
public interface ListTableModel<T> extends TableModel {
/**
* @return The list of objects supporting the rows to be displayed in the
* table.

View File

@ -1,13 +1,26 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datasourcesummary.uiutils;
/**
*
* @author gregd
* Interface for a loadable component that can show messages, results, or a
* DataFetchResult.
*/
public interface LoadableComponent<T> {
@ -56,5 +69,5 @@ public interface LoadableComponent<T> {
*
* @param result The DataFetchResult.
*/
public void showDataFetchResult(DataFetchResult<T> result);
void showDataFetchResult(DataFetchResult<T> result);
}

View File

@ -1,7 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datasourcesummary.uiutils;
@ -22,32 +35,48 @@ import org.jfree.chart.plot.PiePlot;
import org.jfree.data.general.DefaultPieDataset;
/**
*
* @author gregd
* A pie chart panel.
*/
public class PieChartPanel extends AbstractLoadableComponent<List<PieChartPanel.PieChartItem>> {
/**
*
* An individual pie chart slice in the pie chart.
*/
public static class PieChartItem {
private final String label;
private final double value;
/**
* Main constructor.
*
* @param label The label for this pie slice.
* @param value The value for this item.
*/
public PieChartItem(String label, double value) {
this.label = label;
this.value = value;
}
/**
* @return The label for this item.
*/
public String getLabel() {
return label;
}
/**
* @return The value for this item.
*/
public double getValue() {
return value;
}
}
/**
* A JFreeChart message overlay that can show a message for the purposes of
* the LoadableComponent.
*/
private static class MessageOverlay extends AbstractOverlay implements Overlay {
private static final long serialVersionUID = 1L;
@ -71,31 +100,38 @@ public class PieChartPanel extends AbstractLoadableComponent<List<PieChartPanel.
void setMessage(String message) {
overlay.setMessage(message);
}
@Override
public void paintOverlay(Graphics2D gd, ChartPanel cp) {
overlay.paintOverlay(gd, cp.getWidth(), cp.getHeight());
}
}
private static final long serialVersionUID = 1L;
private static final Font DEFAULT_FONT = new JLabel().getFont();
private static final Font DEFAULT_HEADER_FONT = new Font(DEFAULT_FONT.getName(), DEFAULT_FONT.getStyle(), (int) (DEFAULT_FONT.getSize() * 1.5));
private static final PieSectionLabelGenerator DEFAULT_LABEL_GENERATOR =
new StandardPieSectionLabelGenerator(
private static final PieSectionLabelGenerator DEFAULT_LABEL_GENERATOR
= new StandardPieSectionLabelGenerator(
"{0}: {1} ({2})", new DecimalFormat("0"), new DecimalFormat("0.0%"));
private final MessageOverlay overlay = new MessageOverlay();
private final DefaultPieDataset dataset = new DefaultPieDataset();
private final JFreeChart chart;
/**
* Main constructor.
*/
public PieChartPanel() {
this(null);
}
/**
* Main constructor for the pie chart.
*
* @param title The title for this pie chart.
*/
public PieChartPanel(String title) {
// Create chart
this.chart = ChartFactory.createPieChart(
@ -109,6 +145,9 @@ public class PieChartPanel extends AbstractLoadableComponent<List<PieChartPanel.
chart.getLegend().setItemFont(DEFAULT_FONT);
chart.getTitle().setFont(DEFAULT_HEADER_FONT);
// don't show a legend by default
chart.removeLegend();
PiePlot plot = ((PiePlot) chart.getPlot());
plot.setLabelGenerator(DEFAULT_LABEL_GENERATOR);
@ -123,18 +162,27 @@ public class PieChartPanel extends AbstractLoadableComponent<List<PieChartPanel.
this.add(panel, BorderLayout.CENTER);
}
/**
* @return The title for this chart if one exists.
*/
public String getTitle() {
return (this.chart == null || this.chart.getTitle() == null) ?
null :
this.chart.getTitle().getText();
return (this.chart == null || this.chart.getTitle() == null)
? null
: this.chart.getTitle().getText();
}
/**
* Sets the title for this pie chart.
*
* @param title The title.
*
* @return As a utility, returns this.
*/
public PieChartPanel setTitle(String title) {
this.chart.getTitle().setText(title);
return this;
}
@Override
protected void setMessage(boolean visible, String message) {
this.overlay.setVisible(visible);