Google Tag Manager

Showing posts with label JComboBox. Show all posts
Showing posts with label JComboBox. Show all posts

2018/11/29

aterai

Add editable JCheckBox to ComboBoxEditor of JComboBox

Code

class CheckComboBoxEditor implements ComboBoxEditor {
  private final EditorPanel editor = new EditorPanel(new ComboItem());
  @Override public void selectAll() {
    editor.selectAll();
  }
  @Override public Object getItem() {
    return editor.getItem();
  }
  @Override public void setItem(Object anObject) {
    EventQueue.invokeLater(() -> {
      Container c = SwingUtilities.getAncestorOfClass(
          JComboBox.class, getEditorComponent());
      if (c instanceof JComboBox) {
        JComboBox combo = (JComboBox) c;
        int idx = combo.getSelectedIndex();
        if (idx >= 0 && idx != editor.getEditingIndex()) {
          System.out.println("setItem: " + idx);
          editor.setEditingIndex(idx);
        }
      }
    });
    if (anObject instanceof ComboItem) {
      editor.setItem((ComboItem) anObject);
    } else {
      editor.setItem(new ComboItem());
    }
  }
  @Override public Component getEditorComponent() {
    return editor;
  }
  @Override public void addActionListener(ActionListener l) {
    editor.addActionListener(l);
  }
  @Override public void removeActionListener(ActionListener l) {
    editor.removeActionListener(l);
  }
}

final class EditorPanel extends JPanel {
  private final JCheckBox enabledCheck = new JCheckBox();
  private final JCheckBox editableCheck = new JCheckBox();
  private final JTextField textField = new JTextField("", 16);
  private final transient ComboItem data;
  private int editingIndex = -1;

  protected EditorPanel(ComboItem data) {
    super();
    this.data = data;
    setItem(data);

    enabledCheck.addActionListener(e -> {
      Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
      if (c instanceof JComboBox) {
        JComboBox combo = (JComboBox) c;
        ComboItem item = (ComboItem) combo.getItemAt(editingIndex);
        item.setEnabled(((JCheckBox) e.getSource()).isSelected());
        editableCheck.setEnabled(item.isEnabled());
        textField.setEnabled(item.isEnabled());
        combo.setSelectedIndex(editingIndex);
      }
    });
    enabledCheck.setOpaque(false);
    enabledCheck.setFocusable(false);

    editableCheck.addActionListener(e -> {
      Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
      if (c instanceof JComboBox) {
        JComboBox combo = (JComboBox) c;
        ComboItem item = (ComboItem) combo.getItemAt(editingIndex);
        item.setEditable(((JCheckBox) e.getSource()).isSelected());
        textField.setEditable(item.isEditable());
        combo.setSelectedIndex(editingIndex);
      }
    });
    editableCheck.setOpaque(false);
    editableCheck.setFocusable(false);

    textField.addActionListener(e -> {
      Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
      if (c instanceof JComboBox) {
        JComboBox combo = (JComboBox) c;
        ComboItem item = (ComboItem) combo.getItemAt(editingIndex);
        item.setText(((JTextField) e.getSource()).getText());
        combo.setSelectedIndex(editingIndex);
      }
    });
    textField.setBorder(BorderFactory.createEmptyBorder());
    textField.setOpaque(false);

    setOpaque(false);
    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));

    add(enabledCheck);
    add(editableCheck);
    add(textField);
  }
  public int getEditingIndex() {
    return editingIndex;
  }
  public void setEditingIndex(int idx) {
    this.editingIndex = idx;
  }
  public ComboItem getItem() {
    data.setEnabled(enabledCheck.isSelected());
    data.setEditable(editableCheck.isSelected());
    data.setText(textField.getText());
    return data;
  }
  public void setItem(ComboItem item) {
    enabledCheck.setSelected(item.isEnabled());

    editableCheck.setSelected(item.isEditable());
    editableCheck.setEnabled(item.isEnabled());

    textField.setText(item.getText());
    textField.setEnabled(item.isEnabled());
    textField.setEditable(item.isEditable());
  }
  public void selectAll() {
    textField.requestFocusInWindow();
    textField.selectAll();
  }
  public void addActionListener(ActionListener l) {
    textField.addActionListener(l);
    enabledCheck.addActionListener(l);
    editableCheck.addActionListener(l);
  }
  public void removeActionListener(ActionListener l) {
    textField.removeActionListener(l);
    enabledCheck.removeActionListener(l);
    editableCheck.removeActionListener(l);
  }
}

References

2018/05/25

aterai

Use JTable instead of JList as a drop down list of JComboBox

Code

