19 package org.sleuthkit.autopsy.timeline.actions;
 
   21 import java.awt.Dialog;
 
   22 import java.time.Instant;
 
   23 import java.time.LocalDateTime;
 
   24 import java.time.ZoneId;
 
   25 import java.util.Arrays;
 
   26 import java.util.List;
 
   27 import java.util.Objects;
 
   28 import java.util.logging.Level;
 
   29 import javafx.application.Platform;
 
   30 import javafx.embed.swing.JFXPanel;
 
   31 import javafx.fxml.FXML;
 
   32 import javafx.scene.Scene;
 
   33 import javafx.scene.control.Alert;
 
   34 import javafx.scene.control.ButtonBase;
 
   35 import javafx.scene.control.ButtonType;
 
   36 import javafx.scene.control.ChoiceBox;
 
   37 import javafx.scene.control.ComboBox;
 
   38 import javafx.scene.control.DialogPane;
 
   39 import javafx.scene.control.TextField;
 
   40 import javafx.scene.image.Image;
 
   41 import javafx.scene.image.ImageView;
 
   42 import javafx.util.StringConverter;
 
   43 import javax.swing.JDialog;
 
   44 import javax.swing.SwingUtilities;
 
   45 import jfxtras.scene.control.LocalDateTimeTextField;
 
   46 import org.apache.commons.lang3.StringUtils;
 
   47 import org.controlsfx.control.action.Action;
 
   48 import org.controlsfx.control.textfield.TextFields;
 
   49 import org.controlsfx.tools.ValueExtractor;
 
   50 import org.controlsfx.validation.ValidationSupport;
 
   51 import org.controlsfx.validation.Validator;
 
   52 import org.openide.util.NbBundle;
 
   75     "AddManualEvent.text=Add Event",
 
   76     "AddManualEvent.longText=Manually add an event to the timeline."})
 
   80     private static final String MANUAL_CREATION = 
"Manual Creation"; 
 
   81     private static final Image ADD_EVENT_IMAGE = 
