Merge pull request #1944 from millmanorama/IG-follow-up-flag-image

add follow up flag image to follow up action and in group list , impr…
This commit is contained in:
Richard Cordovano 2016-02-05 11:59:58 -05:00
commit 7f3396a261
13 changed files with 187 additions and 93 deletions

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,10 +20,8 @@ package org.sleuthkit.autopsy.imagegallery.actions;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
import javafx.scene.image.ImageView;
import org.controlsfx.control.action.Action;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.datamodel.TagName;
/**
@ -36,6 +34,6 @@ public class TagGroupAction extends Action {
Set<Long> fileIdSet = ImmutableSet.copyOf(controller.viewState().get().getGroup().getFileIDs());
new AddDrawableTagAction(controller).addTagsToFiles(tagName, "", fileIdSet);
});
setGraphic(new ImageView(DrawableAttribute.TAGS.getIcon()));
setGraphic(controller.getTagsManager().getGraphic(tagName));
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,10 +18,8 @@
*/
package org.sleuthkit.autopsy.imagegallery.actions;
import javafx.scene.image.ImageView;
import org.controlsfx.control.action.Action;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.datamodel.TagName;
/**
@ -31,6 +29,6 @@ public class TagSelectedFilesAction extends Action {
public TagSelectedFilesAction(final TagName tagName, ImageGalleryController controller) {
super(tagName.getDisplayName(), actionEvent -> new AddDrawableTagAction(controller).addTag(tagName, ""));
setGraphic(new ImageView(DrawableAttribute.TAGS.getIcon()));
setGraphic(controller.getTagsManager().getGraphic(tagName));
}
}

View File

@ -23,9 +23,17 @@ import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import org.openide.util.NbBundle;
/**
@ -51,6 +59,9 @@ public enum Category {
FIVE(Color.GREEN, 5, Bundle.Category_five()),
ZERO(Color.LIGHTGREY, 0, Bundle.Category_zero());
private static final BorderWidths BORDER_WIDTHS_2 = new BorderWidths(2);
private static final CornerRadii CORNER_RADII_4 = new CornerRadii(4);
public static ImmutableList<Category> getNonZeroCategories() {
return nonZeroCategories;
}
@ -108,9 +119,10 @@ public enum Category {
}
public Node getGraphic() {
Rectangle rectangle = new Rectangle(16d, 16d, getColor());
rectangle.setArcHeight(8);
rectangle.setArcWidth(8);
return rectangle;
Region region = new Region();
region.setBackground(new Background(new BackgroundFill(getColor(), CORNER_RADII_4, Insets.EMPTY)));
region.setPrefSize(16, 16);
region.setBorder(new Border(new BorderStroke(getColor().darker(), BorderStrokeStyle.SOLID, CORNER_RADII_4, BORDER_WIDTHS_2)));
return region;
}
}

View File

@ -25,7 +25,9 @@ import java.util.List;
import java.util.function.Function;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.StringProperty;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
@ -82,10 +84,16 @@ public class DrawableAttribute<T extends Comparable<T>> {
* advantage. move categories into DrawableDB?
*/
public final static DrawableAttribute<Category> CATEGORY =
new DrawableAttribute<>(AttributeName.CATEGORY, Bundle.DrawableAttribute_category(),
new DrawableAttribute<Category>(AttributeName.CATEGORY, Bundle.DrawableAttribute_category(),
false,
"category-icon.png", //NON-NLS
f -> Collections.singleton(f.getCategory()));
f -> Collections.singleton(f.getCategory())) {
@Override
public Node getGraphicForValue(Category val) {
return val.getGraphic();
}
};
public final static DrawableAttribute<TagName> TAGS =
new DrawableAttribute<>(AttributeName.TAGS, Bundle.DrawableAttribute_tags(),
@ -195,8 +203,8 @@ public class DrawableAttribute<T extends Comparable<T>> {
* TODO: override this to load per value icons form some attributes like
* mime-type and category
*/
public Image getIconForValue(T val) {
return getIcon();
public Node getGraphicForValue(T val) {
return new ImageView(getIcon());
}
public static List<DrawableAttribute<?>> getGroupableAttrs() {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-15 Basis Technology Corp.
* Copyright 2013-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,6 +26,9 @@ import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.openide.util.NbBundle;
@ -40,7 +43,7 @@ import org.sleuthkit.datamodel.TskCoreException;
/**
* Manages Tags, Tagging, and the relationship between Categories and Tags in
* the autopsy Db. delegates some, work to the backing {@link TagsManager}.
* the autopsy Db. Delegates some work to the backing {@link TagsManager}.
*/
@NbBundle.Messages({"DrawableTagsManager.followUp=Follow Up"})
public class DrawableTagsManager {
@ -48,11 +51,14 @@ public class DrawableTagsManager {
private static final Logger LOGGER = Logger.getLogger(DrawableTagsManager.class.getName());
private static final String FOLLOW_UP = Bundle.DrawableTagsManager_followUp();
private static Image FOLLOW_UP_IMAGE;
final private Object autopsyTagsManagerLock = new Object();
private TagsManager autopsyTagsManager;
/** Used to distribute {@link TagsChangeEvent}s */
/**
* Used to distribute {@link TagsChangeEvent}s
*/
private final EventBus tagsEventBus = new AsyncEventBus(
Executors.newSingleThreadExecutor(
new BasicThreadFactory.Builder().namingPattern("Tags Event Bus").uncaughtExceptionHandler((Thread t, Throwable e) -> { //NON-NLS
@ -60,7 +66,9 @@ public class DrawableTagsManager {
}).build()
));
/** The tag name corresponding to the "built-in" tag "Follow Up" */
/**
* The tag name corresponding to the "built-in" tag "Follow Up"
*/
private TagName followUpTagName;
public DrawableTagsManager(TagsManager autopsyTagsManager) {
@ -137,8 +145,8 @@ public class DrawableTagsManager {
* get all the TagNames that are not categories
*
* @return all the TagNames that are not categories, in alphabetical order
* by displayName, or, an empty set if there was an exception looking them
* up from the db.
* by displayName, or, an empty set if there was an exception
* looking them up from the db.
*/
@Nonnull
public List<TagName> getNonCategoryTagNames() {
@ -228,4 +236,22 @@ public class DrawableTagsManager {
autopsyTagsManager.deleteContentTag(ct);
}
}
public Node getGraphic(TagName tagname) {
try {
if (tagname.equals(getFollowUpTagName())) {
return new ImageView(getFollowUpImage());
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to get \"Follow Up\" tag name from db.", ex);
}
return DrawableAttribute.TAGS.getGraphicForValue(tagname);
}
synchronized private static Image getFollowUpImage() {
if (FOLLOW_UP_IMAGE == null) {
FOLLOW_UP_IMAGE = new Image("/org/sleuthkit/autopsy/imagegallery/images/flag_red.png");
}
return FOLLOW_UP_IMAGE;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Copyright 2013-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.imagegallery.datamodel.grouping;
import java.util.Map;
import java.util.Objects;
import javafx.scene.image.Image;
import javafx.scene.Node;
import javax.annotation.concurrent.Immutable;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.datamodel.TagName;
@ -89,7 +89,7 @@ public class GroupKey<T extends Comparable<T>> implements Comparable<GroupKey<T>
return val.compareTo(o.val);
}
public Image getIcon() {
return attr.getIconForValue(val);
public Node getGraphic() {
return attr.getGraphicForValue(val);
}
}

View File

@ -1,11 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.SplitMenuButton?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<fx:root minWidth="-1.0" orientation="HORIZONTAL" prefWidth="-1.0" type="javafx.scene.control.ToolBar" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<fx:root minWidth="-1.0" orientation="HORIZONTAL" prefWidth="-1.0" type="javafx.scene.control.ToolBar" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
<items>
<Label text="Group By:">
<labelFor>
@ -13,7 +23,7 @@
</labelFor>
</Label>
<fx:reference source="groupByBox" />
<Region prefHeight="-1.0" prefWidth="20.0" />
<Region prefHeight="-1.0" prefWidth="10.0" />
<Label text="Sort By:">
<labelFor>
<ComboBox fx:id="sortByBox" />
@ -50,26 +60,54 @@
</children>
</HBox>
<Separator orientation="VERTICAL" prefHeight="-1.0" prefWidth="20.0" />
<CheckBox fx:id="onlyAnalyzedCheckBox" allowIndeterminate="false" indeterminate="false" mnemonicParsing="false" prefWidth="16.0" selected="true" text="only analyzed groups" underline="false" visible="false" />
<Label contentDisplay="RIGHT" text="Apply to Group:" textOverrun="ELLIPSIS" />
<HBox alignment="CENTER" spacing="5.0">
<children>
<Label text="Tag Group's Files:">
<graphic>
<ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../images/tag_red.png" />
</image>
</ImageView>
</graphic>
</Label>
<SplitMenuButton id="tagSplitMenu" fx:id="tagGroupMenuButton" disable="true" mnemonicParsing="false" text="Follow Up" textOverrun="ELLIPSIS">
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</SplitMenuButton>
</children>
</HBox>
<HBox alignment="CENTER" spacing="5.0">
<children>
<Label text="Categorize Group's Files:">
<graphic>
<ImageView fitHeight="16.0" fitWidth="16.0" mouseTransparent="true" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../images/category-icon.png" />
</image>
</ImageView>
</graphic>
</Label>
<SplitMenuButton id="catSplitMenu" fx:id="catGroupMenuButton" disable="true" mnemonicParsing="false" text="Cat-0">
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</SplitMenuButton>
</children>
</HBox>
<Separator orientation="VERTICAL" prefHeight="-1.0" prefWidth="20.0" />
<HBox alignment="CENTER" spacing="5.0">
<children>
<Label text="Thumbnail Size (px):">
<labelFor>
<Slider fx:id="sizeSlider" blockIncrement="100.0" majorTickUnit="100.0" max="300.0" min="100.0" minorTickCount="0" orientation="HORIZONTAL" prefHeight="-1.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="100.0" />
</labelFor>
</Label>
<fx:reference source="sizeSlider" />
</children>
</HBox>
</items>
</fx:root>

View File

@ -29,7 +29,6 @@ import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioButton;
@ -62,9 +61,6 @@ public class Toolbar extends ToolBar {
@FXML
private ComboBox<DrawableAttribute<?>> groupByBox;
@FXML
private CheckBox onlyAnalyzedCheckBox;
@FXML
private Slider sizeSlider;
@ -125,7 +121,7 @@ public class Toolbar extends ToolBar {
assert catGroupMenuButton != null : "fx:id=\"catSelectedMenubutton\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert descRadio != null : "fx:id=\"descRadio\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert groupByBox != null : "fx:id=\"groupByBox\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert onlyAnalyzedCheckBox != null : "fx:id=\"onlyAnalyzedCheckBox\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert orderGroup != null : "fx:id=\"orderGroup\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert sizeSlider != null : "fx:id=\"sizeSlider\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert sortByBox != null : "fx:id=\"sortByBox\" was not injected: check your FXML file 'Toolbar.fxml'.";

View File

@ -145,6 +145,8 @@ import org.sleuthkit.datamodel.TskCoreException;
public class GroupPane extends BorderPane {
private static final Logger LOGGER = Logger.getLogger(GroupPane.class.getName());
private static final BorderWidths BORDER_WIDTHS_2 = new BorderWidths(2);
private static final CornerRadii CORNER_RADII_2 = new CornerRadii(2);
private static final DropShadow DROP_SHADOW = new DropShadow(10, Color.BLUE);
@ -383,10 +385,11 @@ public class GroupPane extends BorderPane {
assert tileToggle != null : "fx:id=\"tileToggle\" was not injected: check your FXML file 'GroupHeader.fxml'.";
for (Category cat : Category.values()) {
getToggleForCategory(cat).setBorder(new Border(new BorderStroke(cat.getColor(), BorderStrokeStyle.SOLID, new CornerRadii(1), new BorderWidths(1))));
getToggleForCategory(cat).getStyleClass().remove("radio-button");
getToggleForCategory(cat).getStyleClass().add("toggle-button");
getToggleForCategory(cat).selectedProperty().addListener((ov, wasSelected, toggleSelected) -> {
ToggleButton toggleForCategory = getToggleForCategory(cat);
toggleForCategory.setBorder(new Border(new BorderStroke(cat.getColor(), BorderStrokeStyle.SOLID, CORNER_RADII_2, BORDER_WIDTHS_2)));
toggleForCategory.getStyleClass().remove("radio-button");
toggleForCategory.getStyleClass().add("toggle-button");
toggleForCategory.selectedProperty().addListener((ov, wasSelected, toggleSelected) -> {
if (toggleSelected && slideShowPane != null) {
slideShowPane.getFileID().ifPresent((fileID) -> {
selectionModel.clearAndSelect(fileID);

View File

@ -24,13 +24,17 @@ import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.scene.Node;
import javafx.scene.control.ListCell;
import javafx.scene.control.OverrunStyle;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javax.annotation.Nonnull;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup;
import org.sleuthkit.datamodel.TagName;
/**
*
@ -66,9 +70,10 @@ class GroupListCell extends ListCell<DrawableGroup> {
};
private final ReadOnlyObjectProperty<GroupComparators<?>> sortOrder;
private final ImageGalleryController controller;
GroupListCell(ReadOnlyObjectProperty<GroupComparators<?>> sortOrderProperty) {
GroupListCell(ImageGalleryController controller, ReadOnlyObjectProperty<GroupComparators<?>> sortOrderProperty) {
this.controller = controller;
this.sortOrder = sortOrderProperty;
getStylesheets().add(GroupTreeCell.class.getResource("GroupTreeCell.css").toExternalForm()); //NON-NLS
getStyleClass().add("groupTreeCell"); //reduce indent to 5, default is 10 which uses up a lot of space. NON-NLS
@ -102,10 +107,10 @@ class GroupListCell extends ListCell<DrawableGroup> {
} else {
final String text = getGroupName() + getCountsText();
String style;
Image icon;
Node icon;
if (isNull(group)) {
//"dummy" group in file system tree <=> a folder with no drawables
icon = EMPTY_FOLDER_ICON;
icon = new ImageView(EMPTY_FOLDER_ICON);
style = "";
} else {
//if number of files in this group changes (eg a file is recategorized), update counts via listener
@ -117,13 +122,15 @@ class GroupListCell extends ListCell<DrawableGroup> {
group.seenProperty().addListener(seenListener);
//and use icon corresponding to group type
icon = group.getGroupKey().getIcon();
icon = (group.getGroupByAttribute() == DrawableAttribute.TAGS)
? controller.getTagsManager().getGraphic((TagName) group.getGroupByValue())
: group.getGroupKey().getGraphic();
style = getSeenStyleClass();
}
Platform.runLater(() -> {
setTooltip(new Tooltip(text));
setGraphic(new ImageView(icon));
setGraphic(icon);
setText(text);
setStyle(style);
});

View File

@ -32,7 +32,6 @@ import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.ImageView;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.Beta;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
@ -73,7 +72,7 @@ final public class GroupTree extends NavPanel<TreeItem<GroupTreeNode>> {
getToolBar().visibleProperty().bind(groupedByPath.not());
getToolBar().managedProperty().bind(groupedByPath.not());
groupTree.setCellFactory(treeView -> new GroupTreeCell(getSortByBox().getSelectionModel().selectedItemProperty()));
groupTree.setCellFactory(treeView -> new GroupTreeCell(getController(), getSortByBox().getSelectionModel().selectedItemProperty()));
groupTree.setShowRoot(false);
getGroupManager().getAnalyzedGroups().addListener((ListChangeListener.Change<? extends DrawableGroup> change) -> {

View File

@ -24,6 +24,7 @@ import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.scene.Node;
import javafx.scene.control.OverrunStyle;
import javafx.scene.control.Tooltip;
import javafx.scene.control.TreeCell;
@ -31,7 +32,10 @@ import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup;
import org.sleuthkit.datamodel.TagName;
/**
* A cell in the NavPanel tree that listens to its associated group's fileids
@ -72,8 +76,10 @@ class GroupTreeCell extends TreeCell<GroupTreeNode> {
});
};
private final ReadOnlyObjectProperty<GroupComparators<?>> sortOrder;
private final ImageGalleryController controller;
GroupTreeCell(ReadOnlyObjectProperty<GroupComparators<?>> sortOrderProperty) {
GroupTreeCell(ImageGalleryController controller, ReadOnlyObjectProperty<GroupComparators<?>> sortOrderProperty) {
this.controller = controller;
this.sortOrder = sortOrderProperty;
getStylesheets().add(GroupTreeCell.class.getResource("GroupTreeCell.css").toExternalForm()); //NON-NLS
getStyleClass().add("groupTreeCell"); //reduce indent to 5, default is 10 which uses up a lot of space. NON-NLS
@ -112,7 +118,8 @@ class GroupTreeCell extends TreeCell<GroupTreeNode> {
setStyle("");
});
} else {
if (isNull(treeNode.getGroup())) {
DrawableGroup group = treeNode.getGroup();
if (isNull(group)) {
final String text = getGroupName();
//"dummy" group in file system tree <=> a folder with no drawables
Platform.runLater(() -> {
@ -124,20 +131,22 @@ class GroupTreeCell extends TreeCell<GroupTreeNode> {
} else {
//if number of files in this group changes (eg a file is recategorized), update counts via listener
treeNode.getGroup().getFileIDs().addListener(fileCountListener);
treeNode.getGroup().uncatCountProperty().addListener(fileCountListener);
treeNode.getGroup().hashSetHitsCountProperty().addListener(fileCountListener);
group.getFileIDs().addListener(fileCountListener);
group.uncatCountProperty().addListener(fileCountListener);
group.hashSetHitsCountProperty().addListener(fileCountListener);
sortOrder.addListener(fileCountListener);
//if the seen state of this group changes update its style
treeNode.getGroup().seenProperty().addListener(seenListener);
group.seenProperty().addListener(seenListener);
//and use icon corresponding to group type
final Image icon = treeNode.getGroup().getGroupKey().getIcon();
Node icon = (group.getGroupByAttribute() == DrawableAttribute.TAGS)
? controller.getTagsManager().getGraphic((TagName) group.getGroupByValue())
: group.getGroupKey().getGraphic();
final String text = getGroupName() + getCountsText();
final String style = getSeenStyleClass();
Platform.runLater(() -> {
setTooltip(new Tooltip(text));
setGraphic(new ImageView(icon));
setGraphic(icon);
setText(text);
setStyle(style);
});

View File

@ -79,7 +79,7 @@ final public class HashHitGroupList extends NavPanel<DrawableGroup> {
getBorderPane().setCenter(groupList);
sorted = getController().getGroupManager().getAnalyzedGroups().filtered((DrawableGroup t) -> t.getHashSetHitsCount() > 0).sorted(getDefaultComparator());
groupList.setCellFactory(treeView -> new GroupListCell(getSortByBox().getSelectionModel().selectedItemProperty()));
groupList.setCellFactory(treeView -> new GroupListCell(getController(), getSortByBox().getSelectionModel().selectedItemProperty()));
groupList.setItems(sorted);
}