Google Tag Manager

2011/12/22

Dropdown menu button in the JTableHeader

Code

@Override public void mouseClicked(MouseEvent e) {
  JTableHeader header = (JTableHeader)e.getSource();
  JTable table = header.getTable();
  TableColumnModel columnModel = table.getColumnModel();
  int vci = columnModel.getColumnIndexAtX(e.getX());
  int mci = table.convertColumnIndexToModel(vci);
  TableColumn column = table.getColumnModel().getColumn(mci);
  Rectangle r = header.getHeaderRect(vci);
  Container c = (Container)getTableCellRendererComponent(table, "", true, true, -1, vci);
  r.translate(r.width-BUTTON_WIDTH, 0);
  r.setSize(BUTTON_WIDTH, r.height);
  Point pt = e.getPoint();
  if(c.getComponentCount() > 0 && r.contains(pt) && pop!=null) {
    pop.show(header, r.x, r.height);
    JButton b = (JButton)c.getComponent(0);
    b.doClick();
    e.consume();
  }
}
@Override public void mouseExited(MouseEvent e) {
  rolloverIndex = -1;
}
@Override public void mouseMoved(MouseEvent e) {
  JTableHeader header = (JTableHeader)e.getSource();
  JTable table = header.getTable();
  TableColumnModel columnModel = table.getColumnModel();
  int vci = columnModel.getColumnIndexAtX(e.getX());
  int mci = table.convertColumnIndexToModel(vci);
  rolloverIndex = mci;
}

References

2011/11/28

JTable group directories first sorting

Code

// > dir /O:GN
// > ls --group-directories-first
class FileGroupComparator extends DefaultFileComparator{
  private final JTable table;
  public FileGroupComparator(JTable table, int column) {
    super(column);
    this.table = table;
  }
  public int compare(File a, File b) {
    int flag = 1;
    java.util.List < ? extends TableRowSorter.SortKey > keys
        = table.getRowSorter().getSortKeys();
    if(!keys.isEmpty()) {
      TableRowSorter.SortKey sortKey = keys.get(0);
      if(sortKey.getColumn()==column &&
         sortKey.getSortOrder()==SortOrder.DESCENDING) {
        flag = -1;
      }
    }
    if(a.isDirectory() && !b.isDirectory()) {
      return -1*flag;
    }else if(!a.isDirectory() && b.isDirectory()) {
      return  1*flag;
    }else{
      return super.compare(a, b);
    }
  }
}

References

2011/10/28

fixed width JButtons in bottom right corner of the JPanel

Code

private static JComponent createRightAlignButtonBox2(
    Listlist, int buttonWidth, int buttonHeight, int gap) {
  SpringLayout layout = new SpringLayout();
  JPanel p = new JPanel(layout);
  SpringLayout.Constraints pCons = layout.getConstraints(p);
  pCons.setConstraint(SpringLayout.SOUTH, Spring.constant(buttonHeight+gap+gap));

  Spring x     = layout.getConstraint(SpringLayout.WIDTH, p);
  Spring y     = Spring.constant(gap);
  Spring g     = Spring.minus(Spring.constant(gap));
  Spring width = Spring.constant(buttonWidth);
  for(JButton b: list) {
      SpringLayout.Constraints constraints = layout.getConstraints(b);
      constraints.setConstraint(SpringLayout.EAST, x = Spring.sum(x, g));
      constraints.setY(y);
      constraints.setWidth(width);
      p.add(b);
      x = Spring.sum(x, Spring.minus(width));
  }
  return p;
}

References

2011/09/29

JProgressBar in JComboBox

Code

class ProgressCellRenderer extends DefaultListCellRenderer {
  private final JProgressBar bar = new JProgressBar() {
    @Override public Dimension getPreferredSize() {
      return ProgressCellRenderer.this.getPreferredSize();
    }
  };
  @Override public Component getListCellRendererComponent(
      JList list, Object value, int index,
      boolean isSelected, boolean cellHasFocus) {
    if(index < 0 && worker!=null && !worker.isDone()) {
      bar.setFont(list.getFont());
      bar.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
      bar.setValue(count);
      return bar;
    }else{
      return super.getListCellRendererComponent(
          list,value,index,isSelected,cellHasFocus);
    }
  }
  @Override public void updateUI() {
    super.updateUI();
    if(bar!=null) SwingUtilities.updateComponentTreeUI(bar);
  }
}

