Google Tag Manager

2010/11/30

JTable CellEditor PopupMenu

Code

public static JPopupMenu installTextComponentPopupMenu(final JTextComponent tc) {
  final UndoManager manager = new UndoManager();
  final Action undoAction   = new UndoAction(manager);
  final Action redoAction   = new RedoAction(manager);
  final Action cutAction    = new DefaultEditorKit.CutAction();
  final Action copyAction   = new DefaultEditorKit.CopyAction();
  final Action pasteAction  = new DefaultEditorKit.PasteAction();
  final Action deleteAction = new AbstractAction("delete") {
    public void actionPerformed(ActionEvent e) {
      JPopupMenu pop = (JPopupMenu)e.getSource();
      ((JTextComponent)pop.getInvoker()).replaceSelection(null);
    }
  };
  tc.addAncestorListener(new AncestorListener() {
    public void ancestorAdded(AncestorEvent e) {
      manager.discardAllEdits();
      tc.requestFocusInWindow();
    }
    public void ancestorMoved(AncestorEvent e) {}
    public void ancestorRemoved(AncestorEvent e) {}
  });
  tc.getDocument().addUndoableEditListener(manager);
  tc.getActionMap().put("undo", undoAction);
  tc.getActionMap().put("redo", redoAction);
  InputMap imap = tc.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.CTRL_MASK), "undo");
  imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK), "redo");

  JPopupMenu popup = new JPopupMenu();
  popup.add(cutAction);
  popup.add(copyAction);
  popup.add(pasteAction);
  popup.add(deleteAction);
  popup.addSeparator();
  popup.add(undoAction);
  popup.add(redoAction);

  popup.addPopupMenuListener(new PopupMenuListener() {
    public void popupMenuCanceled(PopupMenuEvent e) {}
    public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
      undoAction.setEnabled(true);
      redoAction.setEnabled(true);
    }
    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
      JPopupMenu pop = (JPopupMenu)e.getSource();
      JTextField field = (JTextField)pop.getInvoker();
      boolean flg = field.getSelectedText()!=null;
      cutAction.setEnabled(flg);
      copyAction.setEnabled(flg);
      deleteAction.setEnabled(flg);
      undoAction.setEnabled(manager.canUndo());
      redoAction.setEnabled(manager.canRedo());
    }
  });
  tc.setComponentPopupMenu(popup);
  return popup;
}

References

2010/10/26

JTree node highlight search

Code

class HighlightTreeCellRenderer extends DefaultTreeCellRenderer {
  private static final Color rollOverRowColor = new Color(220, 240, 255);
  private final TreeCellRenderer renderer;
  public String q;
  public HighlightTreeCellRenderer(TreeCellRenderer renderer) {
    this.renderer = renderer;
  }

  @Override public Component getTreeCellRendererComponent(JTree tree, Object value,
        boolean isSelected, boolean expanded,
        boolean leaf, int row, boolean hasFocus) {
    JComponent c = (JComponent) renderer.getTreeCellRendererComponent(
        tree, value, isSelected, expanded, leaf, row, hasFocus);
    if (isSelected) {
      c.setOpaque(false);
      c.setForeground(getTextSelectionColor());
      // c.setBackground(Color.BLUE); // getBackgroundSelectionColor());
    } else {
      c.setOpaque(true);
      if (q != null && !q.isEmpty() && value.toString().startsWith(q)) {
        c.setForeground(getTextNonSelectionColor());
        c.setBackground(rollOverRowColor);
      } else {
        c.setForeground(getTextNonSelectionColor());
        c.setBackground(getBackgroundNonSelectionColor());
      }
    }
    return c;
  }
}

References

2010/09/21

SearchBar JComboBox

Code

public class BasicSearchBarComboBoxUI extends SearchBarComboBoxUI {
  protected boolean isEditable = true;
  public static javax.swing.plaf.ComponentUI createUI(JComponent c) {
    return new BasicSearchBarComboBoxUI();
  }

