Google Tag Manager

2009/12/21

snap to ticks drag JSlider

Code

slider.setUI(new MetalSliderUI() {
  @Override protected TrackListener createTrackListener(final JSlider slider) {
    return new TrackListener() {
      @Override public void mouseDragged(MouseEvent e) {
        if (!slider.getSnapToTicks() || slider.getMajorTickSpacing() == 0) {
          super.mouseDragged(e);
          return;
        }
        // case SwingConstants.HORIZONTAL:
        int halfThumbWidth = thumbRect.width / 2;
        final int trackLength = trackRect.width;
        final int trackLeft = trackRect.x - halfThumbWidth;
        final int trackRight = trackRect.x + trackRect.width - 1 + halfThumbWidth;
        int xPos = e.getX();
        int snappedPos = xPos;
        if (xPos <= trackLeft) {
          snappedPos = trackLeft;
        } else if (xPos >= trackRight) {
          snappedPos = trackRight;
        } else {
          // int tickSpacing = slider.getMajorTickSpacing();
          // float actualPixelsForOneTick =
          //     trackLength * tickSpacing / (float) slider.getMaximum();

          // a problem if you choose to set a negative MINIMUM for the JSlider;
          // the calculated drag-positions are wrong.
          // Fixed by bobndrew:
          int possibleTickPositions = slider.getMaximum() - slider.getMinimum();
          int tickSpacing = (slider.getMinorTickSpacing() == 0)
              ? slider.getMajorTickSpacing()
              : slider.getMinorTickSpacing();
          float actualPixelsForOneTick =
              trackLength * tickSpacing / (float) possibleTickPositions;
          xPos -= trackLeft;
          snappedPos = (int) (Math.round(
              xPos / actualPixelsForOneTick) * actualPixelsForOneTick + .5) + trackLeft;
          offset = 0;
          // System.out.println(snappedPos);
        }
        e.translatePoint(snappedPos - e.getX(), 0);
        super.mouseDragged(e);
      }
    };
  }
});

References

2009/11/30

Jump to clicked position JSlider

Code

slider.setUI(new MetalSliderUI() {
  @Override protected TrackListener createTrackListener(JSlider slider) {
    return new TrackListener() {
      @Override public void mousePressed(MouseEvent e) {
        if (UIManager.getBoolean("Slider.onlyLeftMouseButtonDrag")
              && SwingUtilities.isLeftMouseButton(e)) {
          JSlider slider = (JSlider) e.getComponent();
          switch (slider.getOrientation()) {
          case SwingConstants.VERTICAL:
            slider.setValue(valueForYPosition(e.getY()));
            break;
          case SwingConstants.HORIZONTAL:
            slider.setValue(valueForXPosition(e.getX()));
            break;
          default:
            throw new IllegalArgumentException(
                "orientation must be one of: VERTICAL, HORIZONTAL");
          }
          super.mousePressed(e); //isDragging = true;
          super.mouseDragged(e);
        } else {
          super.mousePressed(e);
        }
      }

      @Override public boolean shouldScroll(int direction) {
        return false;
      }
    };
  }
});

References

2009/11/13

add JInternalFrame to Undecorated JFrame

Code

JInternalFrame internal = new JInternalFrame("...");
BasicInternalFrameUI ui = (BasicInternalFrameUI) internal.getUI();
Component title = ui.getNorthPane();
for (MouseMotionListener l: title.getListeners(MouseMotionListener.class)) {
  title.removeMouseMotionListener(l);
}
DragWindowListener dwl = new DragWindowListener();
title.addMouseListener(dwl);
title.addMouseMotionListener(dwl);
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(new JTree()));
p.add(new JButton(new AbstractAction("close") {
  @Override public void actionPerformed(ActionEvent e) {
    Window w = SwingUtilities.windowForComponent((Component) e.getSource());
    // w.dispose();
    w.getToolkit().getSystemEventQueue().postEvent(
      new WindowEvent(w, WindowEvent.WINDOW_CLOSING));
  }
}), BorderLayout.SOUTH);
internal.getContentPane().add(p);
internal.setVisible(true);

KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(e -> {
  String prop = e.getPropertyName();
  if ("activeWindow".equals(prop)) {
    try {
      internal.setSelected(Objects.nonNull(e.getNewValue()));
    } catch (PropertyVetoException ex) {
      throw new IllegalStateException(ex);
    }
  }
});

References

2009/10/29

JCheckBoxMenuItem Icon

Code

UIManager.put("CheckBoxMenuItem.checkIcon", new Icon() {
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.translate(x, y);
    ButtonModel m = ((AbstractButton) c).getModel();
    g2.setPaint(m.isSelected() ? Color.ORANGE : Color.GRAY);
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.fillOval(0, 2, 10, 10);
    g2.dispose();
  }

  @Override public int getIconWidth()  {
    return 14;
  }

  @Override public int getIconHeight() {
    return 14;
  }
});
menu.add(new JCheckBoxMenuItem("checkIcon test"));

References

2009/10/06

Multiple JButtons in a JTable cell

Code

class ButtonsPanel extends JPanel {
  public final List<JButton> buttons =
    Arrays.asList(new JButton("view"), new JButton("edit"));
  public ButtonsPanel() {
    super();
    setOpaque(true);
    for (JButton b: buttons) {
      b.setFocusable(false);
      b.setRolloverEnabled(false);
      add(b);
    }
  }
}

class ButtonsRenderer extends ButtonsPanel
                      implements TableCellRenderer {
  public ButtonsRenderer() {
    super();
    setName("Table.cellRenderer");
  }

  @Override public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected,
      boolean hasFocus, int row, int column) {
    Color bgc = isSelected ? table.getSelectionBackground()
                           : table.getBackground()
    setBackground(bgc);
    return this;
  }
}

class ButtonsEditor extends ButtonsPanel
                    implements TableCellEditor {
  public ButtonsEditor(final JTable table) {
    super();
    // ---->
    // DEBUG: view button click
    //   -> control key down + edit button(same cell) press
    //   -> remain selection color
    MouseListener ml = new MouseAdapter() {
      @Override public void mousePressed(MouseEvent e) {
        ButtonModel m = ((JButton) e.getSource()).getModel();
        if (m.isPressed() && table.isRowSelected(table.getEditingRow())
                          && e.isControlDown()) {
          setBackground(table.getBackground());
        }
      }
    };
    buttons.get(0).addMouseListener(ml);
    buttons.get(1).addMouseListener(ml);
    // <----

    buttons.get(0).addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        fireEditingStopped();
        JOptionPane.showMessageDialog(table, "Viewing");
      }
    });

    buttons.get(1).addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        int row = table.convertRowIndexToModel(table.getEditingRow());
        Object o = table.getModel().getValueAt(row, 0);
        fireEditingStopped();
        JOptionPane.showMessageDialog(table, "Editing: " + o);
      }
    });

    addMouseListener(new MouseAdapter() {
      @Override public void mousePressed(MouseEvent e) {
        fireEditingStopped();
      }
    });
  }

  @Override public Component getTableCellEditorComponent(JTable table,
        Object value, boolean isSelected, int row, int column) {
    this.setBackground(table.getSelectionBackground());
    return this;
  }

  @Override public Object getCellEditorValue() {
    return "";
  }

  // Copied from AbstractCellEditor
  // protected EventListenerList listenerList = new EventListenerList();
  transient protected ChangeEvent changeEvent = null;
  @Override public boolean isCellEditable(java.util.EventObject e) {
    return true;
  }
// ...

References

2009/09/28

Drag rows from one JTable to another JTable

Code

class TableRowTransferHandler extends TransferHandler {
  private final DataFlavor localObjectFlavor;
  private int[] indices;
  private int addIndex = -1; // Location where items were added
  private int addCount; // Number of items added.
  private JComponent source;

  public TableRowTransferHandler() {
    super();
    localObjectFlavor = new DataFlavor(Object[].class, "Array of items");
  }