//........
button = new JButton(new AbstractAction("load") {
  @Override public void actionPerformed(ActionEvent e) {
    button.setEnabled(false);
    combo.setEnabled(false);
    combo.removeAllItems();
    worker = new SwingWorker<String, String>() {
      private int max = 30;
      @Override public String doInBackground() {
        int current = 0;
        while(current <= max && !isCancelled()) {
          try {
            Thread.sleep(50);
            //setProgress(100 * current / max);
            count = 100 * current / max;
            publish("test: "+current);
          }catch(Exception ie) {
            return "Exception";
          }
          current++;
        }
        return "Done";
      }
      @Override protected void process(java.util.List< String > chunks) {
        DefaultComboBoxModel m = (DefaultComboBoxModel)combo.getModel();
        for(String s: chunks) {
          m.addElement(s);
        }
        combo.setSelectedIndex(-1);
        combo.repaint();
      }
      @Override public void done() {
        String text = null;
        if(!isCancelled()) {
          combo.setSelectedIndex(0);
        }
        combo.setEnabled(true);
        button.setEnabled(true);
        count = 0;
      }
    };
    worker.execute();
  }
});

References

2011/08/29

FileSystemTree with JCheckBox

Code

class CheckBoxNodeEditor extends TriStateCheckBox implements TreeCellEditor {
  private final FileSystemView fileSystemView;
  private final JPanel panel = new JPanel(new BorderLayout());
  private DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
  private File file;
  public CheckBoxNodeEditor(FileSystemView fileSystemView) {
    super();
    this.fileSystemView = fileSystemView;
    this.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        stopCellEditing();
      }
    });
    panel.setFocusable(false);
    panel.setRequestFocusEnabled(false);
    panel.setOpaque(false);
    panel.add(this, BorderLayout.WEST);
    this.setOpaque(false);
  }
  @Override public Component getTreeCellEditorComponent(
      JTree tree, Object value, boolean isSelected, boolean expanded,
      boolean leaf, int row) {
    JLabel l = (JLabel)renderer.getTreeCellRendererComponent(
        tree, value, true, expanded, leaf, row, true);
    l.setFont(tree.getFont());
    setOpaque(false);
    if(value != null && value instanceof DefaultMutableTreeNode) {
      this.setEnabled(tree.isEnabled());
      this.setFont(tree.getFont());
      Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
      if(userObject!=null && userObject instanceof CheckBoxNode) {
        CheckBoxNode node = (CheckBoxNode)userObject;
        if(node.status==Status.INDETERMINATE) {
          setIcon(new IndeterminateIcon());
        }else{
          setIcon(null);
        }
        file = node.file;
        l.setIcon(fileSystemView.getSystemIcon(file));
        l.setText(fileSystemView.getSystemDisplayName(file));
        setSelected(node.status==Status.SELECTED);
      }
      //panel.add(this, BorderLayout.WEST);
      panel.add(l);
      return panel;
    }
    return l;
  }
  @Override public Object getCellEditorValue() {
    return new CheckBoxNode(file, isSelected()?Status.SELECTED:Status.DESELECTED);
  }
  @Override public boolean isCellEditable(EventObject e) {
    if(e != null && e instanceof MouseEvent && e.getSource() instanceof JTree) {
      MouseEvent me = (MouseEvent)e;
      JTree tree = (JTree)e.getSource();
      TreePath path = tree.getPathForLocation(me.getX(), me.getY());
      Rectangle r = tree.getPathBounds(path);
      if(r==null) return false;
      Dimension d = getPreferredSize();
      r.setSize(new Dimension(d.width, r.height));
      if(r.contains(me.getX(), me.getY())) {
        if(file==null && System.getProperty("java.version").startsWith("1.7.0")) {
          System.out.println("XXX: Java 7, only on first run\n"+getBounds());
          setBounds(new Rectangle(0,0,d.width,r.height));
        }
        return true;
      }
    }
    return false;
  }
  @Override public void updateUI() {
    super.updateUI();
    if(panel!=null) panel.updateUI();
    //1.6.0_24 bug??? @see 1.7.0 DefaultTreeCellRenderer#updateUI()
    renderer = new DefaultTreeCellRenderer();
  }
