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();
}
synchronized public TimeLineTopComponent getTopComponent(){
return topComponent;
}
synchronized public void pushEventTypeZoom(EventTypeZoomLevel typeZoomeLevel) {
ZoomState currentZoom = filteredEvents.zoomStateProperty().get();
if (currentZoom == null) {

View File

@ -18,7 +18,7 @@
*/
package org.sleuthkit.autopsy.timeline.actions;
import static java.awt.SystemColor.window;
import java.awt.Dialog;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
@ -27,21 +27,20 @@ import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonBase;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.DialogPane;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Modality;
import javafx.stage.Window;
import javafx.util.StringConverter;
import javax.swing.JDialog;
import javax.swing.SwingUtilities;
import jfxtras.scene.control.LocalDateTimeTextField;
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.TimeZoneUtils;
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
import org.sleuthkit.autopsy.timeline.PromptDialogManager;
import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.datamodel.Blackboard;
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 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 static EventCreationDialog dialog;
private final TimeLineController controller;
// private final Long epochMillis;
/**
* Initialize the custom value extractor used by the ValidationSupport for
* the LocalDateTimeTextField in the EventCreationDialogPane.
@ -121,28 +115,21 @@ public class AddManualEvent extends Action {
*/
public AddManualEvent(TimeLineController controller, Long epochMillis) {
super(Bundle.AddManualEvent_text());
this.controller = controller;
setGraphic(new ImageView(ADD_EVENT_IMAGE));
setLongText(Bundle.AddManualEvent_longText());
setEventHandler(actionEvent -> {
setEventHandler(actionEvent -> SwingUtilities.invokeLater(() -> {
if (dialog == null) {
Object source = actionEvent.getSource();
Window owner = null;
if (source instanceof Node) {
owner = ((Node) source).getScene().getWindow();
} else if (source instanceof MenuItem) {
owner = ((MenuItem) source).getParentPopup();
JEventCreationDialog dialog = new JEventCreationDialog(controller, epochMillis, SwingUtilities.windowForComponent(controller.getTopComponent()));
dialog.setVisible(true);
Platform.runLater(() -> {
ManualEventInfo eventInfo = dialog.getManualEventInfo();
if (eventInfo != null) {
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.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();
try {
@ -189,33 +176,49 @@ public class AddManualEvent extends Action {
}
}
/** The dialog that allows the user to enter the event information. */
private static class EventCreationDialog extends Dialog<ManualEventInfo> {
static private final class JEventCreationDialog extends JDialog {
/** Custom DialogPane defined below. */
private final EventCreationDialogPane eventCreationDialogPane;
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private ManualEventInfo manualEventInfo;
EventCreationDialog(TimeLineController controller, Long epochMillis, Window owner) {
this.eventCreationDialogPane = new EventCreationDialogPane(controller, epochMillis);
setTitle(Bundle.AddManualEvent_text());
setDialogPane(eventCreationDialogPane);
initOwner(owner);
initModality(Modality.WINDOW_MODAL);
JEventCreationDialog(TimeLineController controller, Long epochMillis, java.awt.Window owner) {
super(owner, Bundle.AddManualEvent_text(), Dialog.ModalityType.DOCUMENT_MODAL);
setIconImages(owner.getIconImages());
setResizable(false);
JFXPanel jfxPanel = new JFXPanel();
add(jfxPanel);
//We can't do these steps until after the dialog is shown or we get an error.
setOnShown(dialogEvent -> {
// make and configure the JavaFX components.
Platform.runLater(() -> {
PromptDialogManager.setDialogIcons(this);
eventCreationDialogPane.installValidation();
// Custom DialogPane defined below.
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
setResultConverter(buttonType
-> (buttonType == ButtonType.OK)
? eventCreationDialogPane.getManualEventInfo()
: null
);
jfxPanel.setScene(new Scene(customPane));
customPane.installValidation();
SwingUtilities.invokeLater(() -> {
//size and position dialog on EDT
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;
}
}
}

View File

@ -7,17 +7,18 @@
<?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?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>
<AnchorPane>
<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">
<GridPane fx:id="gridPane" hgap="5.0" vgap="5.0">
<columnConstraints>
<ColumnConstraints hgrow="NEVER" maxWidth="93.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" />
</padding>
</GridPane>
</children>
</AnchorPane>
</content>
<buttonTypes>
<ButtonType fx:constant="OK" />
<ButtonType fx:constant="CANCEL" />
</buttonTypes>
</fx:root>