Google Tag Manager

2008/12/25

JTable FishEye Row

Code

public void mouseMoved(MouseEvent e) {
  int row = rowAtPoint(e.getPoint());
  if(prev_row==row) return;
  initRowHeigth(prev_height, row);
  prev_row = row;
}
public void initRowHeigth(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 {
  public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D)g;
    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.translate(-x,-y);
  }
  public int getIconWidth()  { return 9; }
  public int getIconHeight() { return 9; }
}
class MenuToggleButton extends JToggleButton {
  private static final Icon i = new MenuArrowIcon();
  public MenuToggleButton() {
    this("", null);
  }
  public MenuToggleButton(Icon icon) {
    this("", icon);
  }
  public MenuToggleButton(String text) {
    this(text, null);
  }
  public MenuToggleButton(String text, Icon icon) {
    super();
    Action a = new AbstractAction(text) {
      public void actionPerformed(ActionEvent ae) {
        MenuToggleButton b = (MenuToggleButton)ae.getSource();
        if(pop!=null) pop.show(b, 0, b.getHeight());
      }
    };
    a.putValue(Action.SMALL_ICON, icon);
    setAction(a);
    setFocusable(false);
    setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4+i.getIconWidth()));
  }
  protected JPopupMenu pop;
  public void setPopupMenu(final JPopupMenu pop) {
    this.pop = pop;
    pop.addPopupMenuListener(new PopupMenuListener() {
      public void popupMenuCanceled(PopupMenuEvent e) {}
      public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
      public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
        setSelected(false);
      }
    });
  }
  public 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-i.getIconHeight())/2;
    i.paintIcon(this, g, x, y);
  }
}

References

2008/12/02

JLabel Star Rating Bar

Code