//......

References

2011/07/29

Pause and Resume SwingWorker

Code

class RunAction extends AbstractAction{
  public RunAction() {
    super("run");
  }
  @Override public void actionPerformed(ActionEvent evt) {
    final JProgressBar bar1 = new JProgressBar(0, 100);
    final JProgressBar bar2 = new JProgressBar(0, 100);
    runButton.setEnabled(false);
    canButton.setEnabled(true);
    pauseButton.setEnabled(true);
    statusPanel.removeAll();
    statusPanel.add(bar1, BorderLayout.NORTH);
    statusPanel.add(bar2, BorderLayout.SOUTH);
    statusPanel.revalidate();
    worker = new SwingWorker < String, Progress > () {
      @Override public String doInBackground() {
        int current = 0;
        int lengthOfTask = 12; //filelist.size();
        publish(new Progress(Component.LOG, "Length Of Task: " + lengthOfTask));
        publish(new Progress(Component.LOG, "\n---------------------------\n"));
        while(current < lengthOfTask && !isCancelled()) {
          publish(new Progress(Component.LOG, "*"));
          if(!bar1.isDisplayable()) {
            return "Disposed";
          }
          try{
            convertFileToSomething();
          }catch(InterruptedException ie) {
            return "Interrupted";
          }
          publish(new Progress(Component.TOTAL, 100 * current / lengthOfTask));
          current++;
        }
        publish(new Progress(Component.LOG, "\n"));
        return "Done";
      }
      private final Random r = new Random();
      private void convertFileToSomething() throws InterruptedException{
        boolean flag = false;
        int current = 0;
        int lengthOfTask = 10+r.nextInt(50);
        while(current <= lengthOfTask && !isCancelled()) {
          if(isPaused) {
            try{
              Thread.sleep(500);
            }catch(InterruptedException ie) {
              return;
            }
            publish(new Progress(Component.PAUSE, flag));
            flag = !flag;
            continue;
          }
          int iv = 100 * current / lengthOfTask;
          Thread.sleep(20); // dummy
          publish(new Progress(Component.FILE, iv+1));
          current++;
        }
      }
      @Override protected void process(java.util.List < Progress > chunks) {
        for(Progress s: chunks) {
          switch(s.component) {
            case TOTAL: bar1.setValue((Integer)s.value); break;
            case FILE:  bar2.setValue((Integer)s.value); break;
            case LOG:   area.append((String)s.value); break;
            case PAUSE: {
              if((Boolean)s.value) {
                area.append("*");
              }else{
                try{
                  javax.swing.text.Document doc = area.getDocument();
                  doc.remove(area.getDocument().getLength()-1, 1);
                }catch(Exception ex) {
                    ex.printStackTrace();
                }
              }
              break;
            }
          }
        }
      }
      @Override public void done() {
        //...
      }
    };
    worker.execute();
  }
}
private boolean isPaused = false;
class PauseAction extends AbstractAction{
  public PauseAction() {
    super("pause");
  }
  @Override public void actionPerformed(ActionEvent evt) {
    isPaused = (worker!=null && !worker.isCancelled() && !isPaused);
    JButton b = (JButton)evt.getSource();
    b.setText(isPaused?"resume":"pause");
  }
}

References

2011/06/27

Gradient translucent track JSlider

Code

UIManager.put("Slider.horizontalThumbIcon", new Icon() {
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {}
  @Override public int getIconWidth()  { return 15; }
  @Override public int getIconHeight() { return 64; }
});
UIManager.put("Slider.trackWidth", 64);
UIManager.put("Slider.majorTickLength", 6);

