/** Handle button pressed. */
 private void buttonPressed(CloseAction<T> a) {
   _buttonPressed = a.getName();
   _lastState = new FrameState(PredictiveInputFrame.this);
   setVisible(false);
   a.value(this);
 }
  /**
   * Initialize the frame.
   *
   * @param info true if additional information is desired
   */
  private void init(boolean info) {
    _buttonPressed = null;
    addComponentListener(
        new java.awt.event.ComponentAdapter() {
          public void componentResized(ComponentEvent e) {
            validate();
            _matchList.ensureIndexIsVisible(_matchList.getSelectedIndex());
          }
        });

    // buttons
    int i = 0;
    for (final CloseAction<T> a : _actions) {
      _buttons[i] = new JButton(a.getName());
      final String tooltip = a.getToolTipText();
      if (tooltip != null) {
        _buttons[i].setToolTipText(tooltip);
      }
      _buttons[i].addActionListener(
          new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              buttonPressed(a);
            }
          });
      ++i;
    }

    getRootPane().setDefaultButton(_buttons[0]);

    _strategyBox.setEditable(false);
    _strategyBox.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            // System.out.println("set strategy!");
            selectStrategy();
          }
        });
    _strategyBox.addFocusListener(
        new FocusAdapter() {

          public void focusLost(FocusEvent e) {
            boolean bf = false;
            for (JButton b : _buttons) {
              if (e.getOppositeComponent() == b) {
                bf = true;
                break;
              }
            }
            if ((e.getOppositeComponent() != _textField) && (!bf)) {
              for (JComponent c : _optionalComponents) {
                if (e.getOppositeComponent() == c) {
                  return;
                }
              }
              _textField.requestFocus();
            }
          }
        });

    // text field
    _textField.setDragEnabled(false);
    _textField.setFocusTraversalKeysEnabled(false);

    addListener();

    Keymap ourMap =
        JTextComponent.addKeymap("PredictiveInputFrame._textField", _textField.getKeymap());
    for (final CloseAction<T> a : _actions) {
      KeyStroke ks = a.getKeyStroke();
      if (ks != null) {
        ourMap.addActionForKeyStroke(
            ks,
            new AbstractAction() {
              public void actionPerformed(ActionEvent e) {
                buttonPressed(a);
              }
            });
      }
    }
    ourMap.addActionForKeyStroke(
        KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0),
        new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            //        System.out.println("tab!");
            removeListener();
            _pim.extendSharedMask();
            updateTextField();
            updateExtensionLabel();
            updateList();
            addListener();
          }
        });
    ourMap.addActionForKeyStroke(
        KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0),
        new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            //        System.out.println("up!");
            if (_matchList.getModel().getSize() > 0) {
              removeListener();
              int i = _matchList.getSelectedIndex();
              if (i > 0) {
                _matchList.setSelectedIndex(i - 1);
                _matchList.ensureIndexIsVisible(i - 1);
                _pim.setCurrentItem(_pim.getMatchingItems().get(i - 1));
                updateInfo();
              }
              addListener();
            }
          }
        });
    ourMap.addActionForKeyStroke(
        KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),
        new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            //        System.out.println("down!");
            if (_matchList.getModel().getSize() > 0) {
              removeListener();
              int i = _matchList.getSelectedIndex();
              if (i < _matchList.getModel().getSize() - 1) {
                _matchList.setSelectedIndex(i + 1);
                _matchList.ensureIndexIsVisible(i + 1);
                _pim.setCurrentItem(_pim.getMatchingItems().get(i + 1));
                updateInfo();
              }
              addListener();
            }
          }
        });
    ourMap.addActionForKeyStroke(
        KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0),
        new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            //        System.out.println("page up!");
            if (_matchList.getModel().getSize() > 0) {
              removeListener();
              int page = _matchList.getLastVisibleIndex() - _matchList.getFirstVisibleIndex() + 1;
              int i = _matchList.getSelectedIndex() - page;
              if (i < 0) i = 0;
              _matchList.setSelectedIndex(i);
              _matchList.ensureIndexIsVisible(i);
              _pim.setCurrentItem(_pim.getMatchingItems().get(i));
              updateInfo();
              addListener();
            }
          }
        });
    ourMap.addActionForKeyStroke(
        KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0),
        new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            //        System.out.println("page down!");
            if (_matchList.getModel().getSize() > 0) {
              removeListener();
              int page = _matchList.getLastVisibleIndex() - _matchList.getFirstVisibleIndex() + 1;
              int i = _matchList.getSelectedIndex() + page;
              if (i >= _matchList.getModel().getSize()) {
                i = _matchList.getModel().getSize() - 1;
              }
              _matchList.setSelectedIndex(i);
              _matchList.ensureIndexIsVisible(i);
              _pim.setCurrentItem(_pim.getMatchingItems().get(i));
              updateInfo();
              addListener();
            }
          }
        });
    _textField.setKeymap(ourMap);

    _textField.addFocusListener(
        new FocusAdapter() {
          public void focusLost(FocusEvent e) {
            boolean bf = false;
            for (JButton b : _buttons) {
              if (e.getOppositeComponent() == b) {
                bf = true;
                break;
              }
            }
            if ((e.getOppositeComponent() != _strategyBox) && (!bf)) {
              for (JComponent c : _optionalComponents) {
                if (e.getOppositeComponent() == c) {
                  return;
                }
              }
              _textField.requestFocus();
            }
          }
        });

    _matchList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    _matchList.addListSelectionListener(
        new ListSelectionListener() {
          public void valueChanged(ListSelectionEvent e) {
            //        System.out.println("click!");
            removeListener();
            int i = _matchList.getSelectedIndex();
            if (i >= 0) {
              _pim.setCurrentItem(_pim.getMatchingItems().get(i));
              _matchList.ensureIndexIsVisible(i);
              updateInfo();
            }
            addListener();
          }
        });

    // put everything together
    Container contentPane = getContentPane();

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

    GridBagConstraints c = new GridBagConstraints();
    c.anchor = GridBagConstraints.NORTHWEST;
    c.weightx = 1.0;
    c.weighty = 0.0;
    c.gridwidth = GridBagConstraints.REMAINDER; // end row
    c.insets.top = 2;
    c.insets.left = 2;
    c.insets.bottom = 2;
    c.insets.right = 2;

    if (info) {
      c.fill = GridBagConstraints.NONE;
      contentPane.add(_infoLabel, c);
    }

    c.fill = GridBagConstraints.BOTH;
    c.weighty = 1.0;
    contentPane.add(
        new JScrollPane(
            _matchList,
            ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
            ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
        c);

    c.anchor = GridBagConstraints.SOUTHWEST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    c.gridwidth = 1;
    contentPane.add(_tabCompletesLabel, c);

    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 1.0;
    c.gridwidth = GridBagConstraints.REMAINDER;
    contentPane.add(_sharedExtLabel, c);

    contentPane.add(_textField, c);

    _optionalComponents = makeOptions();
    if (_optionalComponents.length > 0) {
      _optionsPanel = new JPanel(new BorderLayout());
      _setupOptionsPanel(_optionalComponents);
      contentPane.add(_optionsPanel, c);
    }

    c.anchor = GridBagConstraints.SOUTHWEST;
    c.weightx = 1.0;
    c.weighty = 0.0;
    c.gridwidth = GridBagConstraints.REMAINDER; // end row
    c.insets.top = 2;
    c.insets.left = 2;
    c.insets.bottom = 2;
    c.insets.right = 2;

    JPanel buttonPanel = new JPanel(new GridBagLayout());
    GridBagConstraints bc = new GridBagConstraints();
    bc.insets.left = 2;
    bc.insets.right = 2;
    buttonPanel.add(new JLabel("Matching strategy:"), bc);
    buttonPanel.add(_strategyBox, bc);
    for (JButton b : _buttons) {
      buttonPanel.add(b, bc);
    }

    contentPane.add(buttonPanel, c);

    pack();
    //    Dimension parentDim = (_owner != null) ? _owner.getSize() : getToolkit().getScreenSize();
    //// int xs = (int) parentDim.getWidth()/3;
    //    int ys = (int) parentDim.getHeight()/4;
    //// in line below, parentDim was _owner.getSize(); changed because former could generate
    // NullPointerException
    //    setSize(new Dimension((int) getSize().getWidth(), (int)Math.min(parentDim.getHeight(),
    // Math.max(ys, 300))));
    if (_owner != null) {
      setLocationRelativeTo(_owner);
    }

    removeListener();
    updateTextField();
    addListener();
    updateList();
  }