Google Tag Manager

2008/12/25

JTable FishEye Row

Code

@Override public void mouseMoved(MouseEvent e) {
  int row = rowAtPoint(e.getPoint());
  if (prev_row == row) {
    return;
  }
  initRowHeight(prev_height, row);
  prev_row = row;
}

public void initRowHeight(int height, int ccRow) {
  int rd2 = (fishEyeRowList.size() - 1) / 2;
  int rowCount = getModel().getRowCount();
  int view_rc = getViewableColoredRowCount(ccRow);
  int view_h = 0;
  for (int i = 0; i < view_rc; i++) {
    view_h += fishEyeRowHeightList.get(i);
  }
  int rest_rc = rowCount - view_rc;
  int rest_h = height - view_h;
  int rest_rh  = rest_h / rest_rc; rest_rh = rest_rh > 0 ? rest_rh : 1;
  int a = rest_h - rest_rh * rest_rc;
  int index = -1;
  for (int i = -rd2; i < rowCount; i++) {
    int crh;
    if (ccRow - rd2 <= i && i <= ccRow + rd2) {
      index++;
      if (i < 0) continue;
      crh = fishEyeRowHeightList.get(index);
    } else {
      if (i < 0) continue;
      crh = rest_rh + (a > 0 ? 1 : 0);
      a = a - 1;
    }
    setRowHeight(i, crh);
  }
}

References

2008/12/15

Adding JPopupMenu to JToolBar-Button

Code

class MenuArrowIcon implements Icon {
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setPaint(Color.BLACK);
    g2.translate(x, y);
    g2.drawLine(2, 3, 6, 3);
    g2.drawLine(3, 4, 5, 4);
    g2.drawLine(4, 5, 4, 5);
    g2.dispose();
  }

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

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

class MenuToggleButton extends JToggleButton {
  private static final Icon ARROW_ICON = new MenuArrowIcon();
  private JPopupMenu popup;

  protected MenuToggleButton() {
    this("", null);
  }

  protected MenuToggleButton(Icon icon) {
    this("", icon);
  }

  protected MenuToggleButton(String text) {
    this(text, null);
  }

  protected MenuToggleButton(String text, Icon icon) {
    super();
    Action action = new AbstractAction(text) {
      @Override public void actionPerformed(ActionEvent e) {
        Component b = (Component) e.getSource();
        Optional.ofNullable(getPopupMenu()).ifPresent(p -> p.show(b, 0, b.getHeight()));
      }
    };
    action.putValue(Action.SMALL_ICON, icon);
    setAction(action);
    setFocusable(false);
    setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4 + ARROW_ICON.getIconWidth()));
  }

  public JPopupMenu getPopupMenu() {
    return popup;
  }

  public void setPopupMenu(JPopupMenu pop) {
    this.popup = pop;
    pop.addPopupMenuListener(new PopupMenuListener() {
      @Override public void popupMenuCanceled(PopupMenuEvent e) {
        /* not needed */
      }

      @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
        /* not needed */
      }

      @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
        setSelected(false);
      }
    });
  }

  @Override protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Dimension dim = getSize();
    Insets ins = getInsets();
    int x = dim.width - ins.right;
    int y = ins.top + (dim.height - ins.top - ins.bottom - ARROW_ICON.getIconHeight()) / 2;
    ARROW_ICON.paintIcon(this, g, x, y);
  }
}

References

2008/12/02

JLabel Star Rating Bar

Code

private final ImageProducer ip = orgIcon.getImage().getSource();

private static ImageIcon makeStarImageIcon(
    ImageProducer ip, float rf, float gf, float bf) {
  return new ImageIcon(Toolkit.getDefaultToolkit().createImage(
    new FilteredImageSource(ip, new SelectedImageFilter(rf, gf, bf))));
}

class SelectedImageFilter extends RGBImageFilter {
  private final float rf;
  private final float gf;
  private final float bf;

  protected SelectedImageFilter(float rf, float gf, float bf) {
    super();
    this.rf = Math.min(1f, rf);
    this.gf = Math.min(1f, gf);
    this.bf = Math.min(1f, bf);
    canFilterIndexColorModel = false;
  }