new Image(
"/org/sleuthkit/autopsy/timeline/images/add.png", 16, 16, 
true, 
true, 
true); 
 
   88         ValueExtractor.addObservableValueExtractor(LocalDateTimeTextField.class::isInstance,
 
   89                 control -> ((LocalDateTimeTextField) control).localDateTimeProperty());
 
  102         this(controller, null);
 
  115         super(Bundle.AddManualEvent_text());
 
  116         setGraphic(
new ImageView(ADD_EVENT_IMAGE));
 
  117         setLongText(Bundle.AddManualEvent_longText());
 
  119         setEventHandler(actionEvent -> SwingUtilities.invokeLater(() -> {
 
  120             JEventCreationDialog dialog = new JEventCreationDialog(controller, epochMillis, SwingUtilities.windowForComponent(controller.getTopComponent()));
 
  121             dialog.setVisible(true);
 
  137         "AddManualEvent.createArtifactFailed=Failed to create artifact for event.",
 
  138         "AddManualEvent.postArtifactFailed=Failed to post artifact to blackboard."})
 
  145             List<BlackboardAttribute> attributes = Arrays.asList(
 
  147                             TSK_TL_EVENT_TYPE, source,
 
  150                             TSK_DESCRIPTION, source,
 
  153                             TSK_DATETIME, source,
 
  162                 logger.log(Level.SEVERE, 
"Error posting artifact to the blackboard.", ex); 
 
  163                 new Alert(Alert.AlertType.ERROR, Bundle.AddManualEvent_postArtifactFailed(), ButtonType.OK).showAndWait();
 
  166             logger.log(Level.SEVERE, 
"Error creatig new artifact.", ex); 
 
  167             new Alert(Alert.AlertType.ERROR, Bundle.AddManualEvent_createArtifactFailed(), ButtonType.OK).showAndWait();
 
  177         private final JFXPanel jfxPanel = 
new JFXPanel();
 
  180             super(owner, Bundle.AddManualEvent_text(), Dialog.ModalityType.DOCUMENT_MODAL);
 
  181             setIconImages(owner.getIconImages());
 
  186             Platform.runLater(() -> {
 
  190                 ((ButtonBase) customPane.lookupButton(ButtonType.CANCEL)).setOnAction(event -> dispose());
 
  192                 ((ButtonBase) customPane.lookupButton(ButtonType.OK)).setOnAction(event -> {
 
  194                     if (manualEventInfo != null) {
 
  195                         addEvent(controller, manualEventInfo);
 
  200                 jfxPanel.setScene(
new Scene(customPane));
 
  202                 SwingUtilities.invokeLater(() -> {
 
  205                     setLocationRelativeTo(owner);
 
  226             private final ValidationSupport validationSupport = 
new ValidationSupport();
 
  230                 this.controller = controller;
 
  232                 if (epochMillis == null) {
 
  233                     timePicker.setLocalDateTime(LocalDateTime.now());
 
  240             @NbBundle.Messages({
"# {0} - datasource name", 
"# {1} - datasource id",
 
  241                 "AddManualEvent.EventCreationDialogPane.dataSourceStringConverter.template={0} (ID: {1})",
 
  242                 "AddManualEvent.EventCreationDialogPane.initialize.dataSourcesError=Error getting datasources in case."})
 
  244                 assert descriptionTextField != null : 
"fx:id=\"descriptionTextField\" was not injected: check your FXML file 'EventCreationDialog.fxml'.";
 
  246                 timeZoneChooser.getItems().setAll(timeZoneList);
 
  248                 TextFields.bindAutoCompletion(timeZoneChooser.getEditor(), timeZoneList);
 
  250                 dataSourceChooser.setConverter(
new StringConverter<DataSource>() {
 
  252                     public String toString(
DataSource dataSource) {
 
  253                         return Bundle.AddManualEvent_EventCreationDialogPane_dataSourceStringConverter_template(dataSource.
getName(), dataSource.
getId());
 
  258                         throw new UnsupportedOperationException(); 
 
  263                     dataSourceChooser.getSelectionModel().select(0);
 
  265                     logger.log(Level.SEVERE, 
"Error getting datasources in case.", ex);
 
  266                     SwingUtilities.invokeLater(() -> 
MessageNotifyUtil.
Message.
error(Bundle.AddManualEvent_EventCreationDialogPane_initialize_dataSourcesError()));
 
  274                 "AddManualEvent.validation.description=Description is required.",
 
  275                 "AddManualEvent.validation.datetime=Invalid datetime",
 
  276                 "AddManualEvent.validation.timezone=Invalid time zone",})
 
  278                 validationSupport.registerValidator(descriptionTextField, 
false,
 
  279                         Validator.createEmptyValidator(Bundle.AddManualEvent_validation_description()));
 
  280                 validationSupport.registerValidator(timePicker, 
false,
 
  281                         Validator.createPredicateValidator(Objects::nonNull, Bundle.AddManualEvent_validation_description()));
 
  282                 validationSupport.registerValidator(timeZoneChooser, 
false,
 
  283                         Validator.createPredicateValidator((String zone) -> timeZoneList.contains(zone.trim()), Bundle.AddManualEvent_validation_timezone()));
 
  285                 validationSupport.initInitialDecoration();
 
  288                 lookupButton(ButtonType.OK).disableProperty().bind(validationSupport.invalidProperty());
 
  299                 String zone = StringUtils.substringAfter(timeZoneChooser.getValue(), 
")").trim(); 
 
  300                 long toEpochSecond = timePicker.getLocalDateTime().atZone(ZoneId.of(zone)).toEpochSecond();
 
  301                 return new ManualEventInfo(dataSourceChooser.getValue(), descriptionTextField.getText(), toEpochSecond);
 
  316             this.datasource = datasource;
 
  317             this.description = description;
 
JEventCreationDialog(TimeLineController controller, Long epochMillis, java.awt.Window owner)
TextField descriptionTextField
EventCreationDialogPane(TimeLineController controller, Long epochMillis)
void postArtifact(BlackboardArtifact artifact, String moduleName)
AddManualEvent(TimeLineController controller, Long epochMillis)
final TimeLineController controller
Blackboard getBlackboard()
ManualEventInfo(DataSource datasource, String description, long time)
static List< String > createTimeZoneList()
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection< BlackboardAttribute > attributesList)
ManualEventInfo getManualEventInfo()
List< DataSource > getDataSources()
static TimeZone getTimeZone()
LocalDateTimeTextField timePicker
SleuthkitCase getSleuthkitCase()
TimelineEventType USER_CREATED
static ZoneId getTimeZoneID()
static String createTimeZoneString(TimeZone timeZone)
SleuthkitCase getSleuthkitCase()
ComboBox< String > timeZoneChooser
EventsModel getEventsModel()
Examiner getCurrentExaminer()
ChoiceBox< DataSource > dataSourceChooser
synchronized static Logger getLogger(String name)
AddManualEvent(TimeLineController controller)
static void construct(Node node, String fxmlFileName)
void addEvent(TimeLineController controller, ManualEventInfo eventInfo)
final DataSource datasource
static void error(String message)