Google Tag Manager

2019/01/30

Swap the position of the child components in the JSplitPane

Code

JSplitPane sp = new JSplitPane();
sp.setLeftComponent(new JScrollPane(new JTree()));
sp.setRightComponent(new JScrollPane(new JTable(6, 3)));
sp.setResizeWeight(.4);

JButton button = new JButton("swap");
button.setFocusable(false);
button.addActionListener(e -> {
  Component left = sp.getLeftComponent();
  Component right = sp.getRightComponent();

  // sp.removeAll(); // Divider is also removed
  sp.remove(left);
  sp.remove(right);
  // or: https://stackoverflow.com/questions/4871874/java-problem-with-jsplitpane
  // sp.setLeftComponent(null);
  // sp.setRightComponent(null);

  sp.setLeftComponent(right);
  sp.setRightComponent(left);

  sp.setResizeWeight(1d - sp.getResizeWeight());
  if (check.isSelected()) {
    sp.setDividerLocation(sp.getDividerLocation());
  }
});

References

2018/12/27

Fade out JTabbedPane tab title on overflow instead of ellipsis

Code

class TextOverflowFadeTabbedPane extends ClippedTitleTabbedPane {
  protected TextOverflowFadeTabbedPane() {
    super();
  }

  protected TextOverflowFadeTabbedPane(int tabPlacement) {
    super(tabPlacement);
  }

  @Override public void insertTab(
        String title, Icon icon, Component component, String tip, int index) {
    super.insertTab(title, icon, component, Objects.toString(tip, title), index);
    JPanel p = new JPanel(new BorderLayout(2, 0));
    p.setOpaque(false);
    p.add(new JLabel(icon), BorderLayout.WEST);
    p.add(new TextOverflowFadeLabel(title));
    setTabComponentAt(index, p);
  }
}

class TextOverflowFadeLabel extends JLabel {
  private static final int LENGTH = 20;
  private static final float DIFF = .05f;

  protected TextOverflowFadeLabel(String text) {
    super(text);
  }

  @Override public void paintComponent(Graphics g) {
    Insets i = getInsets();
    int w = getWidth() - i.left - i.right;
    int h = getHeight() - i.top - i.bottom;
    Rectangle rect = new Rectangle(i.left, i.top, w - LENGTH, h);

    Graphics2D g2 = (Graphics2D) g.create();
    g2.setFont(g.getFont());
    g2.setPaint(getForeground());

    FontRenderContext frc = g2.getFontRenderContext();
    TextLayout tl = new TextLayout(getText(), getFont(), frc);
    int baseline = getBaseline(w, h);

    g2.setClip(rect);
    tl.draw(g2, getInsets().left, baseline);

    rect.width = 1;
    float alpha = 1f;
    for (int x = w - LENGTH; x < w; x++) {
      rect.x = x;
      alpha = Math.max(0f, alpha - DIFF);
      g2.setComposite(AlphaComposite.SrcOver.derive(alpha));
      g2.setClip(rect);
      tl.draw(g2, getInsets().left, baseline);
    }
    g2.dispose();
  }
}

References

2018/11/29

Add editable JCheckBox to ComboBoxEditor of JComboBox

Code

class CheckComboBoxEditor implements ComboBoxEditor {
  private final EditorPanel editor = new EditorPanel(new ComboItem());
  @Override public void selectAll() {
    editor.selectAll();
  }

  @Override public Object getItem() {
    return editor.getItem();
  }

  @Override public void setItem(Object anObject) {
    EventQueue.invokeLater(() -> {
      Container c = SwingUtilities.getAncestorOfClass(
          JComboBox.class, getEditorComponent());
      if (c instanceof JComboBox) {
        JComboBox<?> combo = (JComboBox<?>) c;
        int idx = combo.getSelectedIndex();
        if (idx >= 0 && idx != editor.getEditingIndex()) {
          System.out.println("setItem: " + idx);
          editor.setEditingIndex(idx);
        }
      }
    });
    if (anObject instanceof ComboItem) {
      editor.setItem((ComboItem) anObject);
    } else {
      editor.setItem(new ComboItem());
    }
  }

  @Override public Component getEditorComponent() {
    return editor;
  }

  @Override public void addActionListener(ActionListener l) {
    editor.addActionListener(l);
  }

  @Override public void removeActionListener(ActionListener l) {
    editor.removeActionListener(l);
  }
}

final class EditorPanel extends JPanel {
  private final JCheckBox enabledCheck = new JCheckBox();
  private final JCheckBox editableCheck = new JCheckBox();
  private final JTextField textField = new JTextField("", 16);
  private final transient ComboItem data;
  private int editingIndex = -1;