  @Override public int filterRGB(int x, int y, int argb) {
    int r = (int) (((argb >> 16) & 0xFF) * rf);
    int g = (int) (((argb >> 8) & 0xFF) * gf);
    int b = (int) ((argb & 0xFF) * bf);
    return (argb & 0xFF_00_00_00) | (r << 16) | (g << 8) | (b);
  }
}

References

2008/11/11

create JTabbedPane like component using CardLayout and JRadioButton(or JTableHeader)

Code

class CardLayoutTabbedPane extends JPanel {
  protected final CardLayout cardLayout = new CardLayout();
  protected final JPanel tabPanel = new JPanel(new GridLayout(1, 0, 0, 0));
  protected final JPanel wrapPanel = new JPanel(new BorderLayout(0, 0));
  protected final JPanel contentsPanel = new JPanel(cardLayout);
  protected final ButtonGroup bg = new ButtonGroup();

  public CardLayoutTabbedPane() {
    super(new BorderLayout());
    int left  = 1;
    int right = 3;
    tabPanel.setBorder(BorderFactory.createEmptyBorder(1, left, 0, right));
    contentsPanel.setBorder(BorderFactory.createEmptyBorder(4, left, 2, right));
    wrapPanel.add(tabPanel);
    wrapPanel.add(new JLabel("test:"), BorderLayout.WEST);
    add(wrapPanel, BorderLayout.NORTH);
    add(contentsPanel);
  }

  public void addTab(final String title, final Component comp) {
    JRadioButton b = new TabButton(new AbstractAction(title) {
      public void actionPerformed(ActionEvent e) {
        cardLayout.show(contentsPanel, title);
      }
    });
    tabPanel.add(b);
    bg.add(b);
    b.setSelected(true);
    contentsPanel.add(comp, title);
    cardLayout.show(contentsPanel, title);
  }
}

References

2008/11/05

Rounded Corner JButton

Code

class RoundedCornerButton extends JButton {
  private static final float ARC_WIDTH = 16f;
  private static final float ARC_HEIGHT = 16f;
  protected static final int FOCUS_STROKE = 2;
  protected final Color fc = new Color(100, 150, 255, 200);
  protected final Color ac = new Color(230, 230, 230);
  protected final Color rc = Color.ORANGE;
  protected Shape shape;
  protected Shape border;
  protected Shape base;
  public RoundedCornerButton() {
    super();
  }

  public RoundedCornerButton(Icon icon) {
    super(icon);
  }

  public RoundedCornerButton(String text) {
    super(text);
  }

  public RoundedCornerButton(Action a) {
    super(a);
    // setAction(a);
  }

  public RoundedCornerButton(String text, Icon icon) {
    super(text, icon);
    // setModel(new DefaultButtonModel());
    // init(text, icon);
    // setContentAreaFilled(false);
    // setBackground(new Color(250, 250, 250));
    // initShape();
  }

  @Override public void updateUI() {
    super.updateUI();
    setContentAreaFilled(false);
    setFocusPainted(false);
    setBackground(new Color(250, 250, 250));
    initShape();
  }

  protected void initShape() {
    if (!getBounds().equals(base)) {
      base = getBounds();
      shape = new RoundRectangle2D.Float(
          0, 0, getWidth() - 1, getHeight() - 1, ARC_WIDTH, ARC_HEIGHT);
      border = new RoundRectangle2D.Float(
          FOCUS_STROKE, FOCUS_STROKE, getWidth() - 1 - FOCUS_STROKE * 2,
          getHeight() - 1 - FOCUS_STROKE * 2, ARC_WIDTH, ARC_HEIGHT);
    }
  }

  private void paintFocusAndRollover(Graphics2D g2, Color color) {
    g2.setPaint(new GradientPaint(
        0, 0, color, getWidth() - 1, getHeight() - 1,
        color.brighter(), true));
    g2.fill(shape);
    g2.setColor(getBackground());
    g2.fill(border);
  }

  @Override protected void paintComponent(Graphics g) {
    initShape();
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    if (getModel().isArmed()) {
      g2.setColor(ac);
      g2.fill(shape);
    } else if (isRolloverEnabled() && getModel().isRollover()) {
      paintFocusAndRollover(g2, rc);
    } else if (hasFocus()) {
      paintFocusAndRollover(g2, fc);
    } else {
      g2.setColor(getBackground());
      g2.fill(shape);
    }
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_OFF);
    g2.setColor(getBackground());
    super.paintComponent(g2);
    g2.dispose();
  }

  @Override protected void paintBorder(Graphics g) {
    initShape();
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(getForeground());
    g2.draw(shape);
    g2.dispose();
  }

  @Override public boolean contains(int x, int y) {
    initShape();
    return shape == null ? false : shape.contains(x, y);
  }
}

