package ui.gui.widgets; import model.asn1.exceptions.ParseException; import ui.Utils; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.*; import java.awt.event.ActionListener; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.stream.IntStream; import static java.awt.GridBagConstraints.BOTH; import static java.awt.GridBagConstraints.HORIZONTAL; import static javax.swing.JOptionPane.*; /** * Useful utilities for building GUI. */ public class UIUtils { /** * EFFECTS: Create a horizontal actions pane: * ----------------------------------------------------------- * | | Button1 | Button2 | Button3 | ButtonN | * ----------------------------------------------------------- * REQUIRES: buttons != null */ public static JPanel createActionsPane(JButton... buttons) { final JPanel panelAct = new JPanel(); panelAct.setLayout(new GridBagLayout()); IntStream.range(0, buttons.length) .forEach(i -> panelAct.add(buttons[i], new GCBuilder().gridXY(i + 1, 1).fill(HORIZONTAL).build())); panelAct.add(new JPanel(), new GCBuilder().expandXY().fill(BOTH).build()); return panelAct; } /** * EFFECTS: Show / hide default text for a card layout container. * MODIFIES: cardLayoutPanel * REQUIRES: cardLayoutPanel must have a card layout; it must have CardContent and CardDefault cards. */ public static void setContentVisible(Container cardLayoutPanel, boolean showContent) { switchTo(cardLayoutPanel, showContent ? "CardContent" : "CardDefault"); } /** * EFFECTS: Switch to the card for a card layout panel. * MODIFIES: cardLayoutPanel * REQUIRES: cardLayoutPanel must have a card layout; it must have "card" card. */ public static void switchTo(Container cardLayoutPanel, String card) { ((CardLayout) cardLayoutPanel.getLayout()).show(cardLayoutPanel, card); } /** * EFFECTS: Show an error message based on {@link Throwable#getMessage()} * REQUIRES: component must have a frame. */ public static void alert(Component component, String title, Throwable e) { alert(component, title, e.getMessage()); } /** * EFFECTS: Show an error message. * REQUIRES: component must have a frame. */ public static void alert(Component component, String title, String message) { showMessageDialog(getFrameForComponent(component), message, title, ERROR_MESSAGE); } /** * EFFECTS: Show a file chooser with the given filter title and list of extensions. Starting from cwd. * Return null if cancelled. */ public static Path chooseFile(Component component, String filterTitle, String... extensions) { final JFileChooser fc = new JFileChooser(); fc.setFileFilter(new FileNameExtensionFilter(filterTitle, extensions)); fc.setCurrentDirectory(Paths.get("").toAbsolutePath().toFile()); if (fc.showOpenDialog(getFrameForComponent(component)) == JFileChooser.APPROVE_OPTION) { return fc.getSelectedFile().toPath(); } return null; } /** * EFFECTS: Create a JPanel with CardLayout that has CardDefault set to component and CardContent set to a JLabel * with the default text. */ public static JPanel defView(Component component, String defaultText) { final JPanel panel = new JPanel(); panel.setLayout(new CardLayout(0, 0)); JLabel labelDefault = new JLabel(defaultText); labelDefault.setHorizontalAlignment(0); panel.add(labelDefault, "CardDefault"); panel.add(component, "CardContent"); return panel; } /** * EFFECTS: Create a JScrollPane-wrapped JTable. * MODIFIES: table */ public static JScrollPane scrTbl(JTable table) { final JScrollPane scrollPane = new JScrollPane(); table.setFillsViewportHeight(true); scrollPane.setViewportView(table); return scrollPane; } /** * EFFECTS: Parse the given path and automatically determine if it is a DER binary or a PEM. Automatically decode * PEM. * Throws {@link IOException} if it cannot be read. * Throws {@link ParseException} if the PEM is invalid. */ public static Byte[] openDERorPEM(Path path, String tag) throws IOException, ParseException { final InputStream fd = Files.newInputStream(path, StandardOpenOption.READ); Byte[] bs = Utils.byteToByte(fd.readAllBytes()); fd.close(); if (bs.length < 1) { throw new ParseException("Invalid file: too short"); } if (bs[0] == '-') { bs = Utils.parsePEM(bs, tag); } return bs; } /** * EFFECTS: Create a button with the given label and click listener. */ public static JButton btn(String string, ActionListener onClick) { final JButton btn = new JButton(string); btn.addActionListener(onClick); return btn; } /** * EFFECTS: Create a button with the given label, mnemonic, and click listener. */ public static JButton btn(String string, char m, ActionListener onClick) { final JButton btn = new JButton(string); btn.setMnemonic(m); btn.setDisplayedMnemonicIndex(0); btn.addActionListener(onClick); return btn; } /** * EFFECTS: Create a button with the given label, mnemonic, icon, and click listener. */ public static JButton btn(String string, String icon, ActionListener onClick) { final JButton btn = new JButton(string, new ImageIcon(UIUtils.class.getResource("/" + icon))); btn.addActionListener(onClick); return btn; } }