class DropdownTableComboBox<E extends List<Object>> extends JComboBox<E> {
  protected final transient HighlightListener highlighter = new HighlightListener();
  protected final JTable table = new JTable() {
    @Override public Component prepareRenderer(
          TableCellRenderer renderer, int row, int column) {
      Component c = super.prepareRenderer(renderer, row, column);
      c.setForeground(Color.BLACK);
      if (highlighter.isHighlightableRow(row)) {
        c.setBackground(new Color(255, 200, 200));
      } else if (isRowSelected(row)) {
        c.setBackground(Color.CYAN);
      } else {
        c.setBackground(Color.WHITE);
      }
      return c;
    }
    @Override public void updateUI() {
      removeMouseListener(highlighter);
      removeMouseMotionListener(highlighter);
      super.updateUI();
      addMouseListener(highlighter);
      addMouseMotionListener(highlighter);
      getTableHeader().setReorderingAllowed(false);
    }
  };
  protected final List<E> list;

  protected DropdownTableComboBox(List<E> list, DefaultTableModel model) {
    super();
    this.list = list;
    table.setModel(model);
    list.forEach(this::addItem);
    // list.forEach(model::addRow);
    list.forEach(v -> model.addRow(v.toArray(new Object[0])));
  }

  @Override public void updateUI() {
    super.updateUI();
    EventQueue.invokeLater(() -> {
      setUI(new MetalComboBoxUI() {
        @Override protected ComboPopup createPopup() {
          return new ComboTablePopup(comboBox, table);
        }
      });
      setEditable(false);
    });
  }
  public List<Object> getSelectedRow() {
    return list.get(getSelectedIndex());
  }
}

References

2017/05/30

aterai

Use JComboBox as JTree's node cell editor

Code

class PluginCellEditor extends DefaultCellEditor {
  private final PluginPanel panel;
  private transient PluginNode node;

  protected PluginCellEditor(JComboBox comboBox) {
    super(comboBox);
    panel = new PluginPanel(comboBox);
  }
  @Override public Component getTreeCellEditorComponent(
      JTree tree, Object value, boolean isSelected, boolean expanded,
      boolean leaf, int row) {
    this.node = panel.extractNode(value);
    return panel;
  }
  @Override public Object getCellEditorValue() {
    Object o = super.getCellEditorValue();
    return Optional.ofNullable(node).map(node -> {
      DefaultComboBoxModel m =
        (DefaultComboBoxModel) panel.comboBox.getModel();
      PluginNode n = new PluginNode(panel.pluginName.getText(), node.plugins);
      n.setSelectedPluginIndex(m.getIndexOf(o));
      return (Object) n;
    }).orElse(o);
  }
  @Override public boolean isCellEditable(EventObject e) {
    Object source = e.getSource();
    if (!(source instanceof JTree) || !(e instanceof MouseEvent)) {
      return false;
    }
    JTree tree = (JTree) source;
    Point p = ((MouseEvent) e).getPoint();
    TreePath path = tree.getPathForLocation(p.x, p.y);
    if (Objects.isNull(path)) {
      return false;
    }
    Object node = path.getLastPathComponent();
    if (!(node instanceof DefaultMutableTreeNode)) {
      return false;
    }
    Rectangle r = tree.getPathBounds(path);
    if (Objects.isNull(r)) {
      return false;
    }
    Dimension d = panel.getPreferredSize();
    r.width = d.width;
    if (r.contains(p)) {
      showComboPopup(tree, p);
      return true;
    }
    return delegate.isCellEditable(e);
  }
  private void showComboPopup(JTree tree, Point p) {
    EventQueue.invokeLater(() -> {
      Point pt = SwingUtilities.convertPoint(tree, p, panel);
      Component o = SwingUtilities.getDeepestComponentAt(panel, pt.x, pt.y);
      if (o instanceof JComboBox) {
        panel.comboBox.showPopup();
      } else if (Objects.nonNull(o)) {
        Container c = SwingUtilities.getAncestorOfClass(
            JComboBox.class, (Component) o);
        if (c instanceof JComboBox) {
          panel.comboBox.showPopup();
        }
      }
    });
  }
}

References

2016/08/26

aterai

Use an editable JComboBox as a TableCellEditor

Code

class ComboCellEditor extends AbstractCellEditor implements TableCellEditor {
  private final JComboBox combo = new JComboBox<>();
  protected ComboCellEditor() {
    super();
    combo.setEditable(true);
    combo.addActionListener(e -> {
      fireEditingStopped();
    });
  }
  @Override public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) {
    if (value instanceof ComboBoxModel) {
      @SuppressWarnings("unchecked")
      ComboBoxModel m = (ComboBoxModel) value;
      combo.setModel(m);
    }
    return combo;
  }
  @Override public Object getCellEditorValue() {
    @SuppressWarnings("unchecked")
    DefaultComboBoxModel m = (DefaultComboBoxModel) combo.getModel();
    if (combo.isEditable()) {
      String str = Objects.toString(combo.getEditor().getItem(), "");
      if (!str.isEmpty() && m.getIndexOf(str) < 0) {
        m.insertElementAt(str, 0);
        combo.setSelectedIndex(0);
      }
    }
    return m;
  }
}