class LevelBar extends JPanel implements MouseListener, MouseMotionListener{
  private final int gap;
  protected final List< ImageIcon > iconList;
  protected final List< JLabel > labelList = Arrays.asList(
    new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel()
  );
  protected final ImageIcon defaultIcon;
  private int clicked = -1;
  public LevelBar(ImageIcon defaultIcon, List< ImageIcon > list, int gap) {
    super(new GridLayout(1, 5, gap*2, gap*2));
    this.defaultIcon = defaultIcon;
    this.iconList = list;
    this.gap = gap;
    for(JLabel l:labelList) {
      l.setIcon(defaultIcon);
      add(l);
    }
    addMouseListener(this);
    addMouseMotionListener(this);
  }
  public void clear() {
    clicked = -1;
    repaintIcon(clicked);
  }
  public int getLevel() {
    return clicked;
  }
  public void setLevel(int l) {
    clicked = l;
    repaintIcon(clicked);
  }
  private int getSelectedIconIndex(Point p) {
    for(int i=0;i < labelList.size();i++) {
      Rectangle r = labelList.get(i).getBounds();
      r.grow(gap, gap);
      if(r.contains(p)) return i;
    }
    return -1;
  }
  protected void repaintIcon(int index) {
    for(int i=0;i < labelList.size();i++) {
      labelList.get(i).setIcon(i <= index?iconList.get(i):defaultIcon);
    }
    repaint();
  }
  public void mouseMoved(MouseEvent e) {
    repaintIcon(getSelectedIconIndex(e.getPoint()));
  }
  public void mouseEntered(MouseEvent e) {
    repaintIcon(getSelectedIconIndex(e.getPoint()));
  }
  public void mouseClicked(MouseEvent e) {
    clicked = getSelectedIconIndex(e.getPoint());
  }
  public void mouseExited(MouseEvent e) {
    repaintIcon(clicked);
  }
  public void mouseDragged(MouseEvent e) {}
  public void mousePressed(MouseEvent e) {}
  public void mouseReleased(MouseEvent e) {}
}
class SelectedImageFilter extends RGBImageFilter {
  private final float[] filter;
  public SelectedImageFilter(float[] filter) {
    this.filter = filter;
    canFilterIndexColorModel = true;
  }
  public int filterRGB(int x, int y, int argb) {
    Color color = new Color(argb, true);
    float[] array = new float[4];
    color.getComponents(array);
    return new Color(array[0]*filter[0],
                     array[1]*filter[1],
                     array[2]*filter[2],
                     array[3]).getRGB();
  }
}

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 RoundedCornerButtonUI extends BasicButtonUI{
  private static final float arcwidth  = 16.0f;
  private static final float archeight = 16.0f;
  protected static final int focusstroke = 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;

  @Override protected void installDefaults(AbstractButton b) {
    super.installDefaults(b);
    b.setContentAreaFilled(false);
    b.setOpaque(false);
    b.setBackground(new Color(250, 250, 250));
    initShape(b);
  }
  @Override protected void installListeners(AbstractButton b) {
    BasicButtonListener listener = new BasicButtonListener(b) {
      @Override public void mousePressed(MouseEvent e) {
        AbstractButton b = (AbstractButton) e.getSource();
        initShape(b);
        if(shape.contains(e.getX(), e.getY())) {
          super.mousePressed(e);
        }
      }
      @Override public void mouseEntered(MouseEvent e) {
        if(shape.contains(e.getX(), e.getY())) {
          super.mouseEntered(e);
        }
      }
      @Override public void mouseMoved(MouseEvent e) {
        if(shape.contains(e.getX(), e.getY())) {
          super.mouseEntered(e);
        }else{
          super.mouseExited(e);
        }
      }
    };
    if(listener != null) {
      b.addMouseListener(listener);
      b.addMouseMotionListener(listener);
      b.addFocusListener(listener);
      b.addPropertyChangeListener(listener);
      b.addChangeListener(listener);
    }
  }
  @Override public void paint(Graphics g, JComponent c) {
    Graphics2D g2 = (Graphics2D)g;
    AbstractButton b = (AbstractButton) c;
    ButtonModel model = b.getModel();
    initShape(b);
    //ContentArea
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    if(model.isArmed()) {
      g2.setColor(ac);
      g2.fill(shape);
    }else if(b.isRolloverEnabled() && model.isRollover()) {
      paintFocusAndRollover(g2, c, rc);
    }else if(b.hasFocus()) {
      paintFocusAndRollover(g2, c, fc);
    }else{
      g2.setColor(c.getBackground());
      g2.fill(shape);
    }
    //Border
    g2.setPaint(c.getForeground());
    g2.draw(shape);

    g2.setColor(c.getBackground());
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_OFF);
    super.paint(g2, c);
  }
  private void initShape(JComponent c) {
    if(!c.getBounds().equals(base)) {
      base = c.getBounds();
      shape = new RoundRectangle2D.Float(0, 0, c.getWidth()-1, c.getHeight()-1,
                                         arcwidth, archeight);
      border = new RoundRectangle2D.Float(focusstroke, focusstroke,
                        c.getWidth()-1-focusstroke*2,
                        c.getHeight()-1-focusstroke*2,
                        arcwidth, archeight);
    }
  }
  private void paintFocusAndRollover(Graphics2D g2, JComponent c, Color color) {
    g2.setPaint(new GradientPaint(0, 0, color, c.getWidth()-1, c.getHeight()-1,
                                  color.brighter(), true));
    g2.fill(shape);
    g2.setColor(c.getBackground());
    g2.fill(border);
  }
}

References

2008/10/20

Modal Internal Frame

Code