JSlider slider = makeSlider();
slider.setUI(new MetalSliderUI() {
  int[] pallet = makeGradientPallet();
  @Override public void paintTrack(Graphics g) {
    //Color trackColor = !slider.isEnabled()
    //  ? MetalLookAndFeel.getControlShadow() : slider.getForeground();
    boolean leftToRight = true; //MetalUtils.isLeftToRight(slider);
    Color controlDarkShadow = Color.GRAY;
    Color controlHighlight = new Color(200,255,200);
    Color controlShadow = new Color(0,100,0);

    g.translate( trackRect.x, trackRect.y );

    int trackLeft = 0;
    int trackTop = 0;
    int trackRight = 0;
    int trackBottom = 0;

    // Draw the track
    if(slider.getOrientation() == JSlider.HORIZONTAL) {
      trackBottom = (trackRect.height - 1) - getThumbOverhang();
      trackTop = trackBottom - (getTrackWidth() - 1);
      trackRight = trackRect.width - 1;
    }else{
      if(leftToRight) {
        trackLeft = (trackRect.width - getThumbOverhang()) - getTrackWidth();
        trackRight = (trackRect.width - getThumbOverhang()) - 1;
      }else{
        trackLeft = getThumbOverhang();
        trackRight = getThumbOverhang() + getTrackWidth() - 1;
      }
      trackBottom = trackRect.height - 1;
    }

    if(slider.isEnabled()) {
      g.setColor(controlDarkShadow);
      g.drawRect(trackLeft, trackTop,
                 (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1);

      g.setColor(controlHighlight);
      g.drawLine(trackLeft + 1, trackBottom, trackRight, trackBottom);
      g.drawLine(trackRight, trackTop + 1, trackRight, trackBottom);

      g.setColor(controlShadow);
      g.drawLine(trackLeft + 1, trackTop + 1, trackRight - 2, trackTop + 1);
      g.drawLine(trackLeft + 1, trackTop + 1, trackLeft + 1, trackBottom - 2);
    } else {
      g.setColor(controlShadow);
      g.drawRect(trackLeft, trackTop,
                 (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1);
    }

    // Draw the fill
    int middleOfThumb = 0;
    int fillTop = 0;
    int fillLeft = 0;
    int fillBottom = 0;
    int fillRight = 0;

    if(slider.getOrientation() == JSlider.HORIZONTAL) {
      middleOfThumb = thumbRect.x + (thumbRect.width / 2);
      middleOfThumb -= trackRect.x; // To compensate for the g.translate()
      fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
      fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;

      if(!drawInverted()) {
        fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
        fillRight = middleOfThumb;
      }else{
        fillLeft = middleOfThumb;
        fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;
      }
    }else{
      middleOfThumb = thumbRect.y + (thumbRect.height / 2);
      middleOfThumb -= trackRect.y; // To compensate for the g.translate()
      fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
      fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;

      if(!drawInverted()) {
        fillTop = middleOfThumb;
        fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;
      }else{
        fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
        fillBottom = middleOfThumb;
      }
    }

    if(slider.isEnabled()) {
      g.setColor(slider.getBackground());
      g.drawLine(fillLeft, fillTop, fillRight, fillTop );
      g.drawLine(fillLeft, fillTop, fillLeft, fillBottom );

      double x = (fillRight - fillLeft) / (double)(trackRight - trackLeft);
      g.setColor(getColorFromPallet(pallet, x));
      g.fillRect(fillLeft+1,fillTop+1,fillRight-fillLeft,fillBottom-fillTop);
    }else{
      g.setColor(controlShadow);
      g.fillRect(fillLeft,fillTop,fillRight-fillLeft,trackBottom-trackTop);
    }

    int yy = trackTop + (trackBottom - trackTop) /2;
    for(int i=10;i>=0;i--) {
      g.setColor( new Color(1f,1f,1f,i*0.07f) );
      g.drawLine( trackLeft+2, yy, (trackRight - trackLeft), yy );
      yy--;
    }
    g.translate(-trackRect.x, -trackRect.y);
  }
});
private static int[] makeGradientPallet() {
  BufferedImage image = new BufferedImage(100, 1, BufferedImage.TYPE_INT_RGB);
  Graphics2D g2  = image.createGraphics();
  Point2D start  = new Point2D.Float(0f, 0f);
  Point2D end  = new Point2D.Float(99f, 0f);
  float[] dist   = {0.0f, 0.5f, 1.0f};
  Color[] colors = { Color.RED, Color.YELLOW, Color.GREEN };
  g2.setPaint(new LinearGradientPaint(start, end, dist, colors));
  g2.fillRect(0, 0, 100, 1);
  int width  = image.getWidth(null);
  int[] pallet = new int[width];
  PixelGrabber pg = new PixelGrabber(image, 0, 0, width, 1, pallet, 0, width);
  try{
    pg.grabPixels();
  }catch(Exception e) {
    e.printStackTrace();
  }
  return pallet;
}
private static Color getColorFromPallet(int[] pallet, float x) {
  int i = (int)(pallet.length * x);
  int max = pallet.length-1;
  int index = i<0?0:i>max?max:i;
  int pix = pallet[index] & 0x00ffffff | (0x64 << 24);
  return new Color(pix, true);
}

References

2011/05/30

Translucent image caption using JTextArea, OverlayLayout, EaseInOut

Code

class ImageCaptionLabel extends JLabel implements HierarchyListener {
  private float alpha = 0.0f;
  private javax.swing.Timer animator;
  private int yy = 0;
  private JTextArea textArea = new JTextArea() {
    @Override protected void paintComponent(Graphics g) {
      Graphics2D g2 = (Graphics2D)g;
      g2.setPaint(getBackground());
      g2.fillRect(0, 0, getWidth(), getHeight());
      super.paintComponent(g);
    }
    //@Override public boolean contains(int x, int y) {
    //  return false;
    //}
  };
  public ImageCaptionLabel(String caption, Icon icon) {
    setIcon(icon);
    textArea.setFont(textArea.getFont().deriveFont(11f));
    textArea.setText(caption);
    textArea.setOpaque(false);
    textArea.setEditable(false);
    //textArea.setFocusable(false);
    textArea.setBackground(new Color(0,0,0,0));
    textArea.setForeground(Color.WHITE);
    textArea.setBorder(BorderFactory.createEmptyBorder(2,4,4,4));

    MouseAdapter ma = new MouseAdapter() {
      @Override public void mouseEntered(MouseEvent e) {
        dispatchMouseEvent(e);
      }
      @Override public void mouseExited(MouseEvent e) {
        dispatchMouseEvent(e);
      }
      private void dispatchMouseEvent(MouseEvent e) {
        Component src = e.getComponent();
        Component tgt = ImageCaptionLabel.this;
        tgt.dispatchEvent(SwingUtilities.convertMouseEvent(src, e, tgt));
      }
    };
    textArea.addMouseListener(ma);

    setBorder(BorderFactory.createCompoundBorder(
      BorderFactory.createLineBorder(new Color(222,222,222)),
      BorderFactory.createLineBorder(Color.WHITE, 4)));
    setLayout(new OverlayLayout(this) {
      @Override public void layoutContainer(Container parent) {
        //Insets insets = parent.getInsets();
        int ncomponents = parent.getComponentCount();
        if(ncomponents == 0) return;
        int width = parent.getWidth(); // - (insets.left + insets.right);
        int height = parent.getHeight(); // - (insets.left + insets.right);
        int x = 0; //insets.left; int y = insets.top;
        //for(int i=0;i < ncomponents;i++) {
        Component c = parent.getComponent(0); //= textArea;
        c.setBounds(x, height-yy, width, c.getPreferredSize().height);
        //}
      }
    });
    add(textArea);

    addMouseListener(new MouseAdapter() {
      private int delay = 4;
      private int count = 0;
      @Override public void mouseEntered(MouseEvent e) {
        if(animator!=null && animator.isRunning() ||
           yy==textArea.getPreferredSize().height) return;
        final double h = (double)textArea.getPreferredSize().height;
        animator = new javax.swing.Timer(delay, new ActionListener() {
          @Override public void actionPerformed(ActionEvent e) {
            double a = easeInOut(++count/h);
            yy = (int)(.5d+a*h);
            textArea.setBackground(new Color(0f,0f,0f,(float)(0.6*a)));
            if(yy >= textArea.getPreferredSize().height) {
              yy = textArea.getPreferredSize().height;
              animator.stop();
            }
            revalidate();
            repaint();
          }
        });
        animator.start();
      }
      @Override public void mouseExited(MouseEvent e) {
        if(animator!=null && animator.isRunning() ||
           contains(e.getPoint()) && yy==textArea.getPreferredSize().height) {
            return;
        }
        final double h = (double)textArea.getPreferredSize().height;
        animator = new javax.swing.Timer(delay, new ActionListener() {
          @Override public void actionPerformed(ActionEvent e) {
            double a = easeInOut(--count/h);
            yy = (int)(.5d+a*h);
            textArea.setBackground(new Color(0f,0f,0f,(float)(0.6*a)));
            if(yy <= 0) {
              yy = 0;
              animator.stop();
            }
            revalidate();
            repaint();
          }
        });
        animator.start();
      }
    });
    addHierarchyListener(this);
  }
  @Override public void hierarchyChanged(HierarchyEvent e) {
    if((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED)!=0 &&
       animator!=null && !isDisplayable()) {
      animator.stop();
    }
  }
  //http://www.anima-entertainment.de/math-easein-easeout-easeinout-and-bezier-curves
  //coders≫ Blog Archive ≫ Math: EaseIn EaseOut, EaseInOut and Bezier Curves
  public double easeInOut(double t) {
    if(t < 0.5d) {
      return 0.5d*Math.pow(t*2d, 3d);
    }else{
      return 0.5d*(Math.pow(t*2d-2d, 3d) + 2d);
    }
  }
}

References

2011/05/24

Change border of focused row in JTable

Code

class DotBorder extends EmptyBorder {
  public enum Type { START, END; }
  private static final BasicStroke dashed = new BasicStroke(
    1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
    10.0f, (new float[] {1.0f}), 0.0f);
  private static final Color dotColor = new Color(200,150,150);
  public DotBorder(int top, int left, int bottom, int right) {
    super(top, left, bottom, right);
  }
  public EnumSet type = EnumSet.noneOf(Type.class);
  @Override public boolean isBorderOpaque() {
    return true;
  }
  @Override public void paintBorder(
        Component c, Graphics g, int x, int y, int w, int h) {
    Graphics2D g2 = (Graphics2D)g;
    g2.translate(x,y);
    g2.setPaint(dotColor);
    g2.setStroke(dashed);
    if(type.contains(Type.START)) {
      g2.drawLine(0,0,0,h);
    }
    if(type.contains(Type.END)) {
      g2.drawLine(w-1,0,w-1,h);
    }
    if(c.getBounds().x%2==0) {
      g2.drawLine(0,0,w,0);
      g2.drawLine(0,h-1,w,h-1);
    }else{
      g2.drawLine(1,0,w,0);
      g2.drawLine(1,h-1,w,h-1);
    }
    g2.translate(-x,-y);
  }
}

//......
UIManager.put("Table.focusCellHighlightBorder", new DotBorder(2,2,2,2));
JTable table = new JTable(model) {
  private final DotBorder dotBorder = new DotBorder(2,2,2,2);
  private final Border emptyBorder  = BorderFactory.createEmptyBorder(2,2,2,2);
  private void updateBorderType(DotBorder border, int column) {
    border.type = EnumSet.noneOf(DotBorder.Type.class);
    if(column==0) border.type.add(DotBorder.Type.START);
    if(column==getColumnCount()-1) border.type.add(DotBorder.Type.END);
  }
  @Override public Component prepareRenderer(
      TableCellRenderer tcr, int row, int column) {
    Component c = super.prepareRenderer(tcr, row, column);
    if(row==getSelectionModel().getLeadSelectionIndex()) {
      ((JComponent)c).setBorder(dotBorder);
      updateBorderType(dotBorder, column);
    }else{
      ((JComponent)c).setBorder(emptyBorder);
    }
    return c;
  }
  @Override public Component prepareEditor(
      TableCellEditor editor, int row, int column) {
    Component c = super.prepareEditor(editor, row, column);
    if(c instanceof JCheckBox) {
      JCheckBox b = (JCheckBox)c;
      //System.out.println(b.getBorder());
      //b.setBorder(dotBorder);
      updateBorderType((DotBorder)b.getBorder(), column);
      b.setBorderPainted(true);
      b.setBackground(getSelectionBackground());
    }
    return c;
  }
};

References

2011/04/19

Transparent JTableHeader

Code

class TransparentHeader extends JLabel implements TableCellRenderer {
  private final Border b = BorderFactory.createCompoundBorder(
      BorderFactory.createMatteBorder(0,0,1,0,Color.BLACK),
      BorderFactory.createEmptyBorder(2,2,1,2));
  private final Color alphaZero = new Color(0, true);
  @Override public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected,
        boolean hasFocus, int row, int column) {
    this.setText(value!=null?value.toString():"");
    this.setHorizontalAlignment(JLabel.CENTER);
    this.setOpaque(false);
    this.setBackground(alphaZero);
    this.setForeground(Color.BLACK);
    this.setBorder(b);
    return this;
  }
}

References

2011/03/10

CheckBoxes in JTable Cell

Code

class CheckBoxesPanel extends JPanel {
  protected final String[] title = {"r", "w", "x"};
  public JCheckBox[] buttons;
  public CheckBoxesPanel() {
    super();
    setOpaque(false);
    setBackground(new Color(0,0,0,0));
    setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
    initButtons();
  }
  protected void initButtons() {
    buttons = new JCheckBox[title.length];
    for(int i=0; i < buttons.length; i++) {
      JCheckBox b = new JCheckBox(title[i]);
      b.setOpaque(false);
      b.setFocusable(false);
      b.setRolloverEnabled(false);
      b.setBackground(new Color(0,0,0,0));
      buttons[i] = b;
      add(b);
      add(Box.createHorizontalStrut(5));
    }
  }
  protected void updateButtons(Object v) {
    if("Windows 7".equals(OSNAME)) { //Windows aero?
      removeAll();
      initButtons();
    }
    Integer i = (Integer)(v==null?0:v);
    buttons[0].setSelected((i&(1<<2))!=0);
    buttons[1].setSelected((i&(1<<1))!=0);
    buttons[2].setSelected((i&(1<<0))!=0);
  }
}
class CheckBoxesRenderer extends CheckBoxesPanel
                         implements TableCellRenderer, Serializable {
  public CheckBoxesRenderer() {
    super();
    setName("Table.cellRenderer");
  }
  @Override public Component getTableCellRendererComponent(JTable table,
      Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    updateButtons(value);
    return this;
  }
  public static class UIResource extends CheckBoxesRenderer
                                 implements UIResource{}
}
class CheckBoxesEditor extends CheckBoxesPanel
                       implements TableCellEditor, Serializable {
  public CheckBoxesEditor() {
    ActionListener al = new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        fireEditingStopped();
      }
    };
    ActionMap am = getActionMap();
    for(int i=0; i < buttons.length; i++) {
      final JCheckBox b = buttons[i];
      b.addActionListener(al);
      am.put(title[i], new AbstractAction(title[i]) {
        public void actionPerformed(ActionEvent e) {
          b.setSelected(!b.isSelected());
          fireEditingStopped();
        }
      });
    }
    InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_R, 0), title[0]);
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), title[1]);
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, 0), title[2]);
  }
  @Override public Component getTableCellEditorComponent(JTable table,
        Object value, boolean isSelected, int row, int column) {
    updateButtons(value);
    return this;
  }
  @Override public Object getCellEditorValue() {
    int i = 0;
    if(buttons[0].isSelected()) i|=1<<2;
    if(buttons[1].isSelected()) i|=1<<1;
    if(buttons[2].isSelected()) i|=1<<0;
    return i;
  }

  //Copid from AbstractCellEditor
  protected EventListenerList listenerList = new EventListenerList();
  transient protected ChangeEvent changeEvent = null;
  //......

