Google Tag Manager

2018/12/27

aterai

Fade out JTabbedPane tab title on overflow instead of ellipsis

Code

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

  protected TextOverfloFadeTabbedPane(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 TextOverfloFadeLabel(title));
    setTabComponentAt(index, p);
  }
}

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

  protected TextOverfloFadeLabel(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

aterai

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

aterai

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

aterai

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(
          "%s already exists.
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 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 s = Files.walk(srcDir).filter(Files::isRegularFile)) { List 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

2018/08/29

aterai

Change the tab of JTabbedPane to a flat design style

Code

UIManager.put("TabbedPane.tabInsets", new Insets(5, 10, 5, 10));
UIManager.put("TabbedPane.tabAreaInsets", new Insets(0, 0, 0, 0));
UIManager.put("TabbedPane.selectedLabelShift", 0);
UIManager.put("TabbedPane.labelShift", 0);

// UIManager.put("TabbedPane.foreground", Color.WHITE);
// UIManager.put("TabbedPane.selectedForeground", Color.WHITE);
// UIManager.put("TabbedPane.unselectedBackground", UNSELECTED_BG);
UIManager.put("TabbedPane.tabAreaBackground", UNSELECTED_BG);

JTabbedPane tabs = new JTabbedPane() {
  @Override public void updateUI() {
    super.updateUI();
    setUI(new BasicTabbedPaneUI() {
      @Override protected void paintFocusIndicator(
          Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex,
          Rectangle iconRect, Rectangle textRect, boolean isSelected) {
        // Do not paint anything
      }
      @Override protected void paintTabBorder(
          Graphics g, int tabPlacement, int tabIndex,
          int x, int y, int w, int h, boolean isSelected) {
        // Do not paint anything
      }
      @Override  protected void paintTabBackground(
          Graphics g, int tabPlacement, int tabIndex,
          int x, int y, int w, int h, boolean isSelected) {
        g.setColor(isSelected ? SELECTED_BG : UNSELECTED_BG);
        g.fillRect(x, y, w, h);
      }
      @Override protected void paintContentBorderRightEdge(
          Graphics g, int tabPlacement, int selectedIndex,
          int x, int y, int w, int h) {
        g.setColor(SELECTED_BG);
        g.fillRect(x, y, w, h);
      }
      // ...
    });
    setOpaque(true);
    setForeground(Color.WHITE);
    setTabPlacement(SwingConstants.LEFT);
    setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
  }
};

References