Example #1
0
  /** Creates the GUI. */
  public void majorLayout() {
    //
    // Setup Menu
    //
    JMenuBar menuBar = new JMenuBar();
    JMenu file = new JMenu(ResourceHandler.getMessage("menu.file"));
    file.setMnemonic(ResourceHandler.getAcceleratorKey("menu.file"));

    file.add(exitMenuItem = new JMenuItem(ResourceHandler.getMessage("menu.exit")));
    exitMenuItem.setMnemonic(ResourceHandler.getAcceleratorKey("menu.exit"));
    exitMenuItem.addActionListener(this);
    menuBar.add(file);

    JMenu edit = new JMenu(ResourceHandler.getMessage("menu.edit"));
    edit.setMnemonic(ResourceHandler.getAcceleratorKey("menu.edit"));

    edit.add(optionMenuItem = new JMenuItem(ResourceHandler.getMessage("menu.option")));
    optionMenuItem.setMnemonic(ResourceHandler.getAcceleratorKey("menu.option"));
    optionMenuItem.addActionListener(this);
    menuBar.add(edit);

    JMenu help = new JMenu(ResourceHandler.getMessage("menu.help"));
    help.setMnemonic(ResourceHandler.getAcceleratorKey("menu.help"));

    help.add(helpMenuItem = new JMenuItem(ResourceHandler.getMessage("menu.help")));
    helpMenuItem.setMnemonic(ResourceHandler.getAcceleratorKey("menu.help"));

    help.add(new JSeparator());
    help.add(aboutMenuItem = new JMenuItem(ResourceHandler.getMessage("menu.about")));
    aboutMenuItem.setMnemonic(ResourceHandler.getAcceleratorKey("menu.about"));
    helpMenuItem.addActionListener(this);
    aboutMenuItem.addActionListener(this);
    menuBar.add(help);

    setJMenuBar(menuBar);

    //
    // Setup main GUI
    //

    dirLabel = new JLabel(ResourceHandler.getMessage("converter_gui.lablel0"));
    dirTF = new JTextField();
    dirBttn = new JButton(ResourceHandler.getMessage("button.browse.dir"));
    dirBttn.setMnemonic(ResourceHandler.getAcceleratorKey("button.browse.dir"));

    matchingLabel = new JLabel(ResourceHandler.getMessage("converter_gui.lablel1"));
    matchingTF = new JTextField(ResourceHandler.getMessage("converter_gui.lablel2"));
    recursiveCheckBox = new JCheckBox(ResourceHandler.getMessage("converter_gui.lablel3"));
    recursiveCheckBox.setMnemonic(ResourceHandler.getAcceleratorKey("converter_gui.lablel3"));

    backupLabel = new JLabel(ResourceHandler.getMessage("converter_gui.lablel5"));
    backupTF = new JTextField();
    backupBttn = new JButton(ResourceHandler.getMessage("button.browse.backup"));
    backupBttn.setMnemonic(ResourceHandler.getAcceleratorKey("button.browse.backup"));

    templateLabel = new JLabel(ResourceHandler.getMessage("converter_gui.lablel7"));
    templateCh = new TemplateFileChoice();

    staticVersioningLabel = new JLabel(ResourceHandler.getMessage("static.versioning.label"));
    String version = System.getProperty("java.version");
    if (version.indexOf("-") > 0) {
      version = version.substring(0, version.indexOf("-"));
    }
    int dotIndex = version.indexOf(".");
    dotIndex = version.indexOf(".", dotIndex + 1);
    String familyVersion = version.substring(0, dotIndex);

    MessageFormat formatter =
        new MessageFormat(ResourceHandler.getMessage("static.versioning.radio.button"));
    staticVersioningRadioButton = new JRadioButton(formatter.format(new Object[] {version}));
    staticVersioningRadioButton.setMnemonic(
        ResourceHandler.getAcceleratorKey("static.versioning.radio.button"));

    formatter = new MessageFormat(ResourceHandler.getMessage("dynamic.versioning.radio.button"));
    dynamicVersioningRadioButton = new JRadioButton(formatter.format(new Object[] {familyVersion}));
    dynamicVersioningRadioButton.setMnemonic(
        ResourceHandler.getAcceleratorKey("dynamic.versioning.radio.button"));

    staticVersioningTextArea = new JTextArea(ResourceHandler.getMessage("static.versioning.text"));

    formatter = new MessageFormat(ResourceHandler.getMessage("dynamic.versioning.text"));
    dynamicVersioningTextArea = new JTextArea(formatter.format(new Object[] {familyVersion}));

    ButtonGroup versioningButtonGroup = new ButtonGroup();
    versioningButtonGroup.add(staticVersioningRadioButton);
    versioningButtonGroup.add(dynamicVersioningRadioButton);

    runBttn = new JButton(ResourceHandler.getMessage("button.convert"));
    runBttn.setMnemonic(ResourceHandler.getAcceleratorKey("button.convert"));

    recursiveCheckBox.setOpaque(false);
    staticVersioningRadioButton.setOpaque(false);
    dynamicVersioningRadioButton.setOpaque(false);

    staticVersioningTextArea.setEditable(false);
    staticVersioningTextArea.setLineWrap(true);
    staticVersioningTextArea.setWrapStyleWord(true);
    dynamicVersioningTextArea.setEditable(false);
    dynamicVersioningTextArea.setLineWrap(true);
    dynamicVersioningTextArea.setWrapStyleWord(true);

    staticVersioningPanel.setLayout(new BorderLayout());
    staticVersioningPanel.add(staticVersioningTextArea, "Center");
    staticVersioningPanel.setBorder(new LineBorder(Color.black));

    dynamicVersioningPanel.setLayout(new BorderLayout());
    dynamicVersioningPanel.add(dynamicVersioningTextArea, "Center");
    dynamicVersioningPanel.setBorder(new LineBorder(Color.black));

    if (converter.isStaticVersioning()) {
      staticVersioningRadioButton.setSelected(true);
    } else {
      dynamicVersioningRadioButton.setSelected(true);
    }

    addListeners();

    final int buf = 10, // Buffer (between components and form)
        sp = 10, // Space between components
        vsp = 5, // Vertical space
        indent = 20; // Indent between form (left edge) and component

    GridBagConstraints gbc = new GridBagConstraints();
    GridBagLayout gbl = new GridBagLayout();
    getContentPane().setLayout(gbl);

    //
    // Setup top panel
    //
    GridBagLayout topLayout = new GridBagLayout();
    JPanel topPanel = new JPanel();
    topPanel.setOpaque(false);
    topPanel.setLayout(topLayout);

    topLayout.setConstraints(
        dirLabel,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            0,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(10, 0, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        dirTF,
        new GridBagConstraints(
            1,
            0,
            1,
            1,
            1,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(vsp, 2, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        dirBttn,
        new GridBagConstraints(
            2,
            0,
            1,
            1,
            0,
            0,
            GridBagConstraints.CENTER,
            GridBagConstraints.NONE,
            new Insets(10, sp, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        matchingLabel,
        new GridBagConstraints(
            0,
            1,
            1,
            1,
            0,
            0,
            GridBagConstraints.EAST,
            GridBagConstraints.NONE,
            new Insets(10, 0, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        matchingTF,
        new GridBagConstraints(
            1,
            1,
            1,
            1,
            1,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(vsp, 2, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        recursiveCheckBox,
        new GridBagConstraints(
            2,
            1,
            GridBagConstraints.REMAINDER,
            1,
            1,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(vsp, 10, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        backupLabel,
        new GridBagConstraints(
            0,
            3,
            1,
            1,
            0,
            0,
            GridBagConstraints.EAST,
            GridBagConstraints.NONE,
            new Insets(10, 0, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        backupTF,
        new GridBagConstraints(
            1,
            3,
            1,
            1,
            1,
            0,
            GridBagConstraints.CENTER,
            GridBagConstraints.HORIZONTAL,
            new Insets(vsp, 2, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        backupBttn,
        new GridBagConstraints(
            2,
            3,
            1,
            1,
            0,
            0,
            GridBagConstraints.CENTER,
            GridBagConstraints.NONE,
            new Insets(10, sp, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        templateLabel,
        new GridBagConstraints(
            0,
            4,
            1,
            1,
            0,
            0,
            GridBagConstraints.EAST,
            GridBagConstraints.NONE,
            new Insets(10, 0, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        templateCh,
        new GridBagConstraints(
            1,
            4,
            1,
            1,
            0,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,
            new Insets(vsp, 2, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        sep1,
        new GridBagConstraints(
            0,
            5,
            GridBagConstraints.REMAINDER,
            1,
            1,
            0,
            GridBagConstraints.CENTER,
            GridBagConstraints.HORIZONTAL,
            new Insets(10, 10, 10, 10),
            0,
            0));
    topLayout.setConstraints(
        staticVersioningLabel,
        new GridBagConstraints(
            0,
            6,
            1,
            1,
            0,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(10, 0, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        staticVersioningRadioButton,
        new GridBagConstraints(
            0,
            7,
            GridBagConstraints.REMAINDER,
            1,
            1,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(vsp, 10, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        staticVersioningPanel,
        new GridBagConstraints(
            0,
            8,
            GridBagConstraints.REMAINDER,
            1,
            0,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.BOTH,
            new Insets(vsp, 25, 10, 0),
            0,
            0));
    topLayout.setConstraints(
        dynamicVersioningRadioButton,
        new GridBagConstraints(
            0,
            9,
            GridBagConstraints.REMAINDER,
            1,
            1,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(vsp, 10, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        dynamicVersioningPanel,
        new GridBagConstraints(
            0,
            10,
            GridBagConstraints.REMAINDER,
            1,
            0,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.BOTH,
            new Insets(vsp, 25, 0, 0),
            0,
            0));
    topLayout.setConstraints(
        sep2,
        new GridBagConstraints(
            0,
            11,
            GridBagConstraints.REMAINDER,
            1,
            1,
            0,
            GridBagConstraints.CENTER,
            GridBagConstraints.HORIZONTAL,
            new Insets(10, 10, 0, 10),
            0,
            0));

    invisibleBttn = new JButton();
    invisibleBttn.setVisible(false);
    topLayout.setConstraints(
        invisibleBttn,
        new GridBagConstraints(
            2,
            6,
            1,
            1,
            0,
            0,
            GridBagConstraints.CENTER,
            GridBagConstraints.CENTER,
            new Insets(indent, sp, 0, 0),
            0,
            0));

    topPanel.add(dirLabel);
    topPanel.add(dirTF);
    topPanel.add(dirBttn);
    topPanel.add(matchingLabel);
    topPanel.add(matchingTF);
    topPanel.add(recursiveCheckBox);
    topPanel.add(backupLabel);
    topPanel.add(backupTF);
    topPanel.add(backupBttn);
    topPanel.add(templateLabel);
    topPanel.add(templateCh);
    topPanel.add(sep1);
    topPanel.add(staticVersioningLabel);
    topPanel.add(staticVersioningRadioButton);
    topPanel.add(staticVersioningPanel);
    topPanel.add(dynamicVersioningRadioButton);
    topPanel.add(dynamicVersioningPanel);
    topPanel.add(sep2);
    topPanel.add(invisibleBttn);

    //
    // Setup bottom panel
    //
    GridBagLayout buttomLayout = new GridBagLayout();
    JPanel buttomPanel = new JPanel();
    buttomPanel.setOpaque(false);
    buttomPanel.setLayout(buttomLayout);

    buttomLayout.setConstraints(
        runBttn,
        new GridBagConstraints(
            3,
            0,
            1,
            1,
            0,
            0,
            GridBagConstraints.CENTER,
            GridBagConstraints.NONE,
            new Insets(sp, 0, 0, 0),
            0,
            0));
    buttomPanel.add(runBttn);

    //
    // Setup main panel
    //
    GridBagLayout mainLayout = new GridBagLayout();
    JPanel mainPanel = new JPanel();

    mainPanel.setOpaque(false);
    mainPanel.setLayout(mainLayout);

    mainLayout.setConstraints(
        topPanel,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            1,
            0,
            GridBagConstraints.CENTER,
            GridBagConstraints.HORIZONTAL,
            new Insets(buf, buf, 0, buf),
            0,
            0));
    mainLayout.setConstraints(
        buttomPanel,
        new GridBagConstraints(
            0,
            1,
            1,
            1,
            1,
            1,
            GridBagConstraints.SOUTH,
            GridBagConstraints.HORIZONTAL,
            new Insets(0, buf, buf, buf),
            0,
            0));
    mainPanel.add(topPanel);
    mainPanel.add(buttomPanel);

    Border border = BorderFactory.createEtchedBorder();
    mainPanel.setBorder(border);

    GridBagLayout layout = new GridBagLayout();
    getContentPane().setLayout(layout);

    layout.setConstraints(
        mainPanel,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            1,
            1,
            GridBagConstraints.CENTER,
            GridBagConstraints.BOTH,
            new Insets(0, 0, 0, 0),
            0,
            0));

    getContentPane().add(mainPanel);

    pack();
    setResizable(false);
  }
Example #2
0
  public ThumbMaker() {
    super("ThumbMaker");

    // grab the preferences so that they can be used to fill out the layout
    ThumbMakerPreferences myPrefs = ThumbMakerPreferences.getInstance();

    // content pane
    JPanel pane = new JPanel();
    pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
    setContentPane(pane);

    // top panel
    JPanel top = new JPanel();
    top.setLayout(new BoxLayout(top, BoxLayout.X_AXIS));
    pane.add(top);

    // left-hand panel
    JPanel left = new JPanel();
    left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS));
    top.add(left);

    // horizontal padding
    top.add(Box.createHorizontalStrut(5));

    // label for file list
    JLabel listLabel = GUIUtil.makeLabel("Files to process:");
    listLabel.setDisplayedMnemonic('f');
    String listTip = "List of files from which to create thumbnails";
    listLabel.setToolTipText(listTip);
    left.add(GUIUtil.pad(listLabel));

    // list of files to convert
    list = new JList();
    listLabel.setLabelFor(list);
    list.setToolTipText(listTip);
    list.setModel(new DefaultListModel());
    list.setDragEnabled(true);
    changeFilesInList = new ThumbTransferHandler();
    list.setTransferHandler(changeFilesInList);
    left.add(new JScrollPane(list));

    // progress bar
    progress = new JProgressBar(0, 1);
    progress.setString("[Drag and drop files onto list to begin]");
    progress.setStringPainted(true);
    progress.setToolTipText("Status of thumbnail processing operation");
    left.add(progress);

    // panel for process and remove buttons
    JPanel p = new JPanel();
    p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

    // add files button
    addFiles = new JButton("Add Files");
    addFiles.setMnemonic('d');
    addFiles.setToolTipText("Add files to be processed.");
    addFiles.addActionListener(this);
    p.add(addFiles);

    p.add(Box.createHorizontalStrut(5));

    // process button
    process = new JButton("Process");
    process.setMnemonic('p');
    process.setToolTipText("Begin creating thumbnails");
    process.addActionListener(this);
    p.add(process);

    p.add(Box.createHorizontalStrut(5));

    // remove button
    remove = new JButton("Remove");
    remove.setMnemonic('v');
    remove.setToolTipText("Remove selected files from the list");
    remove.addActionListener(this);
    p.add(remove);

    left.add(GUIUtil.pad(p));

    // right-hand panel
    JPanel right = new JPanel();
    right.setLayout(new BoxLayout(right, BoxLayout.Y_AXIS));
    top.add(right);

    // panel for resolution settings
    p = new JPanel();
    p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

    // resolution label
    JLabel resLabel = GUIUtil.makeLabel("Resolution: ");
    resLabel.setDisplayedMnemonic('s');
    resLabel.setToolTipText("Resolution of the thumbnails");
    p.add(resLabel);

    // x resolution text box
    xres =
        GUIUtil.makeTextField(myPrefs.getStringPref(ThumbMakerPreferences.RES_WIDTH_PREF_NAME), 2);
    resLabel.setLabelFor(xres);
    xres.setToolTipText("Thumbnail width");
    p.add(xres);

    // "by" label
    JLabel byLabel = GUIUtil.makeLabel(" by ");
    byLabel.setDisplayedMnemonic('y');
    p.add(byLabel);

    // y resolution text box
    yres =
        GUIUtil.makeTextField(myPrefs.getStringPref(ThumbMakerPreferences.RES_HEIGHT_PREF_NAME), 2);
    byLabel.setLabelFor(yres);
    yres.setToolTipText("Thumbnail height");
    p.add(yres);

    right.add(GUIUtil.pad(p));
    right.add(Box.createVerticalStrut(8));

    // aspect ratio checkbox
    aspect = new JCheckBox("Maintain aspect ratio", true);
    aspect.setMnemonic('m');
    aspect.setToolTipText(
        "When checked, thumbnails are not stretched, "
            + "but rather padded with the background color.");
    aspect.addActionListener(this);
    right.add(GUIUtil.pad(aspect));
    // make sure that the check box is initialized correctly
    aspect.setSelected(
        myPrefs
            .getStringPref(ThumbMakerPreferences.DO_MAINTAIN_ASPECT_PREF_NAME)
            .equalsIgnoreCase(ThumbMakerPreferences.BOOLEAN_TRUE_STRING));

    // panel for background color
    p = new JPanel();
    p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

    // load the color values from the preferences
    int redValueNumber = myPrefs.getIntegerPref(ThumbMakerPreferences.RED_VALUE_PREF_NAME);
    int greenValueNumber = myPrefs.getIntegerPref(ThumbMakerPreferences.GREEN_VALUE_PREF_NAME);
    int blueValueNumber = myPrefs.getIntegerPref(ThumbMakerPreferences.BLUE_VALUE_PREF_NAME);

    // background color label
    colorLabel = GUIUtil.makeLabel("Background color: ");
    String colorTip = "Thumbnail background color";
    colorLabel.setToolTipText(colorTip);
    p.add(colorLabel);

    // background color
    colorBox = new JPanel();
    colorBox.setToolTipText(colorTip);
    colorBox.setBorder(new LineBorder(Color.black, 1));
    Dimension colorBoxSize = new Dimension(45, 15);
    colorBox.setMaximumSize(colorBoxSize);
    colorBox.setMinimumSize(colorBoxSize);
    colorBox.setPreferredSize(colorBoxSize);
    colorBox.setBackground(new Color(redValueNumber, greenValueNumber, blueValueNumber));
    p.add(colorBox);

    right.add(GUIUtil.pad(p));
    right.add(Box.createVerticalStrut(2));

    // red slider
    redLabel = GUIUtil.makeLabel("R");
    red = new JSlider(0, 255, redValueNumber);
    redValue = GUIUtil.makeLabel("" + redValueNumber);
    redValue.setToolTipText("Red color component slider");
    right.add(makeSlider(redLabel, red, redValue, "Red"));

    // green slider
    greenLabel = GUIUtil.makeLabel("G");
    green = new JSlider(0, 255, greenValueNumber);
    greenValue = GUIUtil.makeLabel("" + greenValueNumber);
    greenValue.setToolTipText("Green color component slider");
    right.add(makeSlider(greenLabel, green, greenValue, "Green"));

    // blue slider
    blueLabel = GUIUtil.makeLabel("B");
    blue = new JSlider(0, 255, blueValueNumber);
    blueValue = GUIUtil.makeLabel("" + blueValueNumber);
    right.add(makeSlider(blueLabel, blue, blueValue, "Blue"));

    right.add(Box.createVerticalStrut(8));

    // panel for algorithm
    p = new JPanel();
    p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

    // algorithm label
    JLabel algorithmLabel = GUIUtil.makeLabel("Algorithm: ");
    algorithmLabel.setDisplayedMnemonic('l');
    String algorithmTip = "Resizing algorithm to use";
    algorithmLabel.setToolTipText(algorithmTip);
    p.add(algorithmLabel);

    // algorithm combo box
    algorithm =
        GUIUtil.makeComboBox(
            new String[] {"Smooth", "Standard", "Fast", "Replicate", "Area averaging"});
    algorithmLabel.setLabelFor(algorithm);
    algorithm.setToolTipText(algorithmTip);
    p.add(algorithm);
    // set the algorithm value from the preferences
    algorithm.setSelectedIndex(myPrefs.getIntegerPref(ThumbMakerPreferences.RESIZE_ALG_PREF_NAME));

    right.add(GUIUtil.pad(p));

    // panel for output format
    p = new JPanel();
    p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

    // format label
    JLabel formatLabel = GUIUtil.makeLabel("Format: ");
    formatLabel.setDisplayedMnemonic('f');
    String formatTip = "Thumbnail output format";
    formatLabel.setToolTipText(formatTip);
    p.add(formatLabel);

    // format combo box
    format = GUIUtil.makeComboBox(new String[] {"PNG", "JPG"});
    formatLabel.setLabelFor(format);
    format.setToolTipText(formatTip);
    p.add(format);
    // set the format value from the preferences
    format.setSelectedIndex(myPrefs.getIntegerPref(ThumbMakerPreferences.THUMB_FORMAT_PREF_NAME));

    right.add(GUIUtil.pad(p));
    right.add(Box.createVerticalStrut(5));

    // panel for prepend string
    p = new JPanel();
    p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

    // prepend label
    JLabel prependLabel = GUIUtil.makeLabel("Prepend: ");
    prependLabel.setDisplayedMnemonic('e');
    String prependTip = "Starting string for each thumbnail filename";
    prependLabel.setToolTipText(prependTip);
    p.add(prependLabel);

    // prepend field
    prepend =
        GUIUtil.makeTextField(
            myPrefs.getStringPref(ThumbMakerPreferences.STRING_TO_PREPEND_PREF_NAME), 4);
    prependLabel.setLabelFor(prepend);
    prepend.setToolTipText(prependTip);
    p.add(prepend);

    p.add(Box.createHorizontalStrut(5));

    // append label
    JLabel appendLabel = GUIUtil.makeLabel("Append: ");
    appendLabel.setDisplayedMnemonic('a');
    String appendTip = "Ending string for each thumbnail filename";
    appendLabel.setToolTipText(appendTip);
    p.add(appendLabel);

    // append field
    append =
        GUIUtil.makeTextField(
            myPrefs.getStringPref(ThumbMakerPreferences.STRING_TO_APPEND_PREF_NAME), 4);
    appendLabel.setLabelFor(append);
    append.setToolTipText(appendTip);
    p.add(append);

    right.add(GUIUtil.pad(p));

    // vertical padding
    right.add(Box.createVerticalGlue());

    // bottom panel
    JPanel bottom = new JPanel();
    bottom.setLayout(new BoxLayout(bottom, BoxLayout.X_AXIS));
    pane.add(bottom);

    // output folder label
    JLabel outputLabel = GUIUtil.makeLabel("Output folder: ");
    outputLabel.setDisplayedMnemonic('o');
    String outputTip = "Thumbnail output folder";
    outputLabel.setToolTipText(outputTip);
    bottom.add(outputLabel);

    // output folder field
    String filePath =
        new File(myPrefs.getStringPref(ThumbMakerPreferences.FILE_PATH_STRING_PREF_NAME))
            .getAbsolutePath();
    output = GUIUtil.makeTextField(filePath, 8);
    outputLabel.setLabelFor(output);
    output.setToolTipText(outputTip);
    // start this in default and then lock down so "..." is used
    output.setEditable(false);
    output.setBackground(Color.LIGHT_GRAY);
    bottom.add(output);

    // add a file chooser button "..."
    dotDotDot = new JButton("...");
    dotDotDot.setMnemonic('.');
    dotDotDot.setToolTipText("Select destination directory.");
    dotDotDot.addActionListener(this);
    bottom.add(dotDotDot);

    right.add(GUIUtil.pad(p));

    setFromPreferences();
    addWindowListener(this);
  }