References

2011/02/28

Highlight entire JTree row on selection

Code

final Color SELC = new Color(100,150,200);
JTree tree = new JTree() {
  @Override public void paintComponent(Graphics g) {
    g.setColor(getBackground());
    g.fillRect(0,0,getWidth(),getHeight());
    if(getSelectionCount()>0) {
      for(int i: getSelectionRows()) {
        Rectangle r = getRowBounds(i);
        g.setColor(SELC);
        g.fillRect(0, r.y, getWidth(), r.height);
      }
    }
    super.paintComponent(g);
    if(getLeadSelectionPath()!=null) {
      Rectangle r = getRowBounds(getRowForPath(getLeadSelectionPath()));
      g.setColor(SELC.darker());
      g.drawRect(0, r.y, getWidth()-1, r.height-1);
    }
  }
};
tree.setUI(new javax.swing.plaf.basic.BasicTreeUI() {
  @Override public Rectangle getPathBounds(JTree tree, TreePath path) {
    if(tree != null && treeState != null) {
      return getPathBounds(path, tree.getInsets(), new Rectangle());
    }
    return null;
  }
  private Rectangle getPathBounds(TreePath path, Insets insets, Rectangle bounds) {
    bounds = treeState.getBounds(path, bounds);
    if(bounds != null) {
      bounds.width = tree.getWidth();
      bounds.y += insets.top;
    }
    return bounds;
  }
});
tree.setOpaque(false);