//menuItem.setMnemonic(KeyEvent.VK_3);
//Creating Modal Internal Frames -- Approach 1 and Approach 2
//http://java.sun.com/developer/JDCTechTips/2001/tt1220.html
class ModalInternalFrameAction3 extends AbstractAction {
  private final Component orgGlassPane;
  private final JPanel glass = new PrintGlassPane();
  public ModalInternalFrameAction3(String label) {
    super(label);
    orgGlassPane = frame.getGlassPane();
    glass.setVisible(false);
  }
  public void actionPerformed(ActionEvent e) {
    JOptionPane optionPane = new JOptionPane();
    optionPane.setMessage("Hello, World");
    optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
    JInternalFrame modal = optionPane.createInternalFrame(desktop, "modal3");
    removeSystemMenuListener(modal);
    modal.addInternalFrameListener(new InternalFrameAdapter() {
      public void internalFrameClosed(InternalFrameEvent e) {
        glass.setVisible(false);
        frame.setGlassPane(orgGlassPane);
      }
    });
    glass.add(modal);
    Rectangle screen = desktop.getBounds();
    modal.setLocation(screen.x + screen.width/2  - modal.getSize().width/2,
                      screen.y + screen.height/2 - modal.getSize().height/2);
    frame.setGlassPane(glass);
    glass.setVisible(true);
    modal.setVisible(true);
    try{
      modal.setSelected(true);
    }catch(java.beans.PropertyVetoException ex) {}
  }
}

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 RubberBandingListener extends MouseInputAdapter {
  @Override public void mouseDragged(MouseEvent e) {
    setFocusable(true);
    if(srcPoint==null) srcPoint = e.getPoint();
    Point destPoint = e.getPoint();
    polygon.reset();
    polygon.addPoint(srcPoint.x,  srcPoint.y);
    polygon.addPoint(destPoint.x, srcPoint.y);
    polygon.addPoint(destPoint.x, destPoint.y);
    polygon.addPoint(srcPoint.x,  destPoint.y);
    //setSelectedIndices(getIntersectsIcons(polygon));
    if(srcPoint.getX()==destPoint.getX() || srcPoint.getY()==destPoint.getY()) {
      line.setLine(srcPoint.getX(),srcPoint.getY(),destPoint.getX(),destPoint.getY());
      setSelectedIndices(getIntersectsIcons(line));
    }else{
      setSelectedIndices(getIntersectsIcons(polygon));
    }
    repaint();
  }
  @Override
  public void mouseReleased(MouseEvent e) {
    setFocusable(true);
    srcPoint = null;
    repaint();
  }
  @Override
  public void mousePressed(MouseEvent e) {
    int index = locationToIndex(e.getPoint());
    Rectangle rect = getCellBounds(index,index);
    if(!rect.contains(e.getPoint())) {
      getSelectionModel().setLeadSelectionIndex(getModel().getSize());
      clearSelection();
      setFocusable(false);
    }else{
      setFocusable(true);
    }
  }
  private int[] getIntersectsIcons(Shape p) {
    ListModel model = getModel();
    Vector< Integer > list = new Vector< Integer >(model.getSize());
    for(int i=0;i < model.getSize();i++) {
      Rectangle r = getCellBounds(i,i);
      if(p.intersects(r)) {
        list.add(i);
      }
    }
    int[] il = new int[list.size()];
    for(int i=0;i < list.size();i++) {
      il[i] = list.get(i);
    }
    return il;
  }
}

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

References

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 {
  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 Shape shape, base;
  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;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(getBackground());
    //g2.setStroke(new BasicStroke(1.0f));
    g2.draw(shape);
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_OFF);
  }
  @Override public boolean contains(int x, int y) {
    initShape();
    return shape.contains(x, y);
    //or return super.contains(x, y) && ((image.getRGB(x, y) >> 24) & 0xff) > 0;
  }
}

References

2008/06/25

Mouse Drag Auto Scrolling

Code

JLabel label = new JLabel();
//"CRW_3857_JFR.jpg" > http://sozai-free.com/
label.setIcon(new ImageIcon(getClass().getResource("CRW_3857_JFR.jpg")));
JScrollPane scroll = new JScrollPane(label,
    JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
//*
ViewportDragScrollListener l = new ViewportDragScrollListener(label);
JViewport v = scroll.getViewport();
v.addMouseMotionListener(l);
v.addMouseListener(l);
v.addHierarchyListener(l);
/*/
//If label has its own MouseListeners, recommended to use ComponentDragScrollListener instead of ViewportDragScrollListener:
ComponentDragScrollListener l = new ComponentDragScrollListener(label);
label.addMouseMotionListener(l);
label.addMouseListener(l);
label.addHierarchyListener(l);
//*/
add(scroll);
scroll.setPreferredSize(new Dimension(320, 320));
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 javax.swing.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 javax.swing.Timer(DELAY, new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        JViewport vport = (JViewport)label.getParent();
        Point vp = vport.getViewPosition();
        vp.translate(move.x, move.y);
        label.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
      }
    });
  }
  @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;
    Point vp = vport.getViewPosition();
    vp.translate(dx, dy);
    label.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
    move.setLocation(SPEED*dx, SPEED*dy);
    startPt.setLocation(pt);
  }
  @Override public void mousePressed(MouseEvent e) {
    ((JComponent)e.getSource()).setCursor(hc); //label.setCursor(hc);
    startPt.setLocation(e.getPoint());
    move.setLocation(0, 0);
    scroller.stop();
  }
  @Override public void mouseReleased(MouseEvent e) {
    ((JComponent)e.getSource()).setCursor(dc); //label.setCursor(dc);
    scroller.start();
  }
  @Override public void mouseExited(MouseEvent e) {
    ((JComponent)e.getSource()).setCursor(dc); //label.setCursor(dc);
    move.setLocation(0, 0);
    scroller.stop();
  }
}
class ComponentDragScrollListener 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 javax.swing.Timer scroller;
  private final JComponent label;
  private Point startPt = new Point();
  private Point move    = new Point();

  public ComponentDragScrollListener(JComponent comp) {
    this.label = comp;
    this.dc = comp.getCursor();
    this.scroller = new javax.swing.Timer(DELAY, new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        Container c = label.getParent();
        if(c instanceof JViewport) {
          JViewport vport = (JViewport)c;
          Point vp = vport.getViewPosition();
          vp.translate(move.x, move.y);
          label.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
        }
      }
    });
  }
  @Override public void hierarchyChanged(HierarchyEvent e) {
    JComponent jc = (JComponent)e.getSource();
    if((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED)!=0
       && !jc.isDisplayable()) {
      scroller.stop();
    }
  }
  @Override public void mouseDragged(MouseEvent e) {
    scroller.stop();
    JComponent jc = (JComponent)e.getSource();
    Container c = jc.getParent();
    if(c instanceof JViewport) {
      JViewport vport = (JViewport)jc.getParent();
      Point cp = SwingUtilities.convertPoint(jc,e.getPoint(),vport);
      int dx = startPt.x - cp.x;
      int dy = startPt.y - cp.y;
      Point vp = vport.getViewPosition();
      vp.translate(dx, dy);
      jc.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
      move.setLocation(SPEED*dx, SPEED*dy);
      startPt.setLocation(cp);
    }
  }
  @Override public void mousePressed(MouseEvent e) {
    scroller.stop();
    move.setLocation(0, 0);
    JComponent jc = (JComponent)e.getSource();
    jc.setCursor(hc);
    Container c = jc.getParent();
    if(c instanceof JViewport) {
      JViewport vport = (JViewport)c;
      Point cp = SwingUtilities.convertPoint(jc,e.getPoint(),vport);
      startPt.setLocation(cp);
    }
  }
  @Override public void mouseReleased(MouseEvent e) {
    ((JComponent)e.getSource()).setCursor(dc);
    scroller.start();
  }
  @Override public void mouseExited(MouseEvent e) {
    ((JComponent)e.getSource()).setCursor(dc);
    move.setLocation(0, 0);
    scroller.stop();
  }
}