References

2016/07/26

aterai

Select multiple JCheckBox in JComboBox

Code

class CheckedComboBox<E extends CheckableItem> extends JComboBox<E> {
  private boolean keepOpen;
  private transient ActionListener listener;

  protected CheckedComboBox() {
    super();
  }
  protected CheckedComboBox(ComboBoxModel<E> aModel) {
    super(aModel);
  }
  protected CheckedComboBox(E[] m) {
    super(m);
  }
  @Override public Dimension getPreferredSize() {
    return new Dimension(200, 20);
  }
  @Override public void updateUI() {
    setRenderer(null);
    removeActionListener(listener);
    super.updateUI();
    listener = e -> {
      if ((e.getModifiers() & InputEvent.MOUSE_EVENT_MASK) != 0) {
        updateItem(getSelectedIndex());
        keepOpen = true;
      }
    };
    setRenderer(new CheckBoxCellRenderer<CheckableItem>());
    addActionListener(listener);
    getInputMap(JComponent.WHEN_FOCUSED).put(
        KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "checkbox-select");
    getActionMap().put("checkbox-select", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        Accessible a = getAccessibleContext().getAccessibleChild(0);
        if (a instanceof BasicComboPopup) {
          BasicComboPopup pop = (BasicComboPopup) a;
          updateItem(pop.getList().getSelectedIndex());
        }
      }
    });
  }
  private void updateItem(int index) {
    if (isPopupVisible()) {
      E item = getItemAt(index);
      item.selected ^= true;
      removeItemAt(index);
      insertItemAt(item, index);
      setSelectedItem(item);
    }
  }
  @Override public void setPopupVisible(boolean v) {
    if (keepOpen) {
      keepOpen = false;
    } else {
      super.setPopupVisible(v);
    }
  }
}

References

2016/03/03

aterai

Validating input on an editable JComboBox with InputVerifier and JLayer

Code

JComboBox comboBox = new JComboBox(model) {
  @Override public void updateUI() {
    getActionMap().put(ENTER_PRESSED, null);
    super.updateUI();
    final JComboBox cb = this;
    final Action defalutEnterPressedAction = getActionMap().get(ENTER_PRESSED);
    getActionMap().put(ENTER_PRESSED, new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        boolean isPopupVisible = isPopupVisible();
        setPopupVisible(false);
        DefaultComboBoxModel m = (DefaultComboBoxModel) getModel();
        String str = Objects.toString(getEditor().getItem(), "");
        if (m.getIndexOf(str) < 0 && getInputVerifier().verify(cb)) {
          m.removeElement(str);
          m.insertElementAt(str, 0);
          if (m.getSize() > 10) {
            m.removeElementAt(10);
          }
          setSelectedIndex(0);
          setPopupVisible(isPopupVisible);
        } else {
          defalutEnterPressedAction.actionPerformed(e);
        }
      }
    });
  }
};
comboBox.setEditable(true);
comboBox.setInputVerifier(new LengthInputVerifier());
comboBox.setEditor(new BasicComboBoxEditor() {
  private Component editorComponent;
  @Override public Component getEditorComponent() {
    if (editorComponent == null) {
      JTextComponent tc = (JTextComponent) super.getEditorComponent();
      editorComponent = new JLayer(tc, new ValidationLayerUI());
    }
    return editorComponent;
  }
});

class LengthInputVerifier extends InputVerifier {
  private static final int MAX_LEN = 6;
  @Override public boolean verify(JComponent c) {
    if (c instanceof JComboBox) {
      JComboBox cb = (JComboBox) c;
      String str = Objects.toString(cb.getEditor().getItem(), "");
      return MAX_LEN - str.length() >= 0;
    }
    return false;
  }
}

References

2012/10/29

aterai

Delete button in a JComboBox popup menu items

Code

