fix modality and placement issues in AddManualEvent dialog

This commit is contained in:
millmanorama 2019-03-14 14:50:20 +01:00
parent c6e1050bbb
commit b02a5f81c8
3 changed files with 92 additions and 89 deletions

View File

@ -488,6 +488,10 @@ public class TimeLineController {
topComponent.requestActive(); topComponent.requestActive();
} }
synchronized public TimeLineTopComponent getTopComponent(){
return topComponent;
}
synchronized public void pushEventTypeZoom(EventTypeZoomLevel typeZoomeLevel) { synchronized public void pushEventTypeZoom(EventTypeZoomLevel typeZoomeLevel) {
ZoomState currentZoom = filteredEvents.zoomStateProperty().get(); ZoomState currentZoom = filteredEvents.zoomStateProperty().get();
if (currentZoom == null) { if (currentZoom == null) {

View File

@ -18,7 +18,7 @@
*/ */
package org.sleuthkit.autopsy.timeline.actions; package org.sleuthkit.autopsy.timeline.actions;
import static java.awt.SystemColor.window; import java.awt.Dialog;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
@ -27,21 +27,20 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.Node; import javafx.scene.Scene;
import javafx.scene.control.Alert; import javafx.scene.control.Alert;
import javafx.scene.control.ButtonBase;
import javafx.scene.control.ButtonType; import javafx.scene.control.ButtonType;
import javafx.scene.control.ChoiceBox; import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ComboBox; import javafx.scene.control.ComboBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.DialogPane; import javafx.scene.control.DialogPane;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.stage.Modality;
import javafx.stage.Window;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import javax.swing.JDialog;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import jfxtras.scene.control.LocalDateTimeTextField; import jfxtras.scene.control.LocalDateTimeTextField;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -56,7 +55,6 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
import org.sleuthkit.autopsy.timeline.FXMLConstructor; import org.sleuthkit.autopsy.timeline.FXMLConstructor;
import org.sleuthkit.autopsy.timeline.PromptDialogManager;
import org.sleuthkit.autopsy.timeline.TimeLineController; import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.datamodel.Blackboard; import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -83,11 +81,7 @@ public class AddManualEvent extends Action {
private static final String MANUAL_CREATION = "Manual Creation"; //NON-NLS private static final String MANUAL_CREATION = "Manual Creation"; //NON-NLS
private static final Image ADD_EVENT_IMAGE = new Image("/org/sleuthkit/autopsy/timeline/images/add.png", 16, 16, true, true, true); // NON-NLS private static final Image ADD_EVENT_IMAGE = new Image("/org/sleuthkit/autopsy/timeline/images/add.png", 16, 16, true, true, true); // NON-NLS
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) // private final Long epochMillis;
private static EventCreationDialog dialog;
private final TimeLineController controller;
/** /**
* Initialize the custom value extractor used by the ValidationSupport for * Initialize the custom value extractor used by the ValidationSupport for
* the LocalDateTimeTextField in the EventCreationDialogPane. * the LocalDateTimeTextField in the EventCreationDialogPane.
@ -121,28 +115,21 @@ public class AddManualEvent extends Action {
*/ */
public AddManualEvent(TimeLineController controller, Long epochMillis) { public AddManualEvent(TimeLineController controller, Long epochMillis) {
super(Bundle.AddManualEvent_text()); super(Bundle.AddManualEvent_text());
this.controller = controller;
setGraphic(new ImageView(ADD_EVENT_IMAGE)); setGraphic(new ImageView(ADD_EVENT_IMAGE));
setLongText(Bundle.AddManualEvent_longText()); setLongText(Bundle.AddManualEvent_longText());
setEventHandler(actionEvent -> { setEventHandler(actionEvent -> SwingUtilities.invokeLater(() -> {
if (dialog == null) { JEventCreationDialog dialog = new JEventCreationDialog(controller, epochMillis, SwingUtilities.windowForComponent(controller.getTopComponent()));
Object source = actionEvent.getSource(); dialog.setVisible(true);
Window owner = null;
if (source instanceof Node) { Platform.runLater(() -> {
owner = ((Node) source).getScene().getWindow(); ManualEventInfo eventInfo = dialog.getManualEventInfo();
} else if (source instanceof MenuItem) { if (eventInfo != null) {
owner = ((MenuItem) source).getParentPopup(); addEvent(controller, eventInfo);
} }
//show the dialog and if it completed normally add the event.
dialog = new EventCreationDialog(controller, epochMillis, owner);
}
dialog.showAndWait().ifPresent(this::addEvent);
dialog = null;
}); });
}));
} }
/** /**
@ -158,7 +145,7 @@ public class AddManualEvent extends Action {
"AddManualEvent.createArtifactFailed=Failed to create artifact for event.", "AddManualEvent.createArtifactFailed=Failed to create artifact for event.",
"AddManualEvent.postArtifactFailed=Failed to post artifact to blackboard." "AddManualEvent.postArtifactFailed=Failed to post artifact to blackboard."
}) })
private void addEvent(ManualEventInfo eventInfo) throws IllegalArgumentException { private void addEvent(TimeLineController controller, ManualEventInfo eventInfo) throws IllegalArgumentException {
SleuthkitCase sleuthkitCase = controller.getEventsModel().getSleuthkitCase(); SleuthkitCase sleuthkitCase = controller.getEventsModel().getSleuthkitCase();
try { try {
@ -189,33 +176,49 @@ public class AddManualEvent extends Action {
} }
} }
/** The dialog that allows the user to enter the event information. */ static private final class JEventCreationDialog extends JDialog {
private static class EventCreationDialog extends Dialog<ManualEventInfo> {
/** Custom DialogPane defined below. */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private final EventCreationDialogPane eventCreationDialogPane; private ManualEventInfo manualEventInfo;
EventCreationDialog(TimeLineController controller, Long epochMillis, Window owner) { JEventCreationDialog(TimeLineController controller, Long epochMillis, java.awt.Window owner) {
this.eventCreationDialogPane = new EventCreationDialogPane(controller, epochMillis); super(owner, Bundle.AddManualEvent_text(), Dialog.ModalityType.DOCUMENT_MODAL);
setTitle(Bundle.AddManualEvent_text()); setIconImages(owner.getIconImages());
setDialogPane(eventCreationDialogPane); setResizable(false);
initOwner(owner); JFXPanel jfxPanel = new JFXPanel();
initModality(Modality.WINDOW_MODAL); add(jfxPanel);
//We can't do these steps until after the dialog is shown or we get an error. // make and configure the JavaFX components.
setOnShown(dialogEvent -> {
Platform.runLater(() -> { Platform.runLater(() -> {
PromptDialogManager.setDialogIcons(this); // Custom DialogPane defined below.
eventCreationDialogPane.installValidation(); EventCreationDialogPane customPane = new EventCreationDialogPane(controller, epochMillis);
//configure ok button to pull ManualEventInfo object.
((ButtonBase) customPane.lookupButton(ButtonType.OK)).setOnAction(event -> {
manualEventInfo = customPane.getManualEventInfo();
dispose();
}); });
//cancel button just closes the dialog
((ButtonBase) customPane.lookupButton(ButtonType.CANCEL)).setOnAction(event -> {
dispose();
}); });
// convert button presses to ManualEventInfo jfxPanel.setScene(new Scene(customPane));
setResultConverter(buttonType customPane.installValidation();
-> (buttonType == ButtonType.OK) SwingUtilities.invokeLater(() -> {
? eventCreationDialogPane.getManualEventInfo() //size and position dialog on EDT
: null pack();
); setLocationRelativeTo(owner);
});
});
}
/**
* Get the MAnualEventInfo combining the user entered data.
*
* @return The ManualEventInfo containing the user entered event info.
*/
ManualEventInfo getManualEventInfo() {
return manualEventInfo;
} }
/** /**
@ -330,4 +333,5 @@ public class AddManualEvent extends Action {
this.time = time; this.time = time;
} }
} }
} }

View File

@ -7,17 +7,18 @@
<?import javafx.scene.control.DialogPane?> <?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?> <?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?> <?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import jfxtras.scene.control.LocalDateTimeTextField?> <?import jfxtras.scene.control.LocalDateTimeTextField?>
<fx:root type="DialogPane" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1"> <fx:root expanded="true" maxHeight="159.0" maxWidth="555.0" minHeight="159.0" minWidth="555.0" prefHeight="159.0" prefWidth="555.0" type="DialogPane" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<buttonTypes>
<ButtonType fx:constant="OK" />
<ButtonType fx:constant="CANCEL" />
</buttonTypes>
<content> <content>
<AnchorPane> <GridPane fx:id="gridPane" hgap="5.0" vgap="5.0">
<children>
<GridPane fx:id="gridPane" hgap="5.0" vgap="5.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="NEVER" maxWidth="93.0" minWidth="10.0" /> <ColumnConstraints hgrow="NEVER" maxWidth="93.0" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="193.0" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" maxWidth="193.0" minWidth="10.0" />
@ -47,11 +48,5 @@
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding> </padding>
</GridPane> </GridPane>
</children>
</AnchorPane>
</content> </content>
<buttonTypes>
<ButtonType fx:constant="OK" />
<ButtonType fx:constant="CANCEL" />
</buttonTypes>
</fx:root> </fx:root>