References

2008/04/07

Drag and Drop the Tabs in JTabbedPane

Code

class DnDTabbedPane extends JTabbedPane {
  private static final int LINE_SIZE = 3;
  private static final int RWH = 20;
  private static final int BUTTON_SIZE = 30; // XXX 30 is magic number of scroll button size
  private final GhostGlassPane glassPane = new GhostGlassPane(this);
  protected int dragTabIndex = -1;
  protected boolean hasGhost = true;
  protected boolean isPaintScrollArea = true;

  protected Rectangle rectBackward = new Rectangle();
  protected Rectangle rectForward = new Rectangle();

  private void clickArrowButton(String actionKey) {
    JButton forwardButton = null;
    JButton backwardButton = null;
    for (Component c : getComponents()) {
      if (c instanceof JButton) {
        if (Objects.isNull(forwardButton)) {
          forwardButton = (JButton) c;
        } else {
          backwardButton = (JButton) c;
          break;
        }
      }
    }
    JButton b = "scrollTabsForwardAction".equals(actionKey) ? forwardButton : backwardButton;
    Optional.ofNullable(b)
        .filter(JButton::isEnabled)
        .ifPresent(JButton::doClick);
  }

  public void autoScrollTest(Point glassPt) {
    Rectangle r = getTabAreaBounds();
    if (isTopBottomTabPlacement(getTabPlacement())) {
      rectBackward.setBounds(r.x, r.y, RWH, r.height);
      rectForward.setBounds(r.x + r.width - RWH - BUTTON_SIZE, r.y, RWH + BUTTON_SIZE, r.height);
    } else {
      rectBackward.setBounds(r.x, r.y, r.width, RWH);
      rectForward.setBounds(r.x, r.y + r.height - RWH - BUTTON_SIZE, r.width, RWH + BUTTON_SIZE);
    }
    rectBackward = SwingUtilities.convertRectangle(getParent(), rectBackward, glassPane);
    rectForward = SwingUtilities.convertRectangle(getParent(), rectForward, glassPane);
    if (rectBackward.contains(glassPt)) {
      clickArrowButton("scrollTabsBackwardAction");
    } else if (rectForward.contains(glassPt)) {
      clickArrowButton("scrollTabsForwardAction");
    }
  }