References

2008/10/20

Modal Internal Frame

Code

// menuItem.setMnemonic(KeyEvent.VK_1);
class ModalInternalFrameAction1 extends AbstractAction {
  public ModalInternalFrameAction1(String label) {
    super(label);
  }

  @Override public void actionPerformed(ActionEvent e) {
    setJMenuEnabled(false);
    JOptionPane.showInternalMessageDialog(
      desktop, "information", "modal1", JOptionPane.INFORMATION_MESSAGE);
    setJMenuEnabled(true);
  }
}

// menuItem.setMnemonic(KeyEvent.VK_2);
class ModalInternalFrameAction2 extends AbstractAction {
  private final JPanel glass = new MyGlassPane();
  public ModalInternalFrameAction2(String label) {
    super(label);
    Rectangle screen = frame.getGraphicsConfiguration().getBounds();
    glass.setBorder(BorderFactory.createEmptyBorder());
    glass.setLocation(0, 0);
    glass.setSize(screen.width, screen.height);
    glass.setOpaque(false);
    glass.setVisible(false);
    desktop.add(glass, JLayeredPane.MODAL_LAYER);
  }

  @Override public void actionPerformed(ActionEvent e) {
    setJMenuEnabled(false);
    glass.setVisible(true);
    JOptionPane.showInternalMessageDialog(
      desktop, "information", "modal2", JOptionPane.INFORMATION_MESSAGE);
    glass.setVisible(false);
    setJMenuEnabled(true);
  }
}

// menuItem.setMnemonic(KeyEvent.VK_3);
// Creating Modal Internal Frames -- Approach 1 and Approach 2
// http://web.archive.org/web/20090803142839/http://java.sun.com/developer/JDCTechTips/2001/tt1220.html
class ModalInternalFrameAction3 extends AbstractAction {
  private final JPanel glass = new PrintGlassPane();
  public ModalInternalFrameAction3(String label) {
    super(label);
    glass.setVisible(false);
  }

  @Override public void actionPerformed(ActionEvent e) {
    JOptionPane optionPane = new JOptionPane();
    JInternalFrame modal = optionPane.createInternalFrame(desktop, "modal3");
    optionPane.setMessage("Hello, World");
    optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
    removeSystemMenuListener(modal);
    modal.addInternalFrameListener(new InternalFrameAdapter() {
      @Override public void internalFrameClosed(InternalFrameEvent e) {
        glass.removeAll();
        glass.setVisible(false);
      }
    });
    glass.add(modal);
    modal.pack();
    getRootPane().setGlassPane(glass);
    glass.setVisible(true);
    modal.setVisible(true);
  }
}

References

2008/10/14

rubber band selection, drag and drop reordering

Code

JList list = new JList(model);
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(0);
list.setFixedCellWidth(62);
list.setFixedCellHeight(62);
list.setCellRenderer(new IconListCellRenderer());
RubberBandingListener rbl = new RubberBandingListener();
list.addMouseMotionListener(rbl);
list.addMouseListener(rbl);
list.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
list.setTransferHandler(new ListItemTransferHandler());
list.setDropMode(DropMode.INSERT);

References

2008/10/09

using rubber band selection in JList

Code

