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.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -344,6 +345,9 @@ public class TimeLineController {
filteredEvents.filterProperty().get(), filteredEvents.filterProperty().get(),
DescriptionLoD.SHORT); DescriptionLoD.SHORT);
historyManager.advance(InitialZoomState); 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 fileID;
private final long epochMillis; private final long epochMillis;
private final String description; private final String description;
/**
* A map from EventType to event ID.
*/
private final Map<EventType, Long> eventTypeMap = new HashMap<>(); 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 * @param epochMillis The timestamp for this event, in millis from the Unix
* epoch. * epoch.
* @param description The full description shared by all the combined events * @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. * @param eventMap A map from EventType to event ID.
*/ */
public CombinedEvent(long epochMillis, String description, long fileID, Map<EventType, Long> eventMap) { public CombinedEvent(long epochMillis, String description, long fileID, Map<EventType, Long> eventMap) {
@ -145,5 +149,4 @@ public class CombinedEvent {
} }
return true; 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))); 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 * Get the tool tip to use for this view when no more specific Tooltip is
* Tooltip is needed. * needed.
* *
* @return The default Tooltip. * @return The default Tooltip.
*/ */
@ -176,8 +176,8 @@ public abstract class AbstractTimelineChart<X, Y, NodeType extends Node, ChartTy
abstract protected Boolean isTickBold(X value); abstract protected Boolean isTickBold(X value);
/** /**
* Apply this view's 'selection effect' to the given node, if * Apply this view's 'selection effect' to the given node, if applied is
* applied is true. If applied is false, remove the affect * true. If applied is false, remove the affect
* *
* @param node The node to apply the 'effect' to * @param node The node to apply the 'effect' to
* @param applied True if the effect should be applied, false if the effect * @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()); 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()); 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; event = null;
} else { } else {
event = controller.getEventsModel().getEventById(item.getRepresentativeEventID()); 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. setOnContextMenuRequested(contextMenuEvent -> {
for (Action action : node.getActions(false)) { //make a new context menu on each request in order to include uptodate tag names and hash sets
if (action == null) { try {
// swing/netbeans uses null action to represent separator in menu EventNode node = EventNode.createEventNode(item.getRepresentativeEventID(), controller.getEventsModel());
menuItems.add(new SeparatorMenuItem()); List<MenuItem> menuItems = new ArrayList<>();
} else {
String actionName = Objects.toString(action.getValue(Action.NAME)); //for each actions avaialable on node, make a menu item.
//for now, suppress properties and tools actions, by ignoring them for (Action action : node.getActions(false)) {
if (Arrays.asList("&Properties", "Tools").contains(actionName) == false) { if (action == null) {
if (action instanceof Presenter.Popup) { // swing/netbeans uses null action to represent separator in menu
/* menuItems.add(new SeparatorMenuItem());
* If the action is really the root of a set } else {
* of actions (eg, tagging). Make a menu String actionName = Objects.toString(action.getValue(Action.NAME));
* that parallels the action's menu. //for now, suppress properties and tools actions, by ignoring them
*/ if (Arrays.asList("&Properties", "Tools").contains(actionName) == false) {
JMenuItem submenu = ((Presenter.Popup) action).getPopupPresenter(); if (action instanceof Presenter.Popup) {
menuItems.add(SwingFXMenuUtils.createFXMenu(submenu)); /*
} else { * If the action is really the root of a
menuItems.add(SwingFXMenuUtils.createFXMenu(new Actions.MenuItem(action, false))); * 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();
});
}
} }
} }
} }