  protected DnDTabbedPane() {
    super();
    glassPane.setName("GlassPane");
    new DropTarget(glassPane, DnDConstants.ACTION_COPY_OR_MOVE, new TabDropTargetListener(), true);
    DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
        this, DnDConstants.ACTION_COPY_OR_MOVE, new TabDragGestureListener());
  }

  @SuppressWarnings("PMD.NPathComplexity")
  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.x + r.width;
      } else {
        r.y = r.y + r.height;
      }
      if (r.contains(tabPt)) {
        return i + 1;
      }
    }

    Rectangle lastRect = getBoundsAt(count - 1);
    Point d = isHorizontal ? new Point(1, 0) : new Point(0, 1);
    lastRect.translate(lastRect.width * d.x, lastRect.height * d.y);
    return lastRect.contains(tabPt) ? count : -1;
  }

  protected void convertTab(int prev, int next) {
    if (next < 0 || prev == next) {
      // This check is needed if tab content is null.
      return;
    }
    final Component cmp = getComponentAt(prev);
    final Component tab = getTabComponentAt(prev);
    final String title = getTitleAt(prev);
    final Icon icon = getIconAt(prev);
    final String tip = getToolTipTextAt(prev);
    final boolean isEnabled = isEnabledAt(prev);
    int tgtIndex = prev > next ? next : next - 1;
    remove(prev);
    insertTab(title, icon, cmp, tip, tgtIndex);
    setEnabledAt(tgtIndex, isEnabled);
    // When you drag and drop a disabled tab, it finishes enabled and selected.
    // pointed out by dlorde
    if (isEnabled) {
      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);
  }

  protected void initTargetLine(int next) {
    boolean isSideNeighbor = next < 0 || dragTabIndex == next || next - dragTabIndex == 1;
    if (isSideNeighbor) {
      glassPane.setTargetRect(0, 0, 0, 0);
      return;
    }
    Optional.ofNullable(getBoundsAt(Math.max(0, next - 1))).ifPresent(boundsRect -> {
      final Rectangle r = SwingUtilities.convertRectangle(this, boundsRect, glassPane);
      int a = Math.min(next, 1); // a = (next == 0) ? 0 : 1;
      if (isTopBottomTabPlacement(getTabPlacement())) {
        glassPane.setTargetRect(r.x + r.width * a - LINE_SIZE / 2, r.y, LINE_SIZE, r.height);
      } else {
        glassPane.setTargetRect(r.x, r.y + r.height * a - LINE_SIZE / 2, r.width, LINE_SIZE);
      }
    });
  }

  protected void initGlassPane(Point tabPt) {
    getRootPane().setGlassPane(glassPane);
    if (hasGhost) {
      Component c = getTabComponentAt(dragTabIndex);
      Component copy = Optional.ofNullable(c).orElseGet(() -> {
        String title = getTitleAt(dragTabIndex);
        Icon icon = getIconAt(dragTabIndex);
        JLabel label = new JLabel(title, icon, LEADING); // Nimbus?
        label.setIconTextGap(UIManager.getInt("TabbedPane.textIconGap"));
        return label;
      });
      Dimension d = copy.getPreferredSize();
      BufferedImage image = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = image.createGraphics();
      SwingUtilities.paintComponent(g2, copy, glassPane, 0, 0, d.width, d.height);
      g2.dispose();
      glassPane.setImage(image);
      if (c != null) {
        setTabComponentAt(dragTabIndex, c);
      }
    }
    Point glassPt = SwingUtilities.convertPoint(this, tabPt, glassPane);
    glassPane.setPoint(glassPt);
    glassPane.setVisible(true);
  }

  protected Rectangle getTabAreaBounds() {
    Rectangle tabbedRect = getBounds();
    // XXX: Rectangle compRect = getSelectedComponent().getBounds();
    // pointed out by daryl. NullPointerException: i.e. addTab("Tab", null)
    // Component comp = getSelectedComponent();
    // int idx = 0;
    // while (Objects.isNull(comp) && idx < getTabCount()) {
    //   comp = getComponentAt(idx++);
    // }

    Rectangle compRect = Optional.ofNullable(getSelectedComponent())
        .map(Component::getBounds)
        .orElseGet(Rectangle::new);
    int tabPlacement = getTabPlacement();
    if (isTopBottomTabPlacement(tabPlacement)) {
      tabbedRect.height = tabbedRect.height - compRect.height;
      if (tabPlacement == BOTTOM) {
        tabbedRect.y += compRect.y + compRect.height;
      }
    } else {
      tabbedRect.width = tabbedRect.width - compRect.width;
      if (tabPlacement == RIGHT) {
        tabbedRect.x += compRect.x + compRect.width;
      }
    }
    tabbedRect.grow(2, 2);
    return tabbedRect;
  }

  public static boolean isTopBottomTabPlacement(int tabPlacement) {
    return tabPlacement == TOP || tabPlacement == BOTTOM;
  }
}