class CellButtonsMouseListener extends MouseAdapter {
  private int prevIndex = -1;
  private JButton prevButton;
  private static void listRepaint(JList list, Rectangle rect) {
    if (Objects.nonNull(rect)) {
      list.repaint(rect);
    }
  }
  @Override public void mouseMoved(MouseEvent e) {
    JList list = (JList) e.getComponent();
    Point pt = e.getPoint();
    int index = list.locationToIndex(pt);
    if (!list.getCellBounds(index, index).contains(pt)) {
      if (prevIndex >= 0) {
        Rectangle r = list.getCellBounds(prevIndex, prevIndex);
        listRepaint(list, r);
      }
      index = -1;
      prevButton = null;
      return;
    }
    if (index >= 0) {
      JButton button = getButton(list, pt, index);
      ButtonsRenderer renderer = (ButtonsRenderer) list.getCellRenderer();
      if (Objects.nonNull(button)) {
        renderer.rolloverIndex = index;
        if (!button.equals(prevButton)) {
          Rectangle r = list.getCellBounds(prevIndex, index);
          listRepaint(list, r);
        }
      } else {
        renderer.rolloverIndex = -1;
        Rectangle r = null;
        if (prevIndex == index) {
          if (prevIndex >= 0 && Objects.nonNull(prevButton)) {
            r = list.getCellBounds(prevIndex, prevIndex);
          }
        } else {
          r = list.getCellBounds(index, index);
        }
        listRepaint(list, r);
        prevIndex = -1;
      }
      prevButton = button;
    }
    prevIndex = index;
  }
  @Override public void mousePressed(MouseEvent e) {
    JList list = (JList) e.getComponent();
    Point pt = e.getPoint();
    int index = list.locationToIndex(pt);
    if (index >= 0) {
      JButton button = getButton(list, pt, index);
      if (Objects.nonNull(button)) {
        listRepaint(list, list.getCellBounds(index, index));
      }
    }
  }
  @Override public void mouseReleased(MouseEvent e) {
    JList list = (JList) e.getComponent();
    Point pt = e.getPoint();
    int index = list.locationToIndex(pt);
    if (index >= 0) {
      JButton button = getButton(list, pt, index);
      if (Objects.nonNull(button)) {
        button.doClick();
        Rectangle r = list.getCellBounds(index, index);
        listRepaint(list, r);
      }
    }
  }
  @Override public void mouseExited(MouseEvent e) {
    JList list = (JList) e.getComponent();
    ButtonsRenderer renderer = (ButtonsRenderer) list.getCellRenderer();
    renderer.rolloverIndex = -1;
  }
  @SuppressWarnings("unchecked")
  private static JButton getButton(JList list, Point pt, int index) {
    Container c = (Container) list.getCellRenderer().getListCellRendererComponent(
        list, "", index, false, false);
    Rectangle r = list.getCellBounds(index, index);
    c.setBounds(r);
    // c.doLayout(); // may be needed for other layout managers (eg. FlowLayout)
    pt.translate(-r.x, -r.y);
    Component b = SwingUtilities.getDeepestComponentAt(c, pt.x, pt.y);
    if (b instanceof JButton) {
      return (JButton) b;
    } else {
      return null;
    }
  }
}

References

2012/07/02

aterai

Rounded corner JComboBox border

Code