class RubberBandSelectionList<E extends ListItem> extends JList<E> {
  private static final AlphaComposite ALPHA =
    AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f);
  private RubberBandListCellRenderer<E> renderer;
  private Color polygonColor;
  public RubberBandSelectionList(ListModel<E> model) {
    super(model);
  }

  @Override public void updateUI() {
    setSelectionForeground(null);
    setSelectionBackground(null);
    setCellRenderer(null);
    if (renderer == null) {
      renderer = new RubberBandListCellRenderer<E>();
    } else {
      removeMouseMotionListener(renderer);
      removeMouseListener(renderer);
    }
    super.updateUI();
    EventQueue.invokeLater(() -> {
      setCellRenderer(renderer);
      addMouseMotionListener(renderer);
      addMouseListener(renderer);
      setLayoutOrientation(JList.HORIZONTAL_WRAP);
      setVisibleRowCount(0);
      setFixedCellWidth(62);
      setFixedCellHeight(62);
      setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    });
    Color c = getSelectionBackground();
    int r = c.getRed();
    int g = c.getGreen();
    int b = c.getBlue();
    polygonColor = r > g ? r > b ? new Color(r, 0, 0) : new Color(0, 0, b)
                         : g > b ? new Color(0, g, 0) : new Color(0, 0, b);
  }

  @Override protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (renderer != null && renderer.polygon != null) {
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setPaint(getSelectionBackground());
      g2.draw(renderer.polygon);
      g2.setComposite(ALPHA);
      g2.setPaint(polygonColor);
      g2.fill(renderer.polygon);
      g2.dispose();
    }
  }
}

References

2008/09/16

JTable Tri-state row sorting (cycle through ascending descending unsorted)

Code

TableModel model = new DefaultTableModel();
JTable table = new JTable(model);
// sort toggles ascending descending unsorted (like TableSorter.java)
TableRowSorter< TableModel > sorter = new TableRowSorter< TableModel >(model) {
  @Override
  public void toggleSortOrder(int column) {
    if(column >= 0 && column < getModelWrapper().getColumnCount() && isSortable(column)) {
      List< SortKey > keys = new ArrayList< SortKey >(getSortKeys());
      if(!keys.isEmpty()) {
        SortKey sortKey = keys.get(0);
        if(sortKey.getColumn()==column && sortKey.getSortOrder()==SortOrder.DESCENDING) {
          setSortKeys(null);
          return;
        }
      }
    }
    super.toggleSortOrder(column);
  }
};
table.setRowSorter(sorter);

2008/09/11

Double-click on each tab and change its name like Excel

Code

private Component tabComponent = null;
private int editing_idx = -1;
private int len = -1;
private Dimension dim;

private void startEditing() {
  // System.out.println("start");
  editing_idx  = tabbedPane.getSelectedIndex();
  tabComponent = tabbedPane.getTabComponentAt(editing_idx);
  tabbedPane.setTabComponentAt(editing_idx, editor);
  editor.setVisible(true);
  editor.setText(tabbedPane.getTitleAt(editing_idx));
  editor.selectAll();
  editor.requestFocusInWindow();
  len = editor.getText().length();
  dim = editor.getPreferredSize();
  editor.setMinimumSize(dim);
}

private void cancelEditing() {
  // System.out.println("cancel");
  if (editing_idx >= 0) {
    tabbedPane.setTabComponentAt(editing_idx, tabComponent);
    editor.setVisible(false);
    editing_idx = -1;
    len = -1;
    tabComponent = null;
    editor.setPreferredSize(null);
  }
}

private void renameTabTitle() {
  // System.out.println("rename");
  String title = editor.getText().trim();
  if (editing_idx >= 0 && !title.isEmpty()) {
    tabbedPane.setTitleAt(editing_idx, title);
  }
  cancelEditing();
}

References

2008/08/13

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

2008/07/29

create round image JButton

Code

class RoundButton extends JButton {
  protected Shape base;
  protected Shape shape

  public RoundButton() {
    this(null, null);
  }

  public RoundButton(Icon icon) {
    this(null, icon);
  }

  public RoundButton(String text) {
    this(text, null);
  }

  public RoundButton(Action a) {
    this();
    setAction(a);
  }

  public RoundButton(String text, Icon icon) {
    setModel(new DefaultButtonModel());
    init(text, icon);
    if (icon == null) {
      return;
    }
    setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
    setBackground(Color.BLACK);
    setContentAreaFilled(false);
    setFocusPainted(false);
    // setVerticalAlignment(SwingConstants.TOP);
    setAlignmentY(Component.TOP_ALIGNMENT);
    initShape();
  }

  protected void initShape() {
    if (!getBounds().equals(base)) {
      Dimension s = getPreferredSize();
      base = getBounds();
      shape = new Ellipse2D.Float(0, 0, s.width - 1, s.height - 1);
    }
  }

  @Override public Dimension getPreferredSize() {
    Icon icon = getIcon();
    Insets i = getInsets();
    int iw = Math.max(icon.getIconWidth(), icon.getIconHeight());
    return new Dimension(iw + i.right + i.left, iw + i.top + i.bottom);
  }