class TabTransferable implements Transferable {
  private static final String NAME = "test";
  private final Component tabbedPane;

  protected TabTransferable(Component tabbedPane) {
    this.tabbedPane = tabbedPane;
  }

  @Override public Object getTransferData(DataFlavor flavor) {
    return tabbedPane;
  }

  @Override public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[] {new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, NAME)};
  }

  @Override public boolean isDataFlavorSupported(DataFlavor flavor) {
    return NAME.equals(flavor.getHumanPresentableName());
  }
}

class TabDragSourceListener implements DragSourceListener {
  @Override public void dragEnter(DragSourceDragEvent e) {
    e.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
  }

  @Override public void dragExit(DragSourceEvent e) {
    e.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
    // glassPane.setTargetRect(0, 0, 0, 0);
    // glassPane.setPoint(new Point(-1000, -1000));
    // glassPane.repaint();
  }

  @Override public void dragOver(DragSourceDragEvent e) {
    // Point glassPt = e.getLocation();
    // JComponent glassPane = (JComponent) e.getDragSourceContext();
    // SwingUtilities.convertPointFromScreen(glassPt, glassPane);
    // int targetIdx = getTargetTabIndex(glassPt);
    // if (getTabAreaBounds().contains(glassPt) && targetIdx >= 0
    //     && targetIdx != dragTabIndex && targetIdx != dragTabIndex + 1) {
    //   e.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
    //   glassPane.setCursor(DragSource.DefaultMoveDrop);
    // } else {
    //   e.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
    //   glassPane.setCursor(DragSource.DefaultMoveNoDrop);
    // }
  }

  @Override public void dragDropEnd(DragSourceDropEvent e) {
    // System.out.println("dragDropEnd");
    // dragTabIndex = -1;
    // glassPane.setVisible(false);
    Component c = e.getDragSourceContext().getComponent();
    if (c instanceof JComponent) {
      JRootPane rp = ((JComponent) c).getRootPane();
      Optional.ofNullable(rp.getGlassPane()).ifPresent(gp -> gp.setVisible(false));
    }
  }

  @Override public void dropActionChanged(DragSourceDragEvent e) {
    /* not needed */
  }
}

class TabDragGestureListener implements DragGestureListener {
  private final DragSourceListener handler = new TabDragSourceListener();

  @Override public void dragGestureRecognized(DragGestureEvent e) {
    Optional.ofNullable(e.getComponent())
        .filter(DnDTabbedPane.class::isInstance)
        .map(DnDTabbedPane.class::cast)
        .filter(t -> t.getTabCount() > 1)
        .ifPresent(t -> startDrag(e, t));
  }

  private void startDrag(DragGestureEvent e, DnDTabbedPane tabs) {
    Point tabPt = e.getDragOrigin();
    int idx = tabs.indexAtLocation(tabPt.x, tabPt.y);
    int selIdx = tabs.getSelectedIndex();
    // When a tab runs rotation occurs, a tab that is not the target is dragged.
    // pointed out by Arjen
    boolean isTabRunsRotated = !(tabs.getUI() instanceof MetalTabbedPaneUI)
        && tabs.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT
        && idx != selIdx;
    tabs.dragTabIndex = isTabRunsRotated ? selIdx : idx;
    if (tabs.dragTabIndex >= 0 && tabs.isEnabledAt(tabs.dragTabIndex)) {
      tabs.initGlassPane(tabPt);
      try {
        e.startDrag(DragSource.DefaultMoveDrop, new TabTransferable(tabs), handler);
      } catch (InvalidDnDOperationException ex) {
        throw new IllegalStateException(ex);
      }
    }
  }
}

class TabDropTargetListener implements DropTargetListener {
  private static final Point HIDDEN_POINT = new Point(0, -1000);

  private static Optional<GhostGlassPane> getGhostGlassPane(Component c) {
    Class<GhostGlassPane> clz = GhostGlassPane.class;
    return Optional.ofNullable(c).filter(clz::isInstance).map(clz::cast);
  }