  @Override protected Transferable createTransferable(JComponent c) {
    source = c;
    JTable table = (JTable) c;
    DefaultTableModel model = (DefaultTableModel) table.getModel();
    List<Object> list = new ArrayList<>();
    indices = table.getSelectedRows();
    for (int i : indices) {
      list.add(model.getDataVector().elementAt(i));
    }
    Object[] transferredObjects = list.toArray();
    return new Transferable() {
      @Override public DataFlavor[] getTransferDataFlavors() {
        return new DataFlavor[] {FLAVOR};
      }

      @Override public boolean isDataFlavorSupported(DataFlavor flavor) {
        return Objects.equals(FLAVOR, flavor);
      }

      @Override public Object getTransferData(DataFlavor flavor)
            throws UnsupportedFlavorException, IOException {
        if (isDataFlavorSupported(flavor)) {
          return nodes;
        } else {
          throw new UnsupportedFlavorException(flavor);
        }
      }
    };
  }

  @Override public boolean canImport(TransferSupport info) {
    JTable table = (JTable) info.getComponent();
    boolean isDroppable = info.isDrop()
      && info.isDataFlavorSupported(localObjectFlavor);
    // XXX bug?
    table.setCursor(isDroppable ? DragSource.DefaultMoveDrop
                                : DragSource.DefaultMoveNoDrop);
    return isDroppable;
  }

  @Override public int getSourceActions(JComponent c) {
    return TransferHandler.MOVE; //TransferHandler.COPY_OR_MOVE;
  }

  @Override public boolean importData(TransferSupport info) {
    TransferHandler.DropLocation tdl = info.getDropLocation();
    if (!(tdl instanceof JTable.DropLocation)) {
      return false;
    }
    JTable.DropLocation dl = (JTable.DropLocation) tdl;
    JTable target = (JTable) info.getComponent();
    DefaultTableModel model = (DefaultTableModel) target.getModel();
    int index = dl.getRow();
    // boolean insert = dl.isInsert();
    int max = model.getRowCount();
    if (index < 0 || index > max) {
      index = max;
    }
    addIndex = index;
    target.setCursor(Cursor.getDefaultCursor());
    try {
      Object[] values =
        (Object[]) info.getTransferable().getTransferData(localObjectFlavor);
      if (Objects.equals(source, target)) {
        addCount = values.length;
      }
      for (int i = 0; i < values.length; i++) {
        int idx = index++;
        // model.insertRow(idx, (Vector<?>) values[i]);
        model.insertRow(i, ((List<?>) o).toArray(new Object[0]));
        target.getSelectionModel().addSelectionInterval(idx, idx);
      }
      return true;
    } catch (UnsupportedFlavorException | IOException ex) {
      ex.printStackTrace();
    }
    return false;
  }

  @Override protected void exportDone(
      JComponent c, Transferable data, int action) {
    cleanup(c, action == MOVE);
  }

  private void cleanup(JComponent c, boolean remove) {
    if (remove && indices != null) {
      c.setCursor(Cursor.getDefaultCursor());
      DefaultTableModel model = (DefaultTableModel) ((JTable) c).getModel();
      if (addCount > 0) {
        for (int i = 0; i < indices.length; i++) {
          if (indices[i] >= addIndex) {
            indices[i] += addCount;
          }
        }
      }
      for (int i = indices.length - 1; i >= 0; i--) {
        model.removeRow(indices[i]);
      }
    }
    indices = null;
    addCount = 0;
    addIndex = -1;
  }
}

References

2009/08/17

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/08/12

JMenuBar Background Image

Code

public JMenuBar createMenubar() {
  final TexturePaint texture = makeTexturePaint();
  JMenuBar mb = new JMenuBar() {
    @Override protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setPaint(texture);
      g2.fillRect(0, 0, getWidth(), getHeight());
      g2.dispose();
    }
  };
  mb.setOpaque(false);
  String[] menuKeys = {"File", "Edit", "Help"};
  for (String key: menuKeys) {
    JMenu m = createMenu(key);
    if (m != null) {
      mb.add(m);
    }
  }
  return mb;
}