  @Override protected void paintBorder(Graphics g) {
    initShape();
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(getBackground());
    // g2.setStroke(new BasicStroke(1f));
    g2.draw(shape);
    g2.dispose();
  }

  @Override public boolean contains(int x, int y) {
    initShape();
    return shape.contains(x, y);
    // Transparent color is 0, making it unclickable:
    // or return super.contains(x, y) && ((image.getRGB(x, y) >> 24) & 0xff) > 0;
  }
}

References

2008/06/25

Mouse Drag Auto Scrolling

Code

class ViewportDragScrollListener extends MouseAdapter
                                 implements HierarchyListener {
  private static final int SPEED = 4;
  private static final int DELAY = 10;
  private final Cursor dc;
  private final Cursor hc = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
  private final Timer scroller;
  private final JComponent label;
  private Point startPt = new Point();
  private Point move    = new Point();

  public ViewportDragScrollListener(JComponent comp) {
    this.label = comp;
    this.dc = comp.getCursor();
    this.scroller = new Timer(DELAY, new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        Container c = SwingUtilities.getAncestorOfClass(
            JViewport.class, label);
        if (c instanceof JViewport.class) {
          JViewport vport = (JViewport) c;
          Rectangle rect = vport.getViewRect();
          rect.translate(move.x, move.y);
          label.scrollRectToVisible(rect);
        }
      }
    });
  }

  @Override public void hierarchyChanged(HierarchyEvent e) {
    JComponent c = (JComponent) e.getSource();
    if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0
        && !c.isDisplayable()) {
      scroller.stop();
    }
  }

  @Override public void mouseDragged(MouseEvent e) {
    JViewport vport = (JViewport) e.getSource();
    Point pt = e.getPoint();
    int dx = startPt.x - pt.x;
    int dy = startPt.y - pt.y;
    Rectangle rect = vport.getViewRect();
    rect.translate(dx, dy);
    label.scrollRectToVisible(rect);
    move.setLocation(SPEED * dx, SPEED * dy);
    startPt.setLocation(pt);
  }

  @Override public void mousePressed(MouseEvent e) {
    e.getComponent().setCursor(hc); // label.setCursor(hc);
    startPt.setLocation(e.getPoint());
    move.setLocation(0, 0);
    scroller.stop();
  }

  @Override public void mouseReleased(MouseEvent e) {
    e.getComponent().setCursor(dc); // label.setCursor(dc);
    scroller.start();
  }

  @Override public void mouseExited(MouseEvent e) {
    e.getComponent().setCursor(dc); // label.setCursor(dc);
    move.setLocation(0, 0);
    scroller.stop();
  }
}

References

2008/04/07

Drag and Drop the Tabs in JTabbedPane

Code

protected int getTargetTabIndex(Point glassPt) {
  int count = getTabCount();
  if (count == 0) {
    return -1;
  }

  Point tabPt = SwingUtilities.convertPoint(glassPane, glassPt, this);
  boolean isHorizontal = isTopBottomTabPlacement(getTabPlacement());
  for (int i = 0; i < count; ++i) {
    Rectangle r = getBoundsAt(i);

    // First half.
    if (isHorizontal) {
      r.width = r.width / 2 + 1;
    } else {
      r.height = r.height / 2 + 1;
    }
    if (r.contains(tabPt)) {
      return i;
    }

    // Second half.
    if (isHorizontal) {
      r.x += r.width;
    } else {
      r.y += r.height;
    }
    if (r.contains(tabPt)) {
      return i + 1;
    }
  }
  Rectangle r = getBoundsAt(getTabCount() - 1);
  r.translate(r.width * d.x / 2, r.height * d.y / 2);
  return r.contains(tabPt) ? getTabCount() : -1;
}

private void convertTab(int prev, int next) {
  if (next < 0 || prev == next) {
    return;
  }
  Component cmp = getComponentAt(prev);
  Component tab = getTabComponentAt(prev);
  String str    = getTitleAt(prev);
  Icon icon     = getIconAt(prev);
  String tip    = getToolTipTextAt(prev);
  boolean flg   = isEnabledAt(prev);
  int tgtindex  = prev > next ? next : next - 1;
  remove(prev);
  insertTab(str, icon, cmp, tip, tgtindex);
  setEnabledAt(tgtindex, flg);

  // When you drag'n'drop a disabled tab, it finishes enabled and selected.
  // pointed out by dlorde
  if (flg) {
    setSelectedIndex(tgtindex);
  }

  // I have a component in all tabs (jlabel with an X to close the tab)
  // and when i move a tab the component disappear.
  // pointed out by Daniel Dario Morales Salas
  setTabComponentAt(tgtindex, tab);
}

