/*
* Autopsy Forensic Browser
*
* Copyright 2011-2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule;
import org.openide.util.NbBundle;
import java.awt.*;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.PathValidator;
/**
* The JPanel for the first page of the new case wizard.
*/
final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
private final JFileChooser fileChooser = new JFileChooser();
private final NewCaseWizardPanel1 wizPanel;
/**
* Constructs the JPanel for the first page of the new case wizard.
*
* @param wizPanel The wizard panmel that owns this panel.
*/
NewCaseVisualPanel1(NewCaseWizardPanel1 wizPanel) {
this.wizPanel = wizPanel;
initComponents();
TextFieldListener listener = new TextFieldListener();
caseNameTextField.getDocument().addDocumentListener(listener);
caseParentDirTextField.getDocument().addDocumentListener(listener);
caseParentDirWarningLabel.setVisible(false);
}
/**
* Should be called by the readSettings() of the wizard panel that owns this
* UI panel so that this panel can read settings for each invocation of the
* wizard as well.
*/
void readSettings() {
caseNameTextField.setText("");
if (UserPreferences.getIsMultiUserModeEnabled()) {
multiUserCaseRadioButton.setEnabled(true);
multiUserCaseRadioButton.setSelected(true);
} else {
multiUserCaseRadioButton.setEnabled(false);
singleUserCaseRadioButton.setSelected(true);
}
validateSettings();
}
/**
* Returns the name of the this panel. This name will be shown on the left
* panel of the "New Case" wizard panel.
*
* @return name the name of this panel
*/
@Override
public String getName() {
return NbBundle.getMessage(this.getClass(), "NewCaseVisualPanel1.getName.text");
}
/**
* Gets the case name that the user types on the case name text field.
*
* @return caseName the case name from the case name text field
*/
String getCaseName() {
return this.caseNameTextField.getText();
}
/**
* Allows the the wizard panel that owns this UI panel to set the base case
* directory to a persisted vlaue.
*
* @param caseParentDir The persisted path to the base case directory.
*/
void setCaseParentDir(String caseParentDir) {
caseParentDirTextField.setText(caseParentDir);
validateSettings();
}
/**
* Gets the base directory that the user typed on the base directory text
* field. Will add file separator if it was not added.
*
* @return baseDirectory the base directory from the case dir text field
*/
String getCaseParentDir() {
String parentDir = this.caseParentDirTextField.getText();
if (parentDir.endsWith(File.separator) == false) {
parentDir = parentDir + File.separator;
}
return parentDir;
}
/**
* Gets the case type.
*
* @return CaseType as set via radio buttons
*/
CaseType getCaseType() {
CaseType value = CaseType.SINGLE_USER_CASE;
if (singleUserCaseRadioButton.isSelected()) {
value = CaseType.SINGLE_USER_CASE;
} else if (multiUserCaseRadioButton.isSelected()) {
value = CaseType.MULTI_USER_CASE;
}
return value;
}
/**
* Called when the user interacts with a child UI component of this panel,
* this method notifies the wizard panel that owns this panel and then
* validates the user's settings.
*/
private void handleUpdate() {
wizPanel.fireChangeEvent();
validateSettings();
}
/**
* Does validation of the current settings and enables or disables the
* "Next" button of the wizard panel that owns this panel.
*/
private void validateSettings() {
/**
* Check the base case directory for the selected case type and show a
* warning if it is a dubious choice.
*/
caseParentDirWarningLabel.setVisible(false);
String parentDir = getCaseParentDir();
if (!PathValidator.isValid(parentDir, getCaseType())) {
caseParentDirWarningLabel.setVisible(true);
caseParentDirWarningLabel.setText(NbBundle.getMessage(this.getClass(), "NewCaseVisualPanel1.CaseFolderOnCDriveError.text"));
}
/**
* Enable the "Next" button for the wizard if there is text entered for
* the case name and base case directory. Also make sure that multi-user
* cases are enabled if the multi-user case radio button is selected.
*/
String caseName = getCaseName();
if (!caseName.equals("") && !parentDir.equals("")) {
caseDirTextField.setText(parentDir + caseName);
wizPanel.setIsFinish(true);
} else {
caseDirTextField.setText("");
wizPanel.setIsFinish(false);
}
}
/**
* Handles validation when the user provides input to text field components
* of this panel.
*/
private class TextFieldListener implements DocumentListener {
@Override
public void insertUpdate(DocumentEvent e) {
handleUpdate();
}
@Override
public void removeUpdate(DocumentEvent e) {
handleUpdate();
}
@Override
public void changedUpdate(DocumentEvent e) {
handleUpdate();
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
caseTypeButtonGroup = new javax.swing.ButtonGroup();
jLabel1 = new javax.swing.JLabel();
caseNameLabel = new javax.swing.JLabel();
caseDirLabel = new javax.swing.JLabel();
caseNameTextField = new javax.swing.JTextField();
caseParentDirTextField = new javax.swing.JTextField();
caseDirBrowseButton = new javax.swing.JButton();
jLabel2 = new javax.swing.JLabel();
caseDirTextField = new javax.swing.JTextField();
singleUserCaseRadioButton = new javax.swing.JRadioButton();
multiUserCaseRadioButton = new javax.swing.JRadioButton();
caseParentDirWarningLabel = new javax.swing.JLabel();
caseTypeLabel = new javax.swing.JLabel();
jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD, 14));
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.jLabel1.text_1")); // NOI18N
caseNameLabel.setFont(caseNameLabel.getFont().deriveFont(caseNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(caseNameLabel, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseNameLabel.text_1")); // NOI18N
caseDirLabel.setFont(caseDirLabel.getFont().deriveFont(caseDirLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(caseDirLabel, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseDirLabel.text")); // NOI18N
caseNameTextField.setFont(caseNameTextField.getFont().deriveFont(caseNameTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseNameTextField.setText(org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseNameTextField.text_1")); // NOI18N
caseParentDirTextField.setFont(caseParentDirTextField.getFont().deriveFont(caseParentDirTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseParentDirTextField.setText(org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseParentDirTextField.text")); // NOI18N
caseDirBrowseButton.setFont(caseDirBrowseButton.getFont().deriveFont(caseDirBrowseButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(caseDirBrowseButton, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseDirBrowseButton.text")); // NOI18N
caseDirBrowseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
caseDirBrowseButtonActionPerformed(evt);
}
});
jLabel2.setFont(jLabel2.getFont().deriveFont(jLabel2.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.jLabel2.text_1")); // NOI18N
caseDirTextField.setEditable(false);
caseDirTextField.setFont(caseDirTextField.getFont().deriveFont(caseDirTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseDirTextField.setText(org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseDirTextField.text_1")); // NOI18N
caseTypeButtonGroup.add(singleUserCaseRadioButton);
singleUserCaseRadioButton.setFont(singleUserCaseRadioButton.getFont().deriveFont(singleUserCaseRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(singleUserCaseRadioButton, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.singleUserCaseRadioButton.text")); // NOI18N
singleUserCaseRadioButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
singleUserCaseRadioButtonActionPerformed(evt);
}
});
caseTypeButtonGroup.add(multiUserCaseRadioButton);
multiUserCaseRadioButton.setFont(multiUserCaseRadioButton.getFont().deriveFont(multiUserCaseRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(multiUserCaseRadioButton, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.multiUserCaseRadioButton.text")); // NOI18N
multiUserCaseRadioButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
multiUserCaseRadioButtonActionPerformed(evt);
}
});
caseParentDirWarningLabel.setFont(caseParentDirWarningLabel.getFont().deriveFont(caseParentDirWarningLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseParentDirWarningLabel.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(caseParentDirWarningLabel, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseParentDirWarningLabel.text")); // NOI18N
caseTypeLabel.setFont(caseTypeLabel.getFont().deriveFont(caseTypeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(caseTypeLabel, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseTypeLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(caseDirTextField, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(0, 227, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(caseNameLabel)
.addGap(26, 26, 26)
.addComponent(caseNameTextField))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(caseDirLabel)
.addComponent(caseTypeLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(singleUserCaseRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(multiUserCaseRadioButton)
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(caseParentDirTextField))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(caseDirBrowseButton)))
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addComponent(caseParentDirWarningLabel)
.addGap(0, 0, Short.MAX_VALUE))))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(31, 31, 31)
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(caseNameLabel)
.addComponent(caseNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(caseDirLabel)
.addComponent(caseParentDirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(caseDirBrowseButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(singleUserCaseRadioButton)
.addComponent(multiUserCaseRadioButton)
.addComponent(caseTypeLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(caseDirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(27, 27, 27)
.addComponent(caseParentDirWarningLabel)
.addContainerGap(21, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
/**
* The action when the Browse button is pressed. The browse button will pop
* up the file chooser window to choose where the user wants to save the
* case directory.
*
* @param evt the action event
*/
private void caseDirBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_caseDirBrowseButtonActionPerformed
fileChooser.setDragEnabled(false);
if (!caseParentDirTextField.getText().trim().equals("")) {
fileChooser.setCurrentDirectory(new File(caseParentDirTextField.getText()));
}
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int choice = fileChooser.showDialog((Component) evt.getSource(), NbBundle.getMessage(this.getClass(),
"NewCaseVisualPanel1.caseDirBrowse.selectButton.text"));
if (JFileChooser.APPROVE_OPTION == choice) {
String path = fileChooser.getSelectedFile().getPath();
caseParentDirTextField.setText(path);
}
}//GEN-LAST:event_caseDirBrowseButtonActionPerformed
private void singleUserCaseRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_singleUserCaseRadioButtonActionPerformed
handleUpdate();
}//GEN-LAST:event_singleUserCaseRadioButtonActionPerformed
private void multiUserCaseRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_multiUserCaseRadioButtonActionPerformed
handleUpdate();
}//GEN-LAST:event_multiUserCaseRadioButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton caseDirBrowseButton;
private javax.swing.JLabel caseDirLabel;
private javax.swing.JTextField caseDirTextField;
private javax.swing.JLabel caseNameLabel;
private javax.swing.JTextField caseNameTextField;
private javax.swing.JTextField caseParentDirTextField;
private javax.swing.JLabel caseParentDirWarningLabel;
private javax.swing.ButtonGroup caseTypeButtonGroup;
private javax.swing.JLabel caseTypeLabel;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JRadioButton multiUserCaseRadioButton;
private javax.swing.JRadioButton singleUserCaseRadioButton;
// End of variables declaration//GEN-END:variables
/**
* Gives notification that there was an insert into the document. The range
* given by the DocumentEvent bounds the freshly inserted region.
*
* @param e the document event
*/
@Override
public void insertUpdate(DocumentEvent e) {
this.wizPanel.fireChangeEvent();
updateUI(e);
}
/**
* Gives notification that a portion of the document has been removed. The
* range is given in terms of what the view last saw (that is, before
* updating sticky positions).
*
* @param e the document event
*/
@Override
public void removeUpdate(DocumentEvent e) {
this.wizPanel.fireChangeEvent();
updateUI(e);
}
/**
* Gives notification that an attribute or set of attributes changed.
*
* @param e the document event
*/
@Override
public void changedUpdate(DocumentEvent e) {
this.wizPanel.fireChangeEvent();
updateUI(e);
}
/**
* The "listener" that listens when the fields in this form are updated.
* This method is used to determine when to enable / disable the "Finish"
* button.
*
* @param e the document event
*/
public void updateUI(DocumentEvent e) {
String caseName = getCaseName();
String parentDir = getCaseParentDir();
if (!caseName.equals("") && !parentDir.equals("")) {
caseDirTextField.setText(parentDir + caseName);
wizPanel.setIsFinish(true);
} else {
caseDirTextField.setText("");
wizPanel.setIsFinish(false);
}
}
}