class RoundedCornerBorder extends AbstractBorder {
  @Override public void paintBorder(
      Component c, Graphics g, int x, int y, int width, int height) {
    Graphics2D g2 = (Graphics2D)g.create();
    g2.setRenderingHint(
        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    int r = 12;
    int w = width  - 1;
    int h = height - 1;
    Area round = new Area(new RoundRectangle2D.Float(x, y, w, h, r, r));
    Container parent = c.getParent();
    if(parent!=null) {
      g2.setColor(parent.getBackground());
      Area corner = new Area(new Rectangle2D.Float(x, y, width, height));
      corner.subtract(round);
      g2.fill(corner);
    }
    g2.setPaint(c.getForeground());
    g2.draw(round);
    g2.dispose();
  }
  @Override public Insets getBorderInsets(Component c) {
    return new Insets(4, 8, 4, 8);
  }
  @Override public Insets getBorderInsets(Component c, Insets insets) {
    insets.left = insets.right = 8;
    insets.top = insets.bottom = 4;
    return insets;
  }
}

class KamabokoBorder extends RoundedCornerBorder {
  @Override public void paintBorder(
      Component c, Graphics g, int x, int y, int width, int height) {
    Graphics2D g2 = (Graphics2D)g.create();
    g2.setRenderingHint(
        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    int r = 12;
    int w = width  - 1;
    int h = height - 1;
//*/
    Path2D.Float p = new Path2D.Float();
    p.moveTo(x, y + h);
    p.lineTo(x, y + r);
    p.quadTo(x, y, x + r, y);
    p.lineTo(x + w - r, y);
    p.quadTo(x + w, y, x + w, y + r);
    p.lineTo(x + w, y + h);
    p.closePath();
    Area round = new Area(p);
/*/
    Area round = new Area(new RoundRectangle2D.Float(x, y, w, h, r, r));
    Rectangle b = round.getBounds();
    b.setBounds(b.x, b.y + r, b.width, b.height - r);
    round.add(new Area(b));
//*/
    Container parent = c.getParent();
    if(parent!=null) {
      g2.setColor(parent.getBackground());
      Area corner = new Area(new Rectangle2D.Float(x, y, width, height));
      corner.subtract(round);
      g2.fill(corner);
    }
    g2.setPaint(c.getForeground());
    g2.draw(round);
    g2.dispose();
  }
}

References

2011/09/29

aterai

JProgressBar in JComboBox

Code

class ProgressCellRenderer extends DefaultListCellRenderer {
  private final JProgressBar bar = new JProgressBar() {
    @Override public Dimension getPreferredSize() {
      return ProgressCellRenderer.this.getPreferredSize();
    }
  };
  @Override public Component getListCellRendererComponent(
      JList list, Object value, int index,
      boolean isSelected, boolean cellHasFocus) {
    if(index < 0 && worker!=null && !worker.isDone()) {
      bar.setFont(list.getFont());
      bar.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
      bar.setValue(count);
      return bar;
    }else{
      return super.getListCellRendererComponent(
          list,value,index,isSelected,cellHasFocus);
    }
  }
  @Override public void updateUI() {
    super.updateUI();
    if(bar!=null) SwingUtilities.updateComponentTreeUI(bar);
  }
}

//........
button = new JButton(new AbstractAction("load") {
  @Override public void actionPerformed(ActionEvent e) {
    button.setEnabled(false);
    combo.setEnabled(false);
    combo.removeAllItems();
    worker = new SwingWorker<String, String>() {
      private int max = 30;
      @Override public String doInBackground() {
        int current = 0;
        while(current <= max && !isCancelled()) {
          try {
            Thread.sleep(50);
            //setProgress(100 * current / max);
            count = 100 * current / max;
            publish("test: "+current);
          }catch(Exception ie) {
            return "Exception";
          }
          current++;
        }
        return "Done";
      }
      @Override protected void process(java.util.List< String > chunks) {
        DefaultComboBoxModel m = (DefaultComboBoxModel)combo.getModel();
        for(String s: chunks) {
          m.addElement(s);
        }
        combo.setSelectedIndex(-1);
        combo.repaint();
      }
      @Override public void done() {
        String text = null;
        if(!isCancelled()) {
          combo.setSelectedIndex(0);
        }
        combo.setEnabled(true);
        button.setEnabled(true);
        count = 0;
      }
    };
    worker.execute();
  }
});

References

2010/09/21

aterai

SearchBar JComboBox

Code

public class BasicSearchBarComboBoxUI extends SearchBarComboBoxUI {
  public static javax.swing.plaf.ComponentUI createUI(JComponent c) {
    return new BasicSearchBarComboBoxUI();
  }
  protected boolean isEditable = true;
  @Override protected void installDefaults() {
    super.installDefaults();
    //comboBox.setEditable(true);
    comboBox.setPreferredSize(new Dimension(0, 20));
    comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
    //comboBox.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
  }
  @Override protected LayoutManager createLayoutManager() {
    return new LayoutManager() {
      @Override public void addLayoutComponent(String name, Component comp) {}
      @Override public void removeLayoutComponent(Component comp) {}
      @Override public Dimension preferredLayoutSize(Container parent) {
        return parent.getPreferredSize();
      }
      @Override public Dimension minimumLayoutSize(Container parent) {
        return parent.getMinimumSize();
      }
      @Override public void layoutContainer(Container parent) {
        if(!(parent instanceof JComboBox)) return;
        JComboBox cb   = (JComboBox)parent;
        int width    = cb.getWidth();
        int height     = cb.getHeight();
        Insets insets  = cb.getInsets();
        int buttonHeight = height - (insets.top + insets.bottom);
        int buttonWidth  = buttonHeight;
        int loupeWidth   = buttonHeight;

        JButton arrowButton = (JButton)cb.getComponent(0);
        if(arrowButton != null) {
          Insets arrowInsets = arrowButton.getInsets();
          buttonWidth = arrowButton.getPreferredSize().width +
                        arrowInsets.left + arrowInsets.right;
          arrowButton.setBounds(insets.left, insets.top,
                                buttonWidth, buttonHeight);
        }
        JButton loupeButton = null;
        for(Component c: cb.getComponents()) {
          if("ComboBox.loupeButton".equals(c.getName())) {
            loupeButton = (JButton)c;
            break;
          }
        }
        //= (JButton)cb.getComponent(3);
        if(loupeButton != null) {
          Insets loupeInsets = loupeButton.getInsets();
          loupeWidth = loupeButton.getPreferredSize().width +
                       loupeInsets.left + loupeInsets.right;
          loupeButton.setBounds(width - (insets.right + loupeWidth), insets.top,
                                loupeWidth, buttonHeight);
        }
        JTextField editor = (JTextField)cb.getEditor().getEditorComponent();
        //JTextField editor = (JTextField)cb.getComponent(1);
        if(editor != null) {
          editor.setBounds(insets.left + buttonWidth, insets.top,
                   width  - (insets.left + insets.right + buttonWidth + loupeWidth),
                   height - (insets.top  + insets.bottom));
        }
      }
    };
  }
//......

References

2010/03/11

aterai

Non Selectable JComboBox Items

Code

class DisableItemComboBox< E> extends JComboBox< E> {
  private final Set< Integer> disableIndexSet = new HashSet<>();
  private boolean isDisableIndex;
  private final Action up = new AbstractAction() {
    @Override public void actionPerformed(ActionEvent e) {
      int si = getSelectedIndex();
      for (int i = si - 1; i >= 0; i--) {
        if (!disableIndexSet.contains(i)) {
          setSelectedIndex(i);
          break;
        }
      }
    }
  };
  private final Action down = new AbstractAction() {
    @Override public void actionPerformed(ActionEvent e) {
      int si = getSelectedIndex();
      for (int i = si + 1; i < getModel().getSize(); i++) {
        if (!disableIndexSet.contains(i)) {
          setSelectedIndex(i);
          break;
        }
      }
    }
  };
  public DisableItemComboBox() {
    super();
  }
  public DisableItemComboBox(ComboBoxModel< E> aModel) {
    super(aModel);
  }
  public DisableItemComboBox(E[] items) {
    super(items);
  }
  @Override public void updateUI() {
    super.updateUI();
    setRenderer(new DefaultListCellRenderer() {
      @Override public Component getListCellRendererComponent(
          JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        Component c;
        if (disableIndexSet.contains(index)) {
          c = super.getListCellRendererComponent(list, value, index, false, false);
          c.setEnabled(false);
        } else {
          c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
          c.setEnabled(true);
        }
        return c;
      }
    });
    ActionMap am = getActionMap();
    am.put("selectPrevious3", up);
    am.put("selectNext3", down);
    InputMap im = getInputMap();
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0),      "selectPrevious3");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_KP_UP, 0),   "selectPrevious3");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),    "selectNext3");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_KP_DOWN, 0), "selectNext3");
  }
  public void setDisableIndex(Set< Integer> set) {
    disableIndexSet.clear();
    for (Integer i : set) {
      disableIndexSet.add(i);
    }
  }
  @Override public void setPopupVisible(boolean v) {
    if (!v && isDisableIndex) {
      isDisableIndex = false;
    } else {
      super.setPopupVisible(v);
    }
  }
  @Override public void setSelectedIndex(int index) {
    if (disableIndexSet.contains(index)) {
      isDisableIndex = true;
    } else {
      //isDisableIndex = false;
      super.setSelectedIndex(index);
    }
  }
}

