Google Tag Manager

2014/03/27

Long pressing the JButton to get a JPopupMenu

Code

class PressAndHoldHandler extends AbstractAction implements MouseListener {
  public final JPopupMenu pop = new JPopupMenu();
  public final ButtonGroup bg = new ButtonGroup();
  private AbstractButton arrowButton;
  private final Timer holdTimer = new Timer(1000, e -> {
    if (arrowButton != null && arrowButton.getModel().isPressed()
        && holdTimer.isRunning()) {
      holdTimer.stop();
      pop.show(arrowButton, 0, arrowButton.getHeight());
      pop.requestFocusInWindow();
    }
  });

  public PressAndHoldHandler() {
    super();
    holdTimer.setInitialDelay(1000);
    pop.setLayout(new GridLayout(0, 3, 5, 5));
    for (MenuContext m: makeMenuList()) {
      AbstractButton b = new JRadioButton(m.command);
      b.setActionCommand(m.command);
      b.setForeground(m.color);
      b.setBorder(BorderFactory.createEmptyBorder());
      b.addActionListener(e -> {
        System.out.println(e.getActionCommand());
        pop.setVisible(false);
      });
      pop.add(b);
      bg.add(b);
    }
  }

  private List<MenuContext> makeMenuList() {
    return Arrays.asList(
      new MenuContext("BLACK", Color.BLACK),
      new MenuContext("BLUE", Color.BLUE),
      new MenuContext("CYAN", Color.CYAN),
      new MenuContext("GREEN", Color.GREEN),
      new MenuContext("MAGENTA", Color.MAGENTA),
      new MenuContext("ORANGE", Color.ORANGE),
      new MenuContext("PINK", Color.PINK),
      new MenuContext("RED", Color.RED),
      new MenuContext("YELLOW", Color.YELLOW));
  }

  @Override public void actionPerformed(ActionEvent e) {
    System.out.println("actionPerformed");
    if (holdTimer.isRunning()) {
      ButtonModel model = bg.getSelection();
      if (model != null) {
        System.out.println(model.getActionCommand());
      }
      holdTimer.stop();
    }
  }

  @Override public void mousePressed(MouseEvent e) {
    System.out.println("mousePressed");
    Component c = e.getComponent();
    if (SwingUtilities.isLeftMouseButton(e) && c.isEnabled()) {
      arrowButton = (AbstractButton) c;
      holdTimer.start();
    }
  }

  @Override public void mouseReleased(MouseEvent e) {
    holdTimer.stop();
  }

  @Override public void mouseExited(MouseEvent e) {
    if (holdTimer.isRunning()) {
      holdTimer.stop();
    }
  }

  @Override public void mouseEntered(MouseEvent e) {
    /* not needed */
  }

  @Override public void mouseClicked(MouseEvent e) {
    /* not needed */
  }
}

References

2014/02/26

Translucent JFrame repaint

Code

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
JLabel label = new JLabel(LocalTime.now().format(formatter), SwingConstants.CENTER);
Timer timer = new Timer(100, null);
timer.addActionListener(e -> {
  label.setText(LocalTime.now().format(formatter));
  Container parent = SwingUtilities.getUnwrappedParent(label);
  if (Objects.nonNull(parent) && parent.isOpaque()) {
    repaintWindowAncestor(label);
  }
});
// ...
private void repaintWindowAncestor(JComponent c) {
  JRootPane root = c.getRootPane();
  if (root == null) {
    return;
  }
  Rectangle r = SwingUtilities.convertRectangle(c, c.getBounds(), root);
  root.repaint(r.x, r.y, r.width, r.height);
}

References

2014/01/30

Use JTree as the table of contents

Code

class TableOfContentsTreeCellRenderer extends DefaultTreeCellRenderer {
  private static BasicStroke READER = new BasicStroke(
    1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
    1f, new float[] { 1f }, 0f);
  private String pn;
  private Point pnPt = new Point();
  private int rxs, rxe, ry;
  private boolean isSynth = false;
  private final JPanel p = new JPanel(new BorderLayout()) {
    @Override protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (pn != null) {
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setColor(isSynth ? getForeground() : getTextNonSelectionColor());
        g2.drawString(pn, pnPt.x - getX(), pnPt.y);
        g2.setStroke(READER);
        g2.drawLine(rxs, pnPt.y, rxe - getX(), pnPt.y);
        g2.dispose();
      }
    }

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

  public TableOfContentsTreeCellRenderer() {
    super();
    p.setOpaque(false);
  }