  protected EditorPanel(ComboItem data) {
    super();
    this.data = data;
    setItem(data);

    enabledCheck.addActionListener(e -> {
      Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
      if (c instanceof JComboBox) {
        JComboBox<?> combo = (JComboBox<?>) c;
        ComboItem item = (ComboItem) combo.getItemAt(editingIndex);
        item.setEnabled(((JCheckBox) e.getSource()).isSelected());
        editableCheck.setEnabled(item.isEnabled());
        textField.setEnabled(item.isEnabled());
        combo.setSelectedIndex(editingIndex);
      }
    });
    enabledCheck.setOpaque(false);
    enabledCheck.setFocusable(false);

    editableCheck.addActionListener(e -> {
      Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
      if (c instanceof JComboBox) {
        JComboBox<?> combo = (JComboBox<?>) c;
        ComboItem item = (ComboItem) combo.getItemAt(editingIndex);
        item.setEditable(((JCheckBox) e.getSource()).isSelected());
        textField.setEditable(item.isEditable());
        combo.setSelectedIndex(editingIndex);
      }
    });
    editableCheck.setOpaque(false);
    editableCheck.setFocusable(false);

    textField.addActionListener(e -> {
      Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
      if (c instanceof JComboBox) {
        JComboBox<?> combo = (JComboBox<?>) c;
        ComboItem item = (ComboItem) combo.getItemAt(editingIndex);
        item.setText(((JTextField) e.getSource()).getText());
        combo.setSelectedIndex(editingIndex);
      }
    });
    textField.setBorder(BorderFactory.createEmptyBorder());
    textField.setOpaque(false);

    setOpaque(false);
    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));

    add(enabledCheck);
    add(editableCheck);
    add(textField);
  }

  public int getEditingIndex() {
    return editingIndex;
  }

  public void setEditingIndex(int idx) {
    this.editingIndex = idx;
  }

  public ComboItem getItem() {
    data.setEnabled(enabledCheck.isSelected());
    data.setEditable(editableCheck.isSelected());
    data.setText(textField.getText());
    return data;
  }

  public void setItem(ComboItem item) {
    enabledCheck.setSelected(item.isEnabled());

    editableCheck.setSelected(item.isEditable());
    editableCheck.setEnabled(item.isEnabled());

    textField.setText(item.getText());
    textField.setEnabled(item.isEnabled());
    textField.setEditable(item.isEditable());
  }

  public void selectAll() {
    textField.requestFocusInWindow();
    textField.selectAll();
  }

  public void addActionListener(ActionListener l) {
    textField.addActionListener(l);
    enabledCheck.addActionListener(l);
    editableCheck.addActionListener(l);
  }

  public void removeActionListener(ActionListener l) {
    textField.removeActionListener(l);
    enabledCheck.removeActionListener(l);
    editableCheck.removeActionListener(l);
  }
}

References

2018/10/31

Create an Image Comparison Slider with JSplitPane

Code

ImageIcon icon = new ImageIcon(getClass().getResource("test.png"));

Component beforeCanvas = new JComponent() {
  @Override protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int iw = icon.getIconWidth();
    int ih = icon.getIconHeight();
    g.drawImage(icon.getImage(), 0, 0, iw, ih, this);
  }
};
split.setLeftComponent(beforeCanvas);

Component afterCanvas = new JComponent() {
  @Override protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g.create();
    int iw = icon.getIconWidth();
    int ih = icon.getIconHeight();
    if (check.isSelected()) {
      g2.setColor(getBackground());
      g2.setXORMode(Color.BLUE);
    } else {
      g2.setPaintMode();
    }
    Point pt = getLocation();
    Insets ins = split.getBorder().getBorderInsets(split);
    g2.translate(-pt.x + ins.left, 0);
    g2.drawImage(icon.getImage(), 0, 0, iw, ih, this);
    g2.dispose();
  }
};
split.setRightComponent(afterCanvas);

References

2018/09/30

Expand the zip file selected by JFileChooser

Code

JButton button1 = new JButton("unzip");
button1.addActionListener(e -> {
  String str = field.getText();
  Path path = Paths.get(str);
  if (str.isEmpty() || Files.notExists(path)) {
    return;
  }
  String name = Objects.toString(path.getFileName());
  int lastDotPos = name.lastIndexOf('.');
  if (lastDotPos > 0) {
    name = name.substring(0, lastDotPos);
  }
  Path destDir = path.resolveSibling(name);
  try {
    if (Files.exists(destDir)) {
      String m = String.format(
          "<html>%s already exists.<br>Do you want to overwrite it?",
          destDir.toString());
      int rv = JOptionPane.showConfirmDialog(
          button1.getRootPane(), m, "Unzip", JOptionPane.YES_NO_OPTION);
      if (rv != JOptionPane.YES_OPTION) {
        return;
      }
    } else {
      if (LOGGER.isLoggable(Level.INFO)) {
        LOGGER.info("mkdir0: " + destDir.toString());
      }
      Files.createDirectories(destDir);
    }
    ZipUtil.unzip(path, destDir);
  } catch (IOException ex) {
    ex.printStackTrace();
  }
});
// ...
public static void unzip(Path zipFilePath, Path destDir) throws IOException {
  try (ZipFile zipFile = new ZipFile(zipFilePath.toString())) {
    Enumeration<? extends ZipEntry> e = zipFile.entries();
    while (e.hasMoreElements()) {
      ZipEntry zipEntry = e.nextElement();
      String name = zipEntry.getName();
      Path path = destDir.resolve(name);
      if (name.endsWith("/")) { // if (Files.isDirectory(path)) {
        log("mkdir1: " + path.toString());
        Files.createDirectories(path);
      } else {
        Path parent = path.getParent();
        if (Files.notExists(parent)) {
          log("mkdir2: " + parent.toString());
          Files.createDirectories(parent);
        }
        log("copy: " + path.toString());
        Files.copy(zipFile.getInputStream(zipEntry),
                   path, StandardCopyOption.REPLACE_EXISTING);
      }
    }
  }
}
//...
public static void zip(Path srcDir, Path zip) throws IOException {
  try (Stream<Path> s = Files.walk(srcDir).filter(Files::isRegularFile)) {
    List<Path> files = s.collect(Collectors.toList());
    try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(zip))) {
      for (Path f: files) {
        String relativePath = srcDir.relativize(f).toString();
        ZipEntry ze = new ZipEntry(relativePath.replace('\\', '/'));
        zos.putNextEntry(ze);
        Files.copy(f, zos);
      }
    }
  }
}

References