References

2009/08/17

aterai

Add JButton and JLabel to the EditorComponent of JComboBox

Code

class SiteComboBoxLayout implements LayoutManager {
  private final JLabel favicon;
  private final JButton feedButton;
  protected SiteComboBoxLayout(JLabel favicon, JButton feedButton) {
    this.favicon = favicon;
    this.feedButton = feedButton;
  }
  @Override public void addLayoutComponent(String name, Component comp) {
    /* not needed */
  }
  @Override public void removeLayoutComponent(Component comp) {
    /* not needed */
  }
  @Override public Dimension preferredLayoutSize(Container parent) {
    return parent.getPreferredSize();
  }
  @Override public Dimension minimumLayoutSize(Container parent) {
    return parent.getMinimumSize();
  }
  @Override public void layoutContainer(Container parent) {
    if (!(parent instanceof JComboBox)) {
      return;
    }
    JComboBox<?> cb = (JComboBox<?>) parent;
    int width = cb.getWidth();
    int height = cb.getHeight();
    Insets insets = cb.getInsets();
    int arrowHeight = height - insets.top - insets.bottom;
    int arrowWidth = arrowHeight;
    int faviconWidth = arrowHeight;
    int feedWidth; // = arrowHeight;

    // Arrow Icon JButton
    JButton arrowButton = (JButton) cb.getComponent(0);
    if (Objects.nonNull(arrowButton)) {
      Insets arrowInsets = arrowButton.getInsets();
      arrowWidth = arrowButton.getPreferredSize().width
        + arrowInsets.left + arrowInsets.right;
      arrowButton.setBounds(width - insets.right - arrowWidth, insets.top,
                            arrowWidth, arrowHeight);
    }

    // Favicon JLabel
    if (Objects.nonNull(favicon)) {
      Insets faviconInsets = favicon.getInsets();
      faviconWidth = favicon.getPreferredSize().width
          + faviconInsets.left + faviconInsets.right;
      favicon.setBounds(insets.left, insets.top, faviconWidth, arrowHeight);
    }


    // Feed Icon JButton
    if (Objects.nonNull(feedButton) && feedButton.isVisible()) {
      Insets feedInsets = feedButton.getInsets();
      feedWidth = feedButton.getPreferredSize().width
          + feedInsets.left + feedInsets.right;
      feedButton.setBounds(width - insets.right - feedWidth - arrowWidth, insets.top,
                           feedWidth, arrowHeight);
    } else {
      feedWidth = 0;
    }

    // JComboBox Editor
    Component editor = cb.getEditor().getEditorComponent();
    if (Objects.nonNull(editor)) {
      editor.setBounds(insets.left + faviconWidth, insets.top,
          width  - insets.left - insets.right - arrowWidth - faviconWidth - feedWidth,
          height - insets.top  - insets.bottom);
    }
  }
}