private JMenu createMenu(String key) {
  JMenu menu = new JMenu(key) {
    @Override protected void fireStateChanged() {
      ButtonModel m = getModel();
      if (m.isPressed() && m.isArmed()) {
        setOpaque(true);
      } else if (m.isSelected()) {
        setOpaque(true);
      } else if (isRolloverEnabled() && m.isRollover()) {
        setOpaque(true);
      } else {
        setOpaque(false);
      }
      super.fireStateChanged();
    };
  };
  if ("Windows XP".equals(System.getProperty("os.name"))) {
    menu.setBackground(new Color(0x0, true)); // XXX: Windows XP lnf?
  }
  menu.add("JMenuItem1");
  menu.add("JMenuItem2");
  menu.add("JMenuItem3");
  return menu;
}

References

2009/06/26

Disable Right Click In JComboBox-Dropdown-List

Code

class BasicComboPopup2 extends BasicComboPopup {
  private transient Handler2 handler2;

  public BasicComboPopup2(JComboBox combo) {
    super(combo);
  }

  @Override public void uninstallingUI() {
    super.uninstallingUI();
    handler2 = null;
  }

  @Override protected MouseListener createListMouseListener() {
    if (handler2 == null) {
      handler2 = new Handler2();
    }
    return handler2;
  }

