Google Tag Manager

2012/10/29

Delete button in a JComboBox popup menu items

Code

class CellButtonsMouseListener extends MouseAdapter {
  @Override public void mouseMoved(MouseEvent e) {
    JList<?> list = (JList<?>) e.getComponent();
    Point pt = e.getPoint();
    int index = list.locationToIndex(pt);
    ButtonsRenderer<?> renderer = (ButtonsRenderer<?>) list.getCellRenderer();
    renderer.rolloverIndex = Objects.nonNull(getButton(list, pt, index)) ? index : -1;
    list.repaint();
  }

  @Override public void mousePressed(MouseEvent e) {
    e.getComponent().repaint();
  }

  @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();
      }
    }
    ((ButtonsRenderer<?>) list.getCellRenderer()).rolloverIndex = -1;
    list.repaint();
  }

  @Override public void mouseExited(MouseEvent e) {
    JList<?> list = (JList<?>) e.getComponent();
    ((ButtonsRenderer<?>) list.getCellRenderer()).rolloverIndex = -1;
  }

  private static <E> JButton getButton(JList<E> list, Point pt, int index) {
    E proto = list.getPrototypeCellValue();
    Component c = list.getCellRenderer().getListCellRendererComponent(
        list, proto, 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);
    return Optional.ofNullable(SwingUtilities.getDeepestComponentAt(c, pt.x, pt.y))
        .filter(JButton.class::isInstance).map(JButton.class::cast).orElse(null);
  }
}

References

2012/09/24

create a gradient titled separator

Code

class TitledSeparator extends JLabel {
  private final String title;
  private final Color target;
  private final int height;
  private final int titlePosition;

  public TitledSeparator(String title, int height, int titlePosition) {
    this(title, null, height, titlePosition);
  }

  public TitledSeparator(
      String title, Color target, int height, int titlePosition) {
    super();
    this.title = title;
    this.target = target;
    this.height = height;
    this.titlePosition = titlePosition;
    updateBorder();
  }

  private void updateBorder() {
    Icon icon = new TitledSeparatorIcon();
    setBorder(BorderFactory.createTitledBorder(
        BorderFactory.createMatteBorder(height, 0, 0, 0, icon), title,
        TitledBorder.DEFAULT_JUSTIFICATION, titlePosition));
  }

  @Override public Dimension getMaximumSize() {
    Dimension d = super.getPreferredSize();
    d.width = Short.MAX_VALUE;
    return d;
  }

  @Override public void updateUI() {
    super.updateUI();
    EventQueue.invokeLater(this::updateBorder);
  }

  private class TitledSeparatorIcon implements Icon {
    private int width = -1;
    private Paint painter1;
    private Paint painter2;

    @Override public void paintIcon(Component c, Graphics g, int x, int y) {
      int w = c.getWidth();
      if (w != width || painter1 == null || painter2 == null) {
        width = w;
        Point2D start = new Point2D.Float();
        Point2D end = new Point2D.Float(width, 0);
        float[] dist = {0f, 1f};
        Color ec = Optional.ofNullable(getBackground())
            .orElse(UIManager.getColor("Panel.background"));
        Color sc = Optional.ofNullable(target).orElse(ec);
        painter1 = new LinearGradientPaint(
            start, end, dist, new Color[] {sc.darker(), ec});
        painter2 = new LinearGradientPaint(
            start, end, dist, new Color[] {sc.brighter(), ec});
      }
      int h = getIconHeight() / 2;
      Graphics2D g2  = (Graphics2D) g.create();
      g2.setPaint(painter1);
      g2.fillRect(x, y, width, getIconHeight());
      g2.setPaint(painter2);
      g2.fillRect(x, y + h, width, getIconHeight() - h);
      g2.dispose();
    }

    @Override public int getIconWidth() {
      return 200; // sample width
    }

    @Override public int getIconHeight() {
      return height;
    }
  }
}

References

2012/08/17

JFileChooser with file already exists Dialog

Code

JFileChooser fileChooser = new JFileChooser() {
  @Override public void approveSelection() {
    File f = getSelectedFile();
    if (f.exists() && getDialogType() == SAVE_DIALOG) {
      String m = String.format(
          "<html>%s already exists.<br>Do you want to replace it?",
          f.getAbsolutePath());
      int rv = JOptionPane.showConfirmDialog(
          this, m, "Save As", JOptionPane.YES_NO_OPTION);
      if (rv != JOptionPane.YES_OPTION) {
        return;
      }
    }
    super.approveSelection();
  }
};

References

2012/07/04

Translucent JPopupMenu

Code

class TranslucentPopupMenu extends JPopupMenu {
  private static final Color ALPHA_ZERO = new Color(0x0, true);
  private static final Color POPUP_BACK = new Color(250, 250, 250, 200);
  private static final Color POPUP_LEFT = new Color(230, 230, 230, 200);
  private static final int LEFT_WIDTH = 24;
  @Override public boolean isOpaque() {
    return false;
  }

  @Override public void updateUI() {
    super.updateUI();
    if (UIManager.getBorder("PopupMenu.border") == null) {
      setBorder(new BorderUIResource(BorderFactory.createLineBorder(Color.GRAY)));
    }
  }

  @Override public JMenuItem add(JMenuItem menuItem) {
    menuItem.setOpaque(false);
    // menuItem.setBackground(ALPHA_ZERO);
    return super.add(menuItem);
  }

  @Override public void show(Component c, int x, int y) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        Window p = SwingUtilities.getWindowAncestor(TranslucentPopupMenu.this);
        if (p instanceof JWindow) {
          System.out.println("Heavy weight");
          JWindow w = (JWindow) p;
          w.setBackground(ALPHA_ZERO);
        } else {
          System.out.println("Light weight");
        }
      }
    });
    super.show(c, x, y);
  }

  @Override protected void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setPaint(POPUP_LEFT);
    g2.fillRect(0, 0, LEFT_WIDTH, getHeight());
    g2.setPaint(POPUP_BACK);
    g2.fillRect(LEFT_WIDTH, 0, getWidth(), getHeight());
    g2.dispose();
    //super.paintComponent(g);
  }
}

References

2012/07/02

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 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);
    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