References

2009/06/26

aterai

Disable Right Click In JComboBox-Dropdown-List

Code

class BasicComboPopup2 extends BasicComboPopup {
  private Handler2 handler2;
  @Override
  public void uninstallingUI() {
    super.uninstallingUI();
    handler2 = null;
  }
  public BasicComboPopup2(JComboBox combo) {
    super(combo);
  }
  protected MouseListener createListMouseListener() {
    if(handler2==null) handler2 = new Handler2();
    return handler2;
  }
  private class Handler2 implements MouseListener{
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e)  {}
    public void mouseClicked(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {
      if(e.getSource() == list) {
        if(list.getModel().getSize() > 0) {
          if(!SwingUtilities.isLeftMouseButton(e) || !comboBox.isEnabled()) return; // <-- ins
          // JList mouse listener
          if(comboBox.getSelectedIndex() == list.getSelectedIndex()) {
            comboBox.getEditor().setItem(list.getSelectedValue());
          }
          comboBox.setSelectedIndex(list.getSelectedIndex());
        }
        comboBox.setPopupVisible(false);
        // workaround for cancelling an edited item (bug 4530953)
        if(comboBox.isEditable() && comboBox.getEditor() != null) {
          comboBox.configureEditor(comboBox.getEditor(), comboBox.getSelectedItem());
        }
      }
    }
  }
}

References

2009/06/03

aterai

Color JComboBox

Code

combo01.setModel(makeModel());
combo01.setRenderer(new MyListCellRenderer(combo01.getRenderer()));
combo01.addItemListener(new ItemListener() {
  public void itemStateChanged(ItemEvent e) {
    if(e.getStateChange()!=ItemEvent.SELECTED) return;
    combo01.setBackground(getOEColor(combo01.getSelectedIndex()));
  }
});
combo01.setSelectedIndex(0);
combo01.setBackground(evenBGColor);

final JTextField field = (JTextField) combo02.getEditor().getEditorComponent();
field.setOpaque(true);
field.setBackground(evenBGColor);
combo02.setEditable(true);
combo02.setModel(makeModel());
combo02.setRenderer(new MyListCellRenderer(combo02.getRenderer()));
combo02.addItemListener(new ItemListener() {
  public void itemStateChanged(ItemEvent e) {
    if(e.getStateChange()!=ItemEvent.SELECTED) return;
    field.setBackground(getOEColor(combo02.getSelectedIndex()));
  }
});
combo02.setSelectedIndex(0);

References

2009/05/19

aterai

Left Clipped JComboBox

Code

final JButton arrowButton = getArrowButton(combo02);
combo02.setRenderer(new DefaultListCellRenderer() {
  public Component getListCellRendererComponent(JList list, Object value, int index,
                          boolean isSelected, boolean cellHasFocus) {
    super.getListCellRendererComponent(list,value,index,isSelected,cellHasFocus);
    int itb=0, ilr=0;
    Insets insets = getInsets();
    itb+=insets.top+insets.bottom; ilr+=insets.left+insets.right;
    insets = combo02.getInsets();
    itb+=insets.top+insets.bottom; ilr+=insets.left+insets.right;
    int availableWidth = combo02.getWidth()-ilr;
    if(index < 0) {
      //@see BasicComboBoxUI#rectangleForCurrentValue
      int buttonSize = combo02.getHeight()-itb;
      if(arrowButton!=null) {
        buttonSize = arrowButton.getWidth();
      }
      availableWidth -= buttonSize;
      JTextField tf = (JTextField)combo02.getEditor().getEditorComponent();
      insets = tf.getMargin();
      availableWidth -= (insets.left + insets.right);
    }
    String cellText = (value!=null)?value.toString():"";
    //blockquote
    //@cite http://tips4java.wordpress.com/2008/11/12/left-dot-renderer/
    //@title Left Dot Renderer
    //@auther Rob Camick
    //FontMetrics fm = getFontMetrics(getFont());
    //if(fm.stringWidth(cellText) > availableWidth) {
    //  String dots = "...";
    //  int textWidth = fm.stringWidth(dots);
    //  int nChars = cellText.length() - 1;
    //  while(nChars > 0) {
    //    textWidth += fm.charWidth(cellText.charAt(nChars));
    //    if(textWidth > availableWidth) break;
    //    nChars--;
    //  }
    //  setText(dots+cellText.substring(nChars+1));
    //}
    //blockquote

    // Unicode surrogate programming with the Java language
    // http://www.ibm.com/developerworks/library/j-unicode/index.html
    FontMetrics fm = getFontMetrics(getFont());
    if (fm.stringWidth(cellText) > availableWidth) {
      String dots = "...";
      int textWidth = fm.stringWidth(dots);
      int len = cellText.length();
      int[] acp = new int[cellText.codePointCount(0, len)];
      int j = acp.length;
      for (int i = len; i > 0; i = cellText.offsetByCodePoints(i, -1)) {
        int cp = cellText.codePointBefore(i);
        textWidth += fm.charWidth(cp);
        if (textWidth > availableWidth) {
          break;
        }
        acp[--j] = cp;
      }
      setText(dots + new String(acp, j, acp.length - j));
    }
    return this;
  }
});