  private class Handler2 extends MouseAdapter {
    @Override public void mouseReleased(MouseEvent e) {
      if (e.getSource().equals(list)) {
        if (list.getModel().getSize() > 0) {
          // <ins>
          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/10

New Tab Button

Code

class TabLayout implements LayoutManager, Serializable {
  private static final long serialVersionUID = 1L;
  private static final int TAB_WIDTH = 100;
  @Override public void addLayoutComponent(String name, Component comp) {
    /* not needed */
  }

  @Override public void removeLayoutComponent(Component comp) {
    /* not needed */
  }

  @Override public Dimension preferredLayoutSize(Container parent) {
    synchronized (parent.getTreeLock()) {
      Insets insets = parent.getInsets();
      int last = parent.getComponentCount() - 1;
      int w = 0;
      int h = 0;
      if (last >= 0) {
        Component comp = parent.getComponent(last);
        Dimension d = comp.getPreferredSize();
        w = d.width;
        h = d.height;
      }
      return new Dimension(insets.left + insets.right + w,
                           insets.top + insets.bottom + h);
    }
  }

  @Override public Dimension minimumLayoutSize(Container parent) {
    synchronized (parent.getTreeLock()) {
      return new Dimension(100, 24);
    }
  }

  @Override public void layoutContainer(Container parent) {
    synchronized (parent.getTreeLock()) {
      int ncomponents = parent.getComponentCount();
      if (ncomponents == 0) {
        return;
      }
      // int nrows = 1;
      // boolean ltr = parent.getComponentOrientation().isLeftToRight();
      Insets insets = parent.getInsets();
      int ncols = ncomponents - 1;
      int lastw = parent.getComponent(ncomponents - 1).getPreferredSize().width;
      int width = parent.getWidth() - insets.left - insets.right - lastw;
      int h = parent.getHeight() - insets.top - insets.bottom;
      int w = width > TAB_WIDTH * ncols ? TAB_WIDTH : width / ncols;
      int gap = width - w * ncols;
      int x = insets.left;
      int y = insets.top;
      for (int i = 0; i < ncomponents; i++) {
        int cw = i == ncols ? lastw : w + (gap-- > 0 ? 1 : 0);
        parent.getComponent(i).setBounds(x, y, cw, h);
        x += cw;
      }
    }
  }

  @Override public String toString() {
    return getClass().getName();
  }
}

References

2009/06/03

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

Left Clipped JComboBox

Code

final JButton arrowButton = getArrowButton(combo02);
combo02.setRenderer(new DefaultListCellRenderer() {
  @Override 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="https://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>
    return this;
  }
});

References

2009/04/06

Animating JTable Rows

Code

public void createActionPerformed(JTable table, DefaultTableModel model) {
  model.addRow(new Object[] {"New name", model.getRowCount(), false});
  int index = table.convertRowIndexToView(model.getRowCount() - 1);
  AtomicInteger height = new AtomicInteger(START_HEIGHT);
  new Timer(DELAY, e -> {
    int h = height.getAndIncrement();
    if (h < END_HEIGHT) {
      table.setRowHeight(index, h);
    } else {
      ((Timer) e.getSource()).stop();
    }
  }).start();
}

public void deleteActionPerformed(JTable table, DefaultTableModel model) {
  int[] selection = table.getSelectedRows();
  if (selection.length == 0) {
    return;
  }
  AtomicInteger height = new AtomicInteger(END_HEIGHT);
  new Timer(DELAY, e -> {
    int h = height.getAndDecrement();
    if (h > START_HEIGHT) {
      for (int i = selection.length - 1; i >= 0; i--) {
        table.setRowHeight(selection[i], h);
      }
    } else {
      ((Timer) e.getSource()).stop();
      for (int i = selection.length - 1; i >= 0; i--) {
        model.removeRow(table.convertRowIndexToModel(selection[i]));
      }
    }
  }).start();
}

References

2009/03/23

Mouse Dragging ViewPort Scroll

Code

MouseAdapter hsl1 = new HandScrollListener();
vport.addMouseMotionListener(hsl1);
vport.addMouseListener(hsl1);

MouseAdapter hsl2 = new DragScrollListener();
label.addMouseMotionListener(hsl2);
label.addMouseListener(hsl2);

class HandScrollListener extends MouseAdapter {
  private final Cursor defCursor = Cursor.getDefaultCursor();
  private final Cursor hndCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
  private final Point pp = new Point();

  @Override public void mouseDragged(MouseEvent e) {
    JViewport vport = (JViewport) e.getComponent();
    Point cp = e.getPoint();
    Rectangle rect = vport.getViewRect();
    rect.translate(pp.x - cp.x, pp.y - cp.y);
    label.scrollRectToVisible(rect);
    pp.setLocation(cp);
  }

  @Override public void mousePressed(MouseEvent e) {
    e.getComponent().setCursor(hndCursor);
    pp.setLocation(e.getPoint());
  }

  @Override public void mouseReleased(MouseEvent e) {
    e.getComponent().setCursor(defCursor);
  }
}

class DragScrollListener extends MouseAdapter {
  private final Cursor defCursor = Cursor.getDefaultCursor();
  private final Cursor hndCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
  private final Point pp = new Point();

  @Override public void mouseDragged(MouseEvent e) {
    Component c = e.getComponent();
    Container p = SwingUtilities.getUnwrappedParent(c);
    if (p instanceof JViewport) {
      JViewport viewport = (JViewport) p;
      Point cp = SwingUtilities.convertPoint(c, e.getPoint(), viewport);
      Rectangle rect = viewport.getViewPosition();
      rect.translate(pp.x - cp.x, pp.y - cp.y);
      ((JComponent) c).scrollRectToVisible(rect);
      pp.setLocation(cp);
    }
  }

  @Override public void mousePressed(MouseEvent e) {
    Component c = e.getComponent();
    c.setCursor(hndCursor);
    Container p = SwingUtilities.getUnwrappedParent(c);
    if (p instanceof JViewport) {
      JViewport viewport = (JViewport) p;
      Point cp = SwingUtilities.convertPoint(c, e.getPoint(), viewport);
      pp.setLocation(cp);
    }
  }

  @Override public void mouseReleased(MouseEvent e) {
    e.getComponent().setCursor(defCursor);
  }
}

References

2009/03/02

Reset RowFilter before sorting

Code

RowFilter<TableModel, Integer> filter = new RowFilter<TableModel, Integer>() {
  @Override public boolean include(Entry<? extends TableModel, ? extends Integer> entry) {
    int vidx = table.convertRowIndexToView(entry.getIdentifier());
    return vidx < USER_SPECIFIED_NUMBER_OF_ROWS;
  }
};
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model) {
  @Override public void toggleSortOrder(int column) {
    if (check.isSelected()) {
      RowFilter<? super TableModel, ? super Integer> f = getRowFilter();
      setRowFilter(null);
      super.toggleSortOrder(column);
      setRowFilter(f);
    } else {
      super.toggleSortOrder(column);
    }
  }
};
table.setRowSorter(sorter);
sorter.setSortKeys(Arrays.asList(new RowSorter.SortKey(1, SortOrder.DESCENDING)));

References

2009/02/27

HyperLink in JTable Cell

Code

class UriRenderer extends DefaultTableCellRenderer implements MouseListener, MouseMotionListener {
  private int viewRowIndex = -1;
  private int viewColumnIndex = -1;
  private boolean isRollover;

  @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    Component c = super.getTableCellRendererComponent(
        table, value, isSelected, false, row, column);
    if (c instanceof JLabel) {
      JLabel l = (JLabel) c;
      // @see https://ateraimemo.com/Swing/ClippedHtmlLabel.html
      // String str = SwingUtilities.layoutCompoundLabel(...);
      String str = Objects.toString(value, "");
      if (isRolloverCell(table, row, column)) {
        l.setText("<html><u><font color='blue'>" + str);
      } else if (hasFocus) {
        l.setText("<html><font color='blue'>" + str);
      } else {
        l.setText(str);
      }
    }
    return c;
  }

  protected boolean isRolloverCell(JTable table, int row, int column) {
    return !table.isEditing() && viewRowIndex == row && viewColumnIndex == column && isRollover;
  }

  private static boolean isUriColumn(JTable table, int column) {
    return column >= 0 && table.getColumnClass(column).equals(URI.class);
  }

  @Override public void mouseMoved(MouseEvent e) {
    JTable table = (JTable) e.getComponent();
    Point pt = e.getPoint();
    int prevRow = viewRowIndex;
    int prevCol = viewColumnIndex;
    viewRowIndex = table.rowAtPoint(pt);
    viewColumnIndex = table.columnAtPoint(pt);
    boolean isSameCell = viewRowIndex == prevRow && viewColumnIndex == prevCol;

    boolean prevRollover = isRollover;
    isRollover = isUriColumn(table, viewColumnIndex);
    boolean isNotRollover = isRollover == prevRollover && !isRollover; // && !prevRollover;

    if (isSameCell && isNotRollover) {
      return;
    }

    // >>>> HyperlinkCellRenderer.java
    // @see https://github.com/sjas/swingset3/blob/master/trunk/SwingSet3/src/com/sun/swingset3/demos/table/HyperlinkCellRenderer.java
    Rectangle repaintRect;
    if (isRollover) {
      Rectangle r = table.getCellRect(viewRowIndex, viewColumnIndex, false);
      repaintRect = prevRollover ? r.union(table.getCellRect(prevRow, prevCol, false)) : r;
    } else { // if (prevRollover) {
      repaintRect = table.getCellRect(prevRow, prevCol, false);
    }
    table.repaint(repaintRect);
    // <<<<
    // table.repaint();
  }

  @Override public void mouseExited(MouseEvent e) {
    JTable table = (JTable) e.getComponent();
    if (isUriColumn(table, viewColumnIndex)) {
      table.repaint(table.getCellRect(viewRowIndex, viewColumnIndex, false));
      viewRowIndex = -1;
      viewColumnIndex = -1;
      isRollover = false;
    }
  }

  @Override public void mouseClicked(MouseEvent e) {
    JTable table = (JTable) e.getComponent();
    Point pt = e.getPoint();
    int col = table.columnAtPoint(pt);
    if (isUriColumn(table, col)) {
      int crow = table.rowAtPoint(pt);
      URI uri = (URI) table.getValueAt(crow, col);
      try {
        if (Desktop.isDesktopSupported()) {
          Desktop.getDesktop().browse(uri);
        }
      } catch (IOException ex) {
        // Logger.getGlobal().severe(ex::getMessage);
        UIManager.getLookAndFeel().provideErrorFeedback(e.getComponent());
      }
    }
  }

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

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

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

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

References

2009/02/26

Use JScrollBar as JSlider

Code

int step = 5;
int extent = 20;
int min = 0;
int max = extent * 10; // 200
int value = 50;
JScrollBar scrollbar = new JScrollBar(
  JScrollBar.HORIZONTAL, value, extent, min, max + extent);
scrollbar.setUnitIncrement(step);
scrollbar.getModel().addChangeListener(new ChangeListener() {
  @Override public void stateChanged(ChangeEvent e) {
    BoundedRangeModel m = (BoundedRangeModel) e.getSource();
    spinner.setValue(m.getValue());
  }
});
JSpinner spinner = new JSpinner(new SpinnerNumberModel(value, min, max, step));

References

2009/02/16

JTableHeader CheckBox

Code

enum Status { SELECTED, DESELECTED, INDETERMINATE }

class HeaderRenderer extends JCheckBox implements TableCellRenderer {
  private final JLabel label = new JLabel("Check All");
  private final int targetColumnIndex;

  public HeaderRenderer(JTableHeader header, int index) {
    super((String) null);
    this.targetColumnIndex = index;
    setOpaque(false);
    setFont(header.getFont());
    header.addMouseListener(new MouseAdapter() {
      @Override public void mouseClicked(MouseEvent e) {
        JTableHeader header = (JTableHeader) e.getComponent();
        JTable table = header.getTable();
        TableColumnModel columnModel = table.getColumnModel();
        int vci = columnModel.getColumnIndexAtX(e.getX());
        int mci = table.convertColumnIndexToModel(vci);
        if (mci == targetColumnIndex) {
          TableColumn column = columnModel.getColumn(vci);
          boolean b = column.getHeaderValue() == Status.DESELECTED;
          TableModel m = table.getModel();
          for (int i = 0; i < m.getRowCount(); i++) {
            m.setValueAt(b, i, mci);
          }
          column.setHeaderValue(b ? Status.SELECTED : Status.DESELECTED);
          // header.repaint();
        }
      }
    });
  }

  @Override public Component getTableCellRendererComponent(
        JTable tbl, Object val, boolean isS, boolean hasF, int row, int col) {
    TableCellRenderer r = tbl.getTableHeader().getDefaultRenderer();
    JLabel l = (JLabel) r.getTableCellRendererComponent(tbl, val, isS, hasF, row, col);
    if (targetColumnIndex == tbl.convertColumnIndexToModel(col)) {
      if (val instanceof Status) {
        switch ((Status) val) {
        case SELECTED:
          setSelected(true);
          setEnabled(true);
          break;
        case DESELECTED:
          setSelected(false);
          setEnabled(true);
          break;
        case INDETERMINATE:
          setSelected(true);
          setEnabled(false);
          break;
        default:
          throw new AssertionError("Unknown Status");
        }
      } else {
        setSelected(true);
        setEnabled(false);
      }
      label.setIcon(new ComponentIcon(this));
      l.setIcon(new ComponentIcon(label));
      l.setText(null);
    }
    return l;
  }
}

class ComponentIcon implements Icon {
  private final JComponent cmp;

  public ComponentIcon(JComponent cmp) {
    this.cmp = cmp;
  }

  @Override public int getIconWidth() {
    return cmp.getPreferredSize().width;
  }

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

  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    SwingUtilities.paintComponent(
        g, cmp, c.getParent(), x, y, getIconWidth(), getIconHeight());
  }
}

References

2009/01/23

create Auto Suggest JComboBox

Code

String[] array = {
    "aaaa", "aaaabbb", "aaaabbbcc", "aaaabbbccddd",
    "abcde", "abefg", "bbb1", "bbb12"};
JComboBox combo = new JComboBox(array);
combo.setEditable(true);
combo.setSelectedIndex(-1);
JTextField field = (JTextField) combo.getEditor().getEditorComponent();
field.setText("");
field.addKeyListener(new ComboKeyHandler(combo));

// ...
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(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, 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