  @Override public void dragEnter(DropTargetDragEvent e) {
    getGhostGlassPane(e.getDropTargetContext().getComponent()).ifPresent(glassPane -> {
      // DnDTabbedPane tabbedPane = glassPane.tabbedPane;
      Transferable t = e.getTransferable();
      DataFlavor[] f = e.getCurrentDataFlavors();
      if (t.isDataFlavorSupported(f[0])) { // && tabbedPane.dragTabIndex >= 0) {
        e.acceptDrag(e.getDropAction());
      } else {
        e.rejectDrag();
      }
    });
  }

  @Override public void dragExit(DropTargetEvent e) {
    // Component c = e.getDropTargetContext().getComponent();
    // System.out.println("DropTargetListener#dragExit: " + c.getName());
    getGhostGlassPane(e.getDropTargetContext().getComponent()).ifPresent(glassPane -> {
      // XXX: glassPane.setVisible(false);
      glassPane.setPoint(HIDDEN_POINT);
      glassPane.setTargetRect(0, 0, 0, 0);
      glassPane.repaint();
    });
  }

  @Override public void dropActionChanged(DropTargetDragEvent e) {
    /* not needed */
  }

  @Override public void dragOver(DropTargetDragEvent e) {
    Component c = e.getDropTargetContext().getComponent();
    getGhostGlassPane(c).ifPresent(glassPane -> {
      Point glassPt = e.getLocation();

      DnDTabbedPane tabbedPane = glassPane.tabbedPane;
      tabbedPane.initTargetLine(tabbedPane.getTargetTabIndex(glassPt));
      tabbedPane.autoScrollTest(glassPt);

      glassPane.setPoint(glassPt);
      glassPane.repaint();
    });
  }

  @Override public void drop(DropTargetDropEvent e) {
    Component c = e.getDropTargetContext().getComponent();
    getGhostGlassPane(c).ifPresent(glassPane -> {
      DnDTabbedPane tabbedPane = glassPane.tabbedPane;
      Transferable t = e.getTransferable();
      DataFlavor[] f = t.getTransferDataFlavors();
      int prev = tabbedPane.dragTabIndex;
      int next = tabbedPane.getTargetTabIndex(e.getLocation());
      if (t.isDataFlavorSupported(f[0]) && prev != next) {
        tabbedPane.convertTab(prev, next);
        e.dropComplete(true);
      } else {
        e.dropComplete(false);
      }
      glassPane.setVisible(false);
      // tabbedPane.dragTabIndex = -1;
    });
  }
}

class GhostGlassPane extends JComponent {
  public final DnDTabbedPane tabbedPane;
  private final Rectangle lineRect = new Rectangle();
  private final Color lineColor = new Color(0, 100, 255);
  private final Point location = new Point();
  private transient BufferedImage draggingGhost;

  protected GhostGlassPane(DnDTabbedPane tabbedPane) {
    super();
    this.tabbedPane = tabbedPane;
    // [JDK-6700748]
    // Cursor flickering during D&D when using CellRendererPane with validation - Java Bug System
    // https://bugs.openjdk.org/browse/JDK-6700748
    // setCursor(null);
  }

  public void setTargetRect(int x, int y, int width, int height) {
    lineRect.setBounds(x, y, width, height);
  }

  public void setImage(BufferedImage draggingImage) {
    this.draggingGhost = draggingImage;
  }

  public void setPoint(Point pt) {
    this.location.setLocation(pt);
  }

  @Override public boolean isOpaque() {
    return false;
  }

  @Override public void setVisible(boolean v) {
    super.setVisible(v);
    if (!v) {
      setTargetRect(0, 0, 0, 0);
      setImage(null);
    }
  }

  @Override protected void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f));
    boolean b = tabbedPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT;
    if (b && tabbedPane.isPaintScrollArea) {
      g2.setPaint(Color.RED);
      g2.fill(tabbedPane.rectBackward);
      g2.fill(tabbedPane.rectForward);
    }
    if (draggingGhost != null) {
      double xx = location.getX() - draggingGhost.getWidth(this) / 2d;
      double yy = location.getY() - draggingGhost.getHeight(this) / 2d;
      g2.drawImage(draggingGhost, (int) xx, (int) yy, this);
    }
    g2.setPaint(lineColor);
    g2.fill(lineRect);
    g2.dispose();
  }
}

References

2008/03/26

JTable pagination using RowFilter

Code

public class MainPanel extends JPanel {
  private static final Color evenColor = new Color(240, 255, 250);
  private static final LinkViewRadioButtonUI ui = new LinkViewRadioButtonUI();
  private static int LR_PAGE_SIZE = 5;