References

2009/01/23

aterai

create Auto Suggest JComboBox

Code

class ComboKeyHandler extends KeyAdapter {
  private final JComboBox<String> comboBox;
  private final List<String> list = new ArrayList<>();
  private boolean shouldHide;

  public ComboKeyHandler(JComboBox<String> combo) {
    super();
    this.comboBox = combo;
    for (int i = 0; i < comboBox.getModel().getSize(); i++) {
      list.add((String) comboBox.getItemAt(i));
    }
  }
  @Override public void keyTyped(final KeyEvent e) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        String text = ((JTextField) e.getComponent()).getText();
        ComboBoxModel<String> m;
        if (text.isEmpty()) {
          String[] array = list.toArray(new String[list.size()]);
          m = new DefaultComboBoxModel<String>(array);
          setSuggestionModel(comboBox, m, "");
          comboBox.hidePopup();
        } else {
          m = getSuggestedModel(list, text);
          if (m.getSize() == 0 || shouldHide) {
            comboBox.hidePopup();
          } else {
            setSuggestionModel(comboBox, m, text);
            comboBox.showPopup();
          }
        }
      }
    });
  }
  @Override public void keyPressed(KeyEvent e) {
    JTextField textField = (JTextField) e.getComponent();
    String text = textField.getText();
    shouldHide = false;
    switch (e.getKeyCode()) {
    case KeyEvent.VK_RIGHT:
      for (String s : list) {
        if (s.startsWith(text)) {
          textField.setText(s);
          return;
        }
      }
      break;
    case KeyEvent.VK_ENTER:
      if (!list.contains(text)) {
        list.add(text);
        Collections.sort(list);
        //setSuggestionModel(comboBox, new DefaultComboBoxModel(list), text);
        setSuggestionModel(comboBox, getSuggestedModel(list, text), text);
      }
      shouldHide = true;
      break;
    case KeyEvent.VK_ESCAPE:
      shouldHide = true;
      break;
    default:
      break;
    }
  }
  private static void setSuggestionModel(
      JComboBox<String> comboBox, ComboBoxModel<String> mdl, String str) {
    comboBox.setModel(mdl);
    comboBox.setSelectedIndex(-1);
    ((JTextField) comboBox.getEditor().getEditorComponent()).setText(str);
  }
  private static ComboBoxModel<String> getSuggestedModel(List<String> list, String text) {
    DefaultComboBoxModel<String> m = new DefaultComboBoxModel<>();
    for (String s : list) {
      if (s.startsWith(text)) {
        m.addElement(s);
      }
    }
    return m;
  }
}

References

2008/08/13

aterai

Multi Column JComboBox

Code

class MultiColumnCellRenderer extends JPanel implements ListCellRenderer{
  private final JLabel leftLabel = new JLabel();
  private final JLabel rightLabel;
  public MultiColumnCellRenderer(int rightWidth) {
    super(new BorderLayout());
    this.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));

    leftLabel.setOpaque(false);
    leftLabel.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));

    final Dimension dim = new Dimension(rightWidth, 0);
    rightLabel = new JLabel() {
      @Override public Dimension getPreferredSize() {
        return dim;
      }
    };
    rightLabel.setOpaque(false);
    rightLabel.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
    rightLabel.setForeground(Color.GRAY);
    rightLabel.setHorizontalAlignment(SwingConstants.RIGHT);

    this.add(leftLabel);
    this.add(rightLabel, BorderLayout.EAST);
  }
  @Override public Component getListCellRendererComponent(
      JList list, Object value, int index,
      boolean isSelected, boolean cellHasFocus) {
    LRItem item = (LRItem)value;
    leftLabel.setText(item.getLeftText());
    rightLabel.setText(item.getRightText());

    leftLabel.setFont(list.getFont());
    rightLabel.setFont(list.getFont());

    if(index<0) {
      leftLabel.setForeground(list.getForeground());
      this.setOpaque(false);
    }else{
      leftLabel.setForeground(
          isSelected?list.getSelectionForeground():list.getForeground());
      this.setBackground(
          isSelected?list.getSelectionBackground():list.getBackground());
      this.setOpaque(true);
    }
    return this;
  }
  @Override public Dimension getPreferredSize() {
    Dimension d = super.getPreferredSize();
    return new Dimension(0, d.height);
  }
  @Override public void updateUI() {
    super.updateUI();
    this.setName("List.cellRenderer");
  }
}

References