References

2008/03/26

JTable pagination using RowFilter

Code

private static int LR_PAGE_SIZE = 5;

private final String[] columnNames = {"Year", "String", "Comment"};
private final DefaultTableModel model = new DefaultTableModel(null, columnNames) {
  @Override public Class<?> getColumnClass(int column) {
    return (column == 0) ? Integer.class : Object.class;
  }
};
private TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
private Box box = Box.createHorizontalBox();

private void initLinkBox(final int itemsPerPage, final int currentPageIndex) {
  // assert currentPageIndex > 0;
  sorter.setRowFilter(new RowFilter<TableModel, Integer>() {
    @Override
    public boolean include(Entry<? extends TableModel, ? extends Integer> entry) {
      int ti = currentPageIndex - 1;
      int ei = entry.getIdentifier();
      return ti * itemsPerPage <= ei && ei < ti * itemsPerPage + itemsPerPage;
    }
  });

  int startPageIndex = currentPageIndex - LR_PAGE_SIZE;
  if (startPageIndex <= 0) {
    startPageIndex = 1;
  }

// #if 0 //BUG
  // int maxPageIndex = (model.getRowCount() / itemsPerPage) + 1;
// #else
  /* "maxPageIndex" gives one blank page if the module of the division is not zero.
   *   pointed out by erServi
   * e.g. rowCount=100, maxPageIndex=100
   */
  int rowCount = model.getRowCount();
  int v = rowCount % itemsPerPage == 0 ? 0 : 1;
  int maxPageIndex = rowCount / itemsPerPage + v;
// #endif
  int endPageIndex = currentPageIndex + LR_PAGE_SIZE - 1;
  if (endPageIndex > maxPageIndex) {
    endPageIndex = maxPageIndex;
  }

  box.removeAll();
  if (startPageIndex >= endPageIndex) {
    // if I only have one page, Y don't want to see pagination buttons
    // suggested by erServi
    return;
  }

  ButtonGroup bg = new ButtonGroup();
  JRadioButton f = makePrevNextRadioButton(
      itemsPerPage, 1, "|<", currentPageIndex > 1);
  box.add(f);
  bg.add(f);
  JRadioButton p = makePrevNextRadioButton(
      itemsPerPage, currentPageIndex - 1, "<", currentPageIndex > 1);
  box.add(p);
  bg.add(p);
  box.add(Box.createHorizontalGlue());
  for (int i = startPageIndex; i <= endPageIndex; i++) {
    JRadioButton c = makeRadioButton(itemsPerPage, currentPageIndex, i);
    box.add(c);
    bg.add(c);
  }
  box.add(Box.createHorizontalGlue());
  JRadioButton n = makePrevNextRadioButton(
      itemsPerPage, currentPageIndex + 1, ">", currentPageIndex < maxPageIndex);
  box.add(n);
  bg.add(n);
  JRadioButton l = makePrevNextRadioButton(
      itemsPerPage, maxPageIndex, ">|", currentPageIndex < maxPageIndex);
  box.add(l);
  bg.add(l);
  box.revalidate();
  box.repaint();
}

References

2008/03/21

Horizontally fill tabs of a JTabbedPane

Code

// horizontal filling, same width tabs
class ClippedTitleTabbedPane extends JTabbedPane {
  public ClippedTitleTabbedPane() {
    super();
  }

  public ClippedTitleTabbedPane(int tabPlacement) {
    super(tabPlacement);
  }

  private Insets getTabInsets() {
    Insets i = UIManager.getInsets("TabbedPane.tabInsets");
    if (i != null) {
      return i;
    } else {
      SynthStyle style = SynthLookAndFeel.getStyle(this, Region.TABBED_PANE_TAB);
      SynthContext context = new SynthContext(
        this, Region.TABBED_PANE_TAB, style, SynthConstants.ENABLED);
      return style.getInsets(context, null);
    }
  }