  @Override public void updateUI() {
    super.updateUI();
    isSynth = getUI().getClass().getName().contains("Synth");
    if (isSynth) {
      //System.out.println("XXX: FocusBorder bug?, JDK 1.7.0, Nimbus start LnF");
      setBackgroundSelectionColor(new Color(0x0, true));
    }
  }

  @Override public Component getTreeCellRendererComponent(
      JTree tree, Object value, boolean selected, boolean expanded,
      boolean leaf, int row, boolean hasFocus) {
    JLabel l = (JLabel) super.getTreeCellRendererComponent(
        tree, value, selected, expanded, leaf, row, hasFocus);
    if (value instanceof DefaultMutableTreeNode) {
      DefaultMutableTreeNode n = (DefaultMutableTreeNode) value;
      Object o = n.getUserObject();
      if (o instanceof TableOfContents) {
        TableOfContents toc = (TableOfContents) o;
        FontMetrics metrics = l.getFontMetrics(l.getFont());
        int gap = l.getIconTextGap();
        int h = l.getPreferredSize().height;
        Insets ins = tree.getInsets();

        p.removeAll();
        p.add(l, BorderLayout.WEST);
        if (isSynth) p.setForeground(l.getForeground());

        pn = String.format("%3d", toc.page);
        pnPt.x = tree.getWidth() - metrics.stringWidth(pn) - gap;
        pnPt.y = (h + metrics.getAscent()) / 2;

        rxs = l.getPreferredSize().width + gap;
        rxe = tree.getWidth() - ins.right - metrics.stringWidth("000") - gap;
        ry  = h / 2;

        return p;
      }
    }
    pn = null;
    return l;
  }
}

References

2013/12/09

Breadcrumb Navigation with JRadioButton

Code

private static JComponent makeBreadcrumbList(int overlap, List<String> list) {
  JPanel p = new JPanel(new FlowLayout(FlowLayout.LEADING, -overlap, 0));
  p.setBorder(BorderFactory.createEmptyBorder(4, overlap + 4, 4, 4));
  p.setOpaque(false);
  ButtonGroup bg = new ButtonGroup();
  for (String title: list) {
    AbstractButton b = makeButton(title, Color.PINK);
    p.add(b);
    bg.add(b);
  }
  return p;
}

References

2013/11/25

Cut copy paste buttuns in the JMenuItem

Code

private static JMenuItem makeEditMenuItem(final JComponent edit) {
  JMenuItem item = new JMenuItem("Edit") {
    @Override public Dimension getPreferredSize() {
      Dimension d = super.getPreferredSize();
      d.width += edit.getPreferredSize().width;
      d.height = Math.max(edit.getPreferredSize().height, d.height);
      return d;
    }

    @Override protected void fireStateChanged() {
      setForeground(Color.BLACK);
      super.fireStateChanged();
    }
  };
  item.setEnabled(false);

  GridBagConstraints c = new GridBagConstraints();
  item.setLayout(new GridBagLayout());
  c.anchor  = GridBagConstraints.LINE_END;
  c.weightx = 1d;

  c.fill = GridBagConstraints.HORIZONTAL;
  item.add(Box.createHorizontalGlue(), c);
  c.fill = GridBagConstraints.NONE;
  item.add(edit, c);

  return item;
}

private static JPanel makeEditButtonBar(List<AbstractButton> list) {
  int size = list.size();
  JPanel p = new JPanel(new GridLayout(1, size, 0, 0)) {
    @Override public Dimension getMaximumSize() {
      return super.getPreferredSize();
    }
  };
  for (AbstractButton b: list) {
    b.setIcon(new ToggleButtonBarCellIcon());
    p.add(b);
  }
  p.setBorder(BorderFactory.createEmptyBorder(4, 10, 4, 10));
  p.setOpaque(false);
  return p;
}

private static AbstractButton makeButton(String title, Action action) {
  JButton b = new JButton(action);
  b.addActionListener(new ActionListener() {
    @Override public void actionPerformed(ActionEvent e) {
      JButton b = (JButton) e.getSource();
      Container c = SwingUtilities.getAncestorOfClass(JPopupMenu.class, b);
      if (c instanceof JPopupMenu) {
        ((JPopupMenu) c).setVisible(false);
      }
    }
  });
  b.setText(title);
  b.setVerticalAlignment(SwingConstants.CENTER);
  b.setVerticalTextPosition(SwingConstants.CENTER);
  b.setHorizontalAlignment(SwingConstants.CENTER);
  b.setHorizontalTextPosition(SwingConstants.CENTER);
  b.setBorder(BorderFactory.createEmptyBorder());
  b.setContentAreaFilled(false);
  b.setFocusPainted(false);
  b.setOpaque(false);
  b.setBorder(BorderFactory.createEmptyBorder());
  return b;
}

References