References

2011/02/03

Translucent JInternalFrame (Nimbus)

Code

class MySynthStyleFactory extends SynthStyleFactory {
  private SynthStyleFactory wrappedFactory;
  public MySynthStyleFactory(SynthStyleFactory factory) {
    this.wrappedFactory = factory;
  }
  public SynthStyle getStyle(JComponent c, Region id) {
    SynthStyle s = wrappedFactory.getStyle(c, id);
    //if(id==Region.INTERNAL_FRAME_TITLE_PANE||id==Region.INTERNAL_FRAME) {
    if(id==Region.INTERNAL_FRAME) {
      s = new TranslucentSynthSytle(s);
    }
    return s;
  }
}
class TranslucentSynthSytle extends SynthStyle {
  private final SynthStyle style;
  public TranslucentSynthSytle(SynthStyle s) {
    style = s;
  }
  public SynthPainter getPainter(final SynthContext context) {
    return new SynthPainter() {
      public void paintInternalFrameBackground(SynthContext context,
                           Graphics g, int x, int y, int w, int h) {
        g.setColor(new Color(100,200,100,100));
        g.fillRoundRect(x,y,w-1,h-1,15,15);
      }
    };
  }
  public boolean isOpaque(SynthContext context) {
    if(context.getRegion()==Region.INTERNAL_FRAME) {
      return false;
    }else{
      return style.isOpaque(context);
    }
  }
  public Color getColorForState(SynthContext context, ColorType type) {
    return null; //Color.RED;
  }
  public Font getFontForState(SynthContext context) {
    return null; //new Font("MONOSPACE", Font.ITALIC, 24);
  }
  //...

References

2011/01/20

JTable RowHeader

Code

class RowHeaderList extends JList {
  private final JTable table;
  private final ListSelectionModel tableSelection;
  private final ListSelectionModel rListSelection;
  public RowHeaderList(ListModel model, JTable table) {
    super(model);
    this.table = table;
    setFixedCellHeight(table.getRowHeight());
    setCellRenderer(new RowHeaderRenderer(table.getTableHeader()));
    RollOverListener rol = new RollOverListener();
    addMouseListener(rol);
    addMouseMotionListener(rol);
    tableSelection = table.getSelectionModel();
    rListSelection = getSelectionModel();
  }
  class RowHeaderRenderer extends JLabel implements ListCellRenderer {
    private final JTableHeader header;
    public RowHeaderRenderer(JTableHeader header) {
      this.header = header;
      this.setOpaque(true);
      this.setBorder(BorderFactory.createMatteBorder(0,0,1,2,Color.GRAY));
      this.setHorizontalAlignment(CENTER);
      this.setForeground(header.getForeground());
      this.setBackground(header.getBackground());
      this.setFont(header.getFont());
    }
    public Component getListCellRendererComponent(JList list, Object value,
               int index, boolean isSelected, boolean cellHasFocus) {
      if(index==pressedRowIndex) {
        setBackground(Color.GRAY);
      }else if(index==rollOverRowIndex) {
        setBackground(Color.WHITE);
      }else if(isSelected) {
        setBackground(Color.GRAY.brighter());
      }else{
        setForeground(header.getForeground());
        setBackground(header.getBackground());
      }
      setText((value==null)?"":value.toString());
      return this;
    }
  }
}

References