  @Override protected void installDefaults() {
    super.installDefaults();
    // comboBox.setEditable(true);
    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) {
        /* 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;
        Rectangle r = SwingUtilities.calculateInnerArea(cb, null);

        int arrowSize = 0;
        JButton arrowButton = (JButton) cb.getComponent(0);
        if (Objects.nonNull(arrowButton)) {
          Insets arrowInsets = arrowButton.getInsets();
          int bw = arrowButton.getPreferredSize().width + arrowInsets.left + arrowInsets.right;
          arrowButton.setBounds(r.x, r.y, bw, r.height);
          arrowSize = bw;
        }
        JButton loupeButton = null;
        for (Component c : cb.getComponents()) {
          if ("ComboBox.loupeButton".equals(c.getName())) {
            loupeButton = (JButton) c;
            break;
          }
        }
        int loupeSize = 0;
        if (Objects.nonNull(loupeButton)) {
          loupeSize = r.height;
          loupeButton.setBounds(r.x + r.width - loupeSize, r.y, loupeSize, r.height);
        }
        JTextField editor = (JTextField) cb.getEditor().getEditorComponent();
        if (Objects.nonNull(editor)) {
          editor.setBounds(r.x + arrowSize, r.y, r.width - arrowSize - loupeSize, r.height);
        }
      }
    };
  }
  // ...

References

2010/09/13

Placeholder for an empty JTable

Code

JEditorPane hint = new JEditorPane("text/html", ">html<>a href='dummy'<No data!>/a<>/html<");

table.setFillsViewportHeight(true);
table.setLayout(new GridBagLayout());
table.add(hint);

model.addTableModelListener(new TableModelListener() {
  @Override public void tableChanged(TableModelEvent e) {
    DefaultTableModel model = (DefaultTableModel) e.getSource();
    hint.setVisible(model.getRowCount() == 0);
  }
});

References

2010/08/16

Kinetic Scrolling JScrollPane

Code

class KineticScrollingListener2 extends MouseAdapter implements HierarchyListener {
  protected static final int SPEED = 4;
  protected static final int DELAY = 10;
  protected static final double D = .8;
  protected final JComponent label;
  protected final Point startPt = new Point();
  protected final Point delta = new Point();
  protected final Cursor dc;
  protected final Cursor hc = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
  protected final Timer inside = new Timer(DELAY, null);
  protected final Timer outside = new Timer(DELAY, null);

  protected static boolean isInside(JViewport viewport, JComponent comp) {
    Point vp = viewport.getViewPosition();
    return vp.x >= 0 && vp.x + viewport.getWidth() - comp.getWidth() <= 0
        && vp.y >= 0 && vp.y + viewport.getHeight() - comp.getHeight() <= 0;
  }

  protected KineticScrollingListener2(JComponent comp) {
    super();
    this.label = comp;
    this.dc = comp.getCursor();
    inside.addActionListener(e -> dragInside());
    outside.addActionListener(e -> dragOutside());
  }

  private void dragInside() {
    JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
    Point vp = viewport.getViewPosition();
    // System.out.format("s: %s, %s%n", delta, vp);
    vp.translate(-delta.x, -delta.y);
    viewport.setViewPosition(vp);
    if (Math.abs(delta.x) > 0 || Math.abs(delta.y) > 0) {
      delta.setLocation((int) (delta.x * D), (int) (delta.y * D));
      // Outside
      if (vp.x < 0 || vp.x + viewport.getWidth() - label.getWidth() > 0) {
        delta.x = (int) (delta.x * D);
      }
      if (vp.y < 0 || vp.y + viewport.getHeight() - label.getHeight() > 0) {
        delta.y = (int) (delta.y * D);
      }
    } else {
      inside.stop();
      if (!isInside(viewport, label)) {
        outside.start();
      }
    }
  }

  private void dragOutside() {
    JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
    Point vp = viewport.getViewPosition();
    // System.out.format("r: %s%n", vp);
    if (vp.x < 0) {
      vp.x = (int) (vp.x * D);
    }
    if (vp.y < 0) {
      vp.y = (int) (vp.y * D);
    }
    if (vp.x + viewport.getWidth() - label.getWidth() > 0) {
      vp.x = (int) (vp.x - (vp.x + viewport.getWidth() - label.getWidth()) * (1d - D));
    }
    if (vp.y + viewport.getHeight() > label.getHeight()) {
      vp.y = (int) (vp.y - (vp.y + viewport.getHeight() - label.getHeight()) * (1d - D));
    }
    viewport.setViewPosition(vp);
    if (isInside(viewport, label)) {
      outside.stop();
    }
  }

  @Override public void mousePressed(MouseEvent e) {
    e.getComponent().setCursor(hc);
    startPt.setLocation(e.getPoint());
    inside.stop();
    outside.stop();
  }

  @Override public void mouseDragged(MouseEvent e) {
    Point pt = e.getPoint();
    JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
    Point vp = viewport.getViewPosition();
    vp.translate(startPt.x - pt.x, startPt.y - pt.y);
    viewport.setViewPosition(vp);
    delta.setLocation(SPEED * (pt.x - startPt.x), SPEED * (pt.y - startPt.y));
    startPt.setLocation(pt);
  }

  @Override public void mouseReleased(MouseEvent e) {
    e.getComponent().setCursor(dc);
    JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
    if (isInside(viewport, label)) {
      inside.start();
    } else {
      outside.start();
    }
  }

  @Override public void hierarchyChanged(HierarchyEvent e) {
    Component c = e.getComponent();
    if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0
        && !c.isDisplayable()) {
      inside.stop();
      outside.stop();
    }
  }
}

References