  private Insets getTabAreaInsets() {
    Insets i = UIManager.getInsets("TabbedPane.tabAreaInsets");
    if (i != null) {
      return i;
    } else {
      SynthStyle style = SynthLookAndFeel.getStyle(this, Region.TABBED_PANE_TAB_AREA);
      SynthContext context = new SynthContext(
        this, Region.TABBED_PANE_TAB_AREA, style, SynthConstants.ENABLED);
      return style.getInsets(context, null);
    }
  }

  @Override public void doLayout() {
    int tabCount  = getTabCount();
    if (tabCount == 0) return;
    Insets tabInsets   = getTabInsets();
    Insets tabAreaInsets = getTabAreaInsets();
    Insets insets = getInsets();
    int areaWidth = getWidth() - tabAreaInsets.left - tabAreaInsets.right
                    - insets.left        - insets.right;
    int tabWidth  = 0; // = tabInsets.left + tabInsets.right + 3;
    int gap     = 0;

    switch (getTabPlacement()) {
    case LEFT:
    case RIGHT:
      tabWidth = areaWidth / 4;
      gap = 0;
      break;
    case BOTTOM:
    case TOP:
    default:
      tabWidth = areaWidth / tabCount;
      gap = areaWidth - (tabWidth * tabCount);
    }
    // "3" is magic number @see BasicTabbedPaneUI#calculateTabWidth
    tabWidth = tabWidth - tabInsets.left - tabInsets.right - 3;
    for (int i = 0; i < tabCount; i++) {
      JComponent l = (JComponent) getTabComponentAt(i);
      if (l == null) break;
      l.setPreferredSize(new Dimension(tabWidth + (i < gap ? 1 : 0), l.getPreferredSize().height));
    }
    super.doLayout();
  }

  @Override public void insertTab(
      String title, Icon icon, Component component, String tip, int index) {
    super.insertTab(title, icon, component, tip == null ? title : tip, index);
    JLabel label = new JLabel(title, SwingConstants.CENTER);
    Dimension dim = label.getPreferredSize();
    Insets tabInsets = getTabInsets();
    label.setPreferredSize(new Dimension(0, dim.height + tabInsets.top + tabInsets.bottom));
    setTabComponentAt(index, label);
  }
}

References

2008/03/18

JProgressBar in JTable Cell

Code

class ProgressRenderer extends DefaultTableCellRenderer {
  private final JProgressBar b = new JProgressBar(0, 100);
  public ProgressRenderer() {
    super();
    setOpaque(true);
    b.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {
    Integer i = (Integer) value;
    String text = "Done";
    if (i < 0) {
      text = "Canceled";
    } else if (i < 100) {
      b.setValue(i);
      return b;
    }
    super.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column);
    return this;
  }
}
final Executor executor = Executors.newCachedThreadPool();
final int rowNumber = model.getRowCount();
SwingWorker<Integer, Integer> worker = new SwingWorker<Integer, Integer>() {
  private int sleepDummy = new Random().nextInt(100) + 1;
  private int lengthOfTask = 120;
  @Override
  protected Integer doInBackground() {
    int current = 0;
    while (current < lengthOfTask && !isCancelled()) {
      if (!table.isDisplayable()) {
        return -1;
      }
      current++;
      try {
        Thread.sleep(sleepDummy);
      } catch (InterruptedException ie) {
        publish(-1);
        break;
      }
      publish(100 * current / lengthOfTask);
    }
    return sleepDummy * lengthOfTask;
  }
  @Override
  protected void process(List<Integer> chunks) {
    for (Integer value : chunks) {
      model.setValueAt(value, rowNumber, 2);
    }
    // model.fireTableCellUpdated(rowNumber, 2);
  }
  @Override
  protected void done() {
    String text;
    int i = -1;
    if (isCancelled()) {
      text = "Canceled";
    } else {
      try {
        i = get();
        text = (i>=0)?"Done":"Disposed";
      } catch (Exception ignore) {
        ignore.printStackTrace();
        text = ignore.getMessage();
      }
    }
    System.out.println(rowNumber +":"+text+"("+i+"ms)");
  }
};
model.addTest(new Test("example", 0), worker);
executor.execute(worker); // JDK 1.6.0_18
// worker.execute();

References