Merge remote-tracking branch 'upstream/TL-list-view' into 792-truncate-descriptions-in-list-view

Conflicts:
	Core/src/org/sleuthkit/autopsy/timeline/datamodel/CombinedEvent.java
	Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java
This commit is contained in:
jmillman 2016-05-26 15:05:39 -04:00
commit 37f2bee2de
4 changed files with 59 additions and 45 deletions

View File

@ -24,6 +24,7 @@ import java.io.IOException;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.ExecutionException;
@ -344,6 +345,9 @@ public class TimeLineController {
filteredEvents.filterProperty().get(),
DescriptionLoD.SHORT);
historyManager.advance(InitialZoomState);
//clear the selected events when the view mode changes
viewMode.addListener(observable -> selectEventIDs(Collections.emptySet()));
}
/**

View File

@ -35,6 +35,10 @@ public class CombinedEvent {
private final long fileID;
private final long epochMillis;
private final String description;
/**
* A map from EventType to event ID.
*/
private final Map<EventType, Long> eventTypeMap = new HashMap<>();
/**
@ -43,7 +47,7 @@ public class CombinedEvent {
* @param epochMillis The timestamp for this event, in millis from the Unix
* epoch.
* @param description The full description shared by all the combined events
* @param fileID The ID of the file all the combined events are for.
* @param fileID The ID of the file shared by all the combined events.
* @param eventMap A map from EventType to event ID.
*/
public CombinedEvent(long epochMillis, String description, long fileID, Map<EventType, Long> eventMap) {
@ -145,5 +149,4 @@ public class CombinedEvent {
}
return true;
}
}

View File

@ -79,8 +79,8 @@ public abstract class AbstractTimelineChart<X, Y, NodeType extends Node, ChartTy
private static final Border ONLY_LEFT_BORDER = new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(0, 0, 0, 1)));
/**
* Get the tool tip to use for this view when no more specific
* Tooltip is needed.
* Get the tool tip to use for this view when no more specific Tooltip is
* needed.
*
* @return The default Tooltip.
*/
@ -176,8 +176,8 @@ public abstract class AbstractTimelineChart<X, Y, NodeType extends Node, ChartTy
abstract protected Boolean isTickBold(X value);
/**
* Apply this view's 'selection effect' to the given node, if
* applied is true. If applied is false, remove the affect
* Apply this view's 'selection effect' to the given node, if applied is
* true. If applied is false, remove the affect
*
* @param node The node to apply the 'effect' to
* @param applied True if the effect should be applied, false if the effect

View File

@ -75,7 +75,7 @@ class ListTimeline extends BorderPane {
private static final Logger LOGGER = Logger.getLogger(ListTimeline.class.getName());
/**
* call-back used to wrap CombinedEvent in a ObservableValue
* call-back used to wrap the CombinedEvent in a ObservableValue
*/
private static final Callback<TableColumn.CellDataFeatures<CombinedEvent, CombinedEvent>, ObservableValue<CombinedEvent>> CELL_VALUE_FACTORY = param -> new SimpleObjectProperty<>(param.getValue());
@ -351,48 +351,55 @@ class ListTimeline extends BorderPane {
event = null;
} else {
event = controller.getEventsModel().getEventById(item.getRepresentativeEventID());
//make context menu
try {
EventNode node = EventNode.createEventNode(event.getEventID(), controller.getEventsModel());
List<MenuItem> menuItems = new ArrayList<>();
//for each actions avaialable on node, make a menu item.
for (Action action : node.getActions(false)) {
if (action == null) {
// swing/netbeans uses null action to represent separator in menu
menuItems.add(new SeparatorMenuItem());
} else {
String actionName = Objects.toString(action.getValue(Action.NAME));
//for now, suppress properties and tools actions, by ignoring them
if (Arrays.asList("&Properties", "Tools").contains(actionName) == false) {
if (action instanceof Presenter.Popup) {
/*
* If the action is really the root of a set
* of actions (eg, tagging). Make a menu
* that parallels the action's menu.
*/
JMenuItem submenu = ((Presenter.Popup) action).getPopupPresenter();
menuItems.add(SwingFXMenuUtils.createFXMenu(submenu));
} else {
menuItems.add(SwingFXMenuUtils.createFXMenu(new Actions.MenuItem(action, false)));
setOnContextMenuRequested(contextMenuEvent -> {
//make a new context menu on each request in order to include uptodate tag names and hash sets
try {
EventNode node = EventNode.createEventNode(item.getRepresentativeEventID(), controller.getEventsModel());
List<MenuItem> menuItems = new ArrayList<>();
//for each actions avaialable on node, make a menu item.
for (Action action : node.getActions(false)) {
if (action == null) {
// swing/netbeans uses null action to represent separator in menu
menuItems.add(new SeparatorMenuItem());
} else {
String actionName = Objects.toString(action.getValue(Action.NAME));
//for now, suppress properties and tools actions, by ignoring them
if (Arrays.asList("&Properties", "Tools").contains(actionName) == false) {
if (action instanceof Presenter.Popup) {
/*
* If the action is really the root of a
* set of actions (eg, tagging). Make a
* menu that parallels the action's
* menu.
*/
JMenuItem submenu = ((Presenter.Popup) action).getPopupPresenter();
menuItems.add(SwingFXMenuUtils.createFXMenu(submenu));
} else {
menuItems.add(SwingFXMenuUtils.createFXMenu(new Actions.MenuItem(action, false)));
}
}
}
}
};
};
//show new context menu.
new ContextMenu(menuItems.toArray(new MenuItem[menuItems.size()]))
.show(this, contextMenuEvent.getScreenX(), contextMenuEvent.getScreenY());
} catch (IllegalStateException ex) {
//Since the case is closed, the user probably doesn't care about this, just log it as a precaution.
LOGGER.log(Level.SEVERE, "There was no case open to lookup the Sleuthkit object backing a SingleEvent.", ex); // NON-NLS
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to lookup Sleuthkit object backing a SingleEvent.", ex); // NON-NLS
Platform.runLater(() -> {
Notifications.create()
.owner(getScene().getWindow())
.text(Bundle.ListChart_errorMsg())
.showError();
});
}
});
setContextMenu(new ContextMenu(menuItems.toArray(new MenuItem[menuItems.size()])));
} catch (IllegalStateException ex) {
//Since the case is closed, the user probably doesn't care about this, just log it as a precaution.
LOGGER.log(Level.SEVERE, "There was no case open to lookup the Sleuthkit object backing a SingleEvent.", ex); // NON-NLS
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to lookup Sleuthkit object backing a SingleEvent.", ex); // NON-NLS
Platform.runLater(() -> {
Notifications.create()
.owner(getScene().getWindow())
.text(Bundle.ListChart_errorMsg())
.showError();
});
}
}
}
}