Skip to content

Commit

Permalink
Improved UI layout and navigation.
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewlalis committed Apr 7, 2022
1 parent 25a3f4a commit babfeba
Show file tree
Hide file tree
Showing 27 changed files with 838 additions and 307 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package nl.andrewl.email_indexer.browser;

import nl.andrewl.email_indexer.browser.control.DatasetOpenAction;
import nl.andrewl.email_indexer.browser.control.ExportDatasetAction;
import nl.andrewl.email_indexer.browser.control.GenerateDatasetAction;
import nl.andrewl.email_indexer.browser.control.*;
import nl.andrewl.email_indexer.browser.control.email.HideAction;
import nl.andrewl.email_indexer.browser.control.email.HideAllByAuthorAction;
import nl.andrewl.email_indexer.browser.control.email.HideAllByBodyAction;
import nl.andrewl.email_indexer.browser.control.email.ShowAction;
import nl.andrewl.email_indexer.browser.email.EmailViewPanel;
import nl.andrewl.email_indexer.data.EmailDataset;

Expand All @@ -19,11 +21,10 @@ public class EmailDatasetBrowser extends JFrame {
public EmailDatasetBrowser () {
super("Email Dataset Browser");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setJMenuBar(buildMenu());

this.emailViewPanel = new EmailViewPanel();
this.searchPanel = new SearchPanel(emailViewPanel);
this.setContentPane(buildUi());
this.setJMenuBar(buildMenu());
this.setPreferredSize(new Dimension(1000, 600));
this.pack();
this.setLocationRelativeTo(null);
Expand Down Expand Up @@ -66,9 +67,16 @@ private JMenuBar buildMenu() {
fileMenu.add(new JMenuItem(new DatasetOpenAction(this)));
fileMenu.add(new JMenuItem(new GenerateDatasetAction(this)));
fileMenu.add(new JMenuItem(new ExportDatasetAction(this)));

menuBar.add(fileMenu);

JMenu filterMenu = new JMenu("Filter");
filterMenu.add(new JMenuItem(new HideAction(emailViewPanel)));
filterMenu.add(new JMenuItem(new ShowAction(emailViewPanel)));
filterMenu.add(new JMenuItem(new HideAllByAuthorAction(emailViewPanel)));
filterMenu.add(new JMenuItem(new HideAllByBodyAction(emailViewPanel)));

menuBar.add(filterMenu);

return menuBar;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package nl.andrewl.email_indexer.browser.control;

import javax.swing.filechooser.FileFilter;
import java.io.File;

/**
* A file filter that only allows users to select directories.
*/
public class DirectoryFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
return f.isDirectory();
}

@Override
public String getDescription() {
return "Directories";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,6 @@ public void actionPerformed(ActionEvent e) {
inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.PAGE_AXIS));
JTextField domainField = new JTextField(0);
JTextField listField = new JTextField(0);
JTextField dirField = new JTextField(0);
dirField.setEditable(false);
JButton setDirButton = new JButton("Download to");
setDirButton.addActionListener(event -> {
JFileChooser fc = new JFileChooser(Path.of(".").toFile());
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int result = fc.showOpenDialog(dialog);
if (result == JFileChooser.APPROVE_OPTION) {
Path dir = fc.getSelectedFile().toPath();
dirField.setText(dir.toAbsolutePath().toString());
}
});

JPanel domainPanel = new JPanel(new BorderLayout());
domainPanel.add(new JLabel("Domain"), BorderLayout.WEST);
domainPanel.add(domainField, BorderLayout.CENTER);
Expand All @@ -47,10 +34,8 @@ public void actionPerformed(ActionEvent e) {
listPanel.add(new JLabel("List"), BorderLayout.WEST);
listPanel.add(listField, BorderLayout.CENTER);
inputPanel.add(listPanel);
JPanel dirPanel = new JPanel(new BorderLayout());
dirPanel.add(dirField, BorderLayout.CENTER);
dirPanel.add(setDirButton, BorderLayout.EAST);
inputPanel.add(dirPanel);
PathSelectField dirField = PathSelectField.directorySelectField();
inputPanel.add(dirField);

p.add(inputPanel, BorderLayout.CENTER);

Expand All @@ -60,10 +45,10 @@ public void actionPerformed(ActionEvent e) {
JButton downloadButton = new JButton("Download");
downloadButton.addActionListener(event -> {
ApacheMailingListDownloader downloader = new ApacheMailingListDownloader(domainField.getText(), listField.getText());
Path outputDir = Path.of(dirField.getText());
Path outputDir = dirField.getSelectedPath();
domainField.setEditable(false);
listField.setEditable(false);
setDirButton.setEnabled(false);
dirField.setEnabled(false);
downloadButton.setEnabled(false);
cancelButton.setEnabled(false);
dialog.setTitle("Downloading...");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nl.andrewl.email_indexer.browser.control;

import nl.andrewl.email_indexer.browser.EmailDatasetBrowser;
import nl.andrewl.email_indexer.data.util.FileUtils;
import nl.andrewl.email_indexer.gen.EmailDatasetGenerator;

import javax.swing.*;
Expand Down Expand Up @@ -33,63 +34,39 @@ public void actionPerformed(ActionEvent e) {
inputPanel.add(items.getKey());
JList<Path> mboxDirsList = items.getValue();

JPanel datasetDirPanel = new JPanel(new BorderLayout());
JTextField datasetDirField = new JTextField(0);
datasetDirField.setEditable(false);
JButton datasetDirButton = new JButton("Generate to");
datasetDirButton.addActionListener(event -> {
JFileChooser fc = new JFileChooser(Path.of(".").toFile());
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int result = fc.showSaveDialog(browser);
if (result == JFileChooser.APPROVE_OPTION) {
Path dsDir = fc.getSelectedFile().toPath();
datasetDirField.setText(dsDir.toAbsolutePath().toString());
}
});
datasetDirPanel.add(datasetDirButton, BorderLayout.EAST);
datasetDirPanel.add(datasetDirField, BorderLayout.CENTER);
inputPanel.add(datasetDirPanel);

PathSelectField datasetDirField = PathSelectField.directorySelectField();
inputPanel.add(datasetDirField);
p.add(inputPanel, BorderLayout.CENTER);

JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(event -> dialog.dispose());
JButton generateButton = new JButton("Generate");
generateButton.addActionListener(event -> {
int size = mboxDirsList.getModel().getSize();
if (size < 1) {
if (!validateDialog(dialog, mboxDirsList, datasetDirField)) return;
Collection<Path> paths = new ArrayList<>();
for (int i = 0; i < mboxDirsList.getModel().getSize(); i++) {
paths.add(mboxDirsList.getModel().getElementAt(i));
}
Path dsDir = datasetDirField.getSelectedPath();
SwingUtils.setAllButtonsEnabled(dialog, false);
datasetDirField.setEnabled(false);
dialog.setTitle("Generating...");
try {
new EmailDatasetGenerator().generate(paths, dsDir)
.thenRun(() -> {
JOptionPane.showMessageDialog(dialog, "Dataset generated!");
dialog.dispose();
});
} catch (Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(
dialog,
"No MBox directories have been added.",
"No MBox Directories",
JOptionPane.WARNING_MESSAGE
"An error occurred while generating the dataset:\n" + ex.getMessage(),
"Error",
JOptionPane.ERROR_MESSAGE
);
} else {
Collection<Path> paths = new ArrayList<>();
for (int i = 0; i < size; i++) {
paths.add(mboxDirsList.getModel().getElementAt(i));
}
Path dsDir = Path.of(datasetDirField.getText());
generateButton.setEnabled(false);
cancelButton.setEnabled(false);
dialog.setTitle("Generating...");
try {
new EmailDatasetGenerator().generate(paths, dsDir)
.thenRun(() -> {
JOptionPane.showMessageDialog(dialog, "Dataset generated!");
dialog.dispose();
});
} catch (Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(
dialog,
"An error occurred while generating the dataset:\n" + ex.getMessage(),
"Error",
JOptionPane.ERROR_MESSAGE
);
dialog.dispose();
}
dialog.dispose();
}
});
buttonPanel.add(generateButton);
Expand All @@ -112,7 +89,9 @@ private Map.Entry<JPanel, JList<Path>> buildMBoxDirsPanel(JDialog owner) {
JButton addMboxDirButton = new JButton("Add Mbox Directory");
addMboxDirButton.addActionListener(event -> {
JFileChooser fc = new JFileChooser(Path.of(".").toFile());
fc.setFileFilter(new DirectoryFileFilter());
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.setAcceptAllFileFilterUsed(false);
int result = fc.showOpenDialog(browser);
if (result == JFileChooser.APPROVE_OPTION) {
Path mboxDir = fc.getSelectedFile().toPath();
Expand Down Expand Up @@ -149,4 +128,27 @@ private Map.Entry<JPanel, JList<Path>> buildMBoxDirsPanel(JDialog owner) {

return new AbstractMap.SimpleEntry<>(mboxDirsPanel, mboxDirsList);
}

private boolean validateDialog(JDialog dialog, JList<Path> mboxDirsList, PathSelectField datasetDirField) {
if (mboxDirsList.getModel().getSize() < 1) {
JOptionPane.showMessageDialog(
dialog,
"No MBox directories have been added.",
"No MBox Directories",
JOptionPane.WARNING_MESSAGE
);
return false;
}
Path datasetDir = datasetDirField.getSelectedPath();
if (datasetDir == null || !Files.isDirectory(datasetDir) || !FileUtils.isDirEmpty(datasetDir)) {
JOptionPane.showMessageDialog(
dialog,
"You must select an empty directory to generate the dataset in.",
"Invalid Dataset Directory",
JOptionPane.WARNING_MESSAGE
);
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package nl.andrewl.email_indexer.browser.control;

import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.nio.file.Path;

public class PathSelectField extends JPanel {
private final JTextField pathField;
private final JButton selectPathButton;
private final MouseListener pathFieldMouseListener;

private final int fileSelectionMode;
private final boolean acceptAll;
private final FileFilter fileFilter;
private Path selectedPath = null;

public PathSelectField(int fileSelectionMode, boolean acceptAll, FileFilter filter) {
super(new BorderLayout());
this.fileSelectionMode = fileSelectionMode;
this.acceptAll = acceptAll;
this.fileFilter = filter;

pathField = new JTextField(0);
pathField.setMinimumSize(new Dimension(100, 30));
pathField.setEditable(false);
add(pathField, BorderLayout.CENTER);

selectPathButton = new JButton("Select file...");
selectPathButton.setMinimumSize(new Dimension(50, 30));
add(selectPathButton, BorderLayout.EAST);

selectPathButton.addActionListener(e -> selectFile());
pathFieldMouseListener = new MouseInputAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2 && e.getButton() == 1) {
selectFile();
}
}
};
pathField.addMouseListener(pathFieldMouseListener);
}

public static PathSelectField directorySelectField() {
return new PathSelectField(JFileChooser.DIRECTORIES_ONLY, false, new DirectoryFileFilter());
}

public static PathSelectField fileTypeSelectField(String extension, String name) {
return new PathSelectField(JFileChooser.FILES_ONLY, false, new FileNameExtensionFilter(name, extension));
}

public void setEnabled(boolean enabled) {
selectPathButton.setEnabled(enabled);
if (enabled) {
pathField.addMouseListener(pathFieldMouseListener);
} else {
pathField.removeMouseListener(pathFieldMouseListener);
}
}

private void selectFile() {
JFileChooser fc = new JFileChooser(selectedPath == null ? Path.of(".").toFile() : selectedPath.toFile());
fc.setFileSelectionMode(fileSelectionMode);
fc.setFileFilter(fileFilter);
fc.setAcceptAllFileFilterUsed(acceptAll);
int result = fc.showDialog(this, "Select");
if (result == JFileChooser.APPROVE_OPTION) {
setSelectPath(fc.getSelectedFile().toPath());
}
}

public void setSelectPath(Path p) {
selectedPath = p;
String text = p == null ? null : p.toAbsolutePath().toString();
pathField.setText(text);
}

public Path getSelectedPath() {
return selectedPath;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package nl.andrewl.email_indexer.browser.control;

import javax.swing.*;
import java.awt.*;
import java.util.Random;

public final class SwingUtils {
public static final Random random = new Random();
private SwingUtils() {}

public static void setAllButtonsEnabled(Container c, boolean enabled) {
for (var component : c.getComponents()) {
if (component instanceof JButton button) {
button.setEnabled(enabled);
} else if (component instanceof Container nested) {
setAllButtonsEnabled(nested, enabled);
}
}
}

@SuppressWarnings("unchecked")
public static <T extends Component> T findFirstInstance(Container c, Class<T> type) {
for (var component: c.getComponents()) {
if (component.getClass().equals(type)) {
return (T) component;
} else if (component instanceof Container nested) {
T result = findFirstInstance(nested, type);
if (result != null) return result;
}
}
return null;
}

public static Color getColor(String text) {
random.setSeed(text.hashCode());
float hue = random.nextFloat();
float saturation = random.nextFloat() / 4f + 0.75f;
float luminance = 0.9f;
return Color.getHSBColor(hue, saturation, luminance);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package nl.andrewl.email_indexer.browser.control.email;

import nl.andrewl.email_indexer.browser.email.EmailViewListener;
import nl.andrewl.email_indexer.browser.email.EmailViewPanel;
import nl.andrewl.email_indexer.data.EmailEntry;

import javax.swing.*;

public abstract class EmailAction extends AbstractAction implements EmailViewListener {
protected final EmailViewPanel emailViewPanel;

protected EmailAction(String name, EmailViewPanel emailViewPanel) {
super(name);
this.emailViewPanel = emailViewPanel;
emailViewPanel.addListener(this);
}

@Override
public void emailUpdated(EmailEntry email) {
setEnabled(email != null && shouldBeEnabled(email));
}

protected abstract boolean shouldBeEnabled(EmailEntry email);
}
Loading

0 comments on commit babfeba

Please sign in to comment.