  private final TestModel model = new TestModel();
  private final TableRowSorter< TestModel > sorter = new TableRowSorter< TestModel >(model);
  private final Box box = Box.createHorizontalBox();
  public MainPanel() {
    super(new BorderLayout());
    JTable table = new JTable(model) {
      @Override
      public Component prepareRenderer(TableCellRenderer tcr, int row, int column) {
        Component c = super.prepareRenderer(tcr, row, column);
        if(isRowSelected(row)) {
          c.setForeground(getSelectionForeground());
          c.setBackground(getSelectionBackground());
        }else{
          c.setForeground(getForeground());
          c.setBackground((row%2==0)?evenColor:getBackground());
        }
        return c;
      }
    };
    table.setFillsViewportHeight(true);
    table.setIntercellSpacing(new Dimension());
    table.setShowHorizontalLines(false);
    table.setShowVerticalLines(false);
    table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
    table.setRowSorter(sorter);

    for(int i=0;i <= 2008;i++) {
      model.addTest(new Test(" Test: "+i, (i%2==0)?"":"comment..."));
    }
    initLinkBox(100, 1);

    add(box, BorderLayout.NORTH);
    add(new JScrollPane(table));
    setPreferredSize(new Dimension(320, 240));
  }
  private void initLinkBox(final int itemsPerPage, final int currentPageIndex) {
    //assert currentPageIndex > 0;
    sorter.setRowFilter(makeRowFilter(itemsPerPage, currentPageIndex-1));

    ArrayList< JRadioButton > l = new ArrayList< JRadioButton >();

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

//#if 0
    //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 maxPageIndex = (rowCount/itemsPerPage) + (rowCount%itemsPerPage==0?0:1);
//#endif
    int endPageIndex = currentPageIndex+LR_PAGE_SIZE-1;
    if(endPageIndex>maxPageIndex) endPageIndex = maxPageIndex;

    if(currentPageIndex > 1)
        l.add(makePNRadioButton(itemsPerPage, currentPageIndex-1, "Prev"));
    //for(int i=startPageIndex;i <= endPageIndex;i++) 
    //    l.add(makeRadioButton(itemsPerPage, currentPageIndex, i-1));
    //if I only have one page, Y don't want to see pagination buttons
    //suggested by erServi
    if(startPageIndex < endPageIndex) {
      for(int i=startPageIndex; i<= endPageIndex;i++) {
          l.add(makeRadioButton(itemsPerPage, currentPageIndex, i-1));
      }
    }
    if(currentPageIndex < maxPageIndex)
        l.add(makePNRadioButton(itemsPerPage, currentPageIndex+1, "Next"));

    box.removeAll();
    ButtonGroup bg = new ButtonGroup();
    box.add(Box.createHorizontalGlue());
    for(JRadioButton r:l) {
      box.add(r); bg.add(r);
    }
    box.add(Box.createHorizontalGlue());
    box.revalidate();
    box.repaint();
    l.clear();
  }

  private JRadioButton makeRadioButton(final int itemsPerPage,
                                       final int current, final int target) {
    JRadioButton radio = new JRadioButton(""+(target+1));
    radio.setForeground(Color.BLUE);
    radio.setUI(ui);
    if(target+1==current) {
      radio.setSelected(true);
      radio.setForeground(Color.BLACK);
    }
    radio.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        initLinkBox(itemsPerPage, target+1);
      }
    });
    return radio;
  }
  private JRadioButton makePNRadioButton(final int itemsPerPage, final int target, String title) {
    JRadioButton radio = new JRadioButton(title);
    radio.setForeground(Color.BLUE);
    radio.setUI(ui);
    radio.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        initLinkBox(itemsPerPage, target);
      }
    });
    return radio;
  }

  private RowFilter< TestModel, Integer > makeRowFilter(final int itemsPerPage, final int target) {
    return new RowFilter< TestModel, Integer >() {
      @Override
      public boolean include(Entry< ? extends TestModel, ? extends Integer > entry) {
        int ei = entry.getIdentifier();
        return (target*itemsPerPage <= ei && ei < target*itemsPerPage+itemsPerPage);
      }
    };
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }

  public static void createAndShowGUI() {
    try{
      UIManager.getInstalledLookAndFeels();
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }catch(Exception e) {
      e.printStackTrace();
    }
    final JFrame frame = new JFrame("@title@");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MainPanel());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

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++) {
      JLabel l = (JLabel)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, JLabel.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