// -*- mode:java; encoding:utf-8 -*-
// vim:set fileencoding=utf-8:
// @homepage@

package example;

import java.awt.*;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Objects;
import java.util.stream.Stream;
import javax.swing.*;
import javax.swing.event.ChangeListener;

public final class MainPanel extends JPanel implements HierarchyListener {
  private final BoundedRangeModel model = new DefaultBoundedRangeModel();
  private final JProgressBar progressBar1 = new StringAlignmentProgressBar(model, SwingConstants.RIGHT);
  private final JProgressBar progressBar2 = new StringAlignmentProgressBar(model, SwingConstants.LEFT);
  private final JCheckBox check = new JCheckBox("setStringPainted");
  private final JButton button = new JButton("Test");
  private transient SwingWorker<String, Void> worker;

  public MainPanel() {
    super(new BorderLayout());

    progressBar2.setBorder(BorderFactory.createTitledBorder("TitledBorder"));

    check.addActionListener(e -> {
      boolean b = ((JCheckBox) e.getSource()).isSelected();
      Stream.of(progressBar1, progressBar2).forEach(bar -> bar.setStringPainted(b));
    });

    button.addActionListener(e -> {
      if (Objects.nonNull(worker) && !worker.isDone()) {
        worker.cancel(true);
      }
      worker = new BackgroundTask();
      worker.addPropertyChangeListener(new ProgressListener(progressBar1));
      worker.execute();
    });

    JPanel p = new JPanel();
    p.setBorder(BorderFactory.createEmptyBorder(16, 16, 16, 16));
    p.add(progressBar1);
    p.add(progressBar2);

    Box box = Box.createHorizontalBox();
    box.add(Box.createHorizontalGlue());
    box.add(check);
    box.add(Box.createHorizontalStrut(5));
    box.add(button);
    box.add(Box.createHorizontalStrut(5));

    addHierarchyListener(this);
    add(p);
    add(box, BorderLayout.SOUTH);
    setPreferredSize(new Dimension(320, 240));
  }

  @Override public void hierarchyChanged(HierarchyEvent e) {
    boolean isDisplayableChanged = (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0;
    if (isDisplayableChanged && !e.getComponent().isDisplayable() && Objects.nonNull(worker)) {
      System.out.println("DISPOSE_ON_CLOSE");
      worker.cancel(true);
      worker = null;
    }
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(MainPanel::createAndShowGui);
  }

  private static void createAndShowGui() {
    try {
      // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
      ex.printStackTrace();
      Toolkit.getDefaultToolkit().beep();
    }
    JFrame frame = new JFrame("@title@");
    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    // frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MainPanel());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

class StringAlignmentProgressBar extends JProgressBar {
  private final JLabel label;
  // private transient ChangeListener changeListener;

  protected StringAlignmentProgressBar(BoundedRangeModel model, int halign) {
    super(model);
    label = new JLabel(getString(), halign);
  }

  @Override public void updateUI() {
    removeAll();
    // removeChangeListener(changeListener);
    super.updateUI();
    setLayout(new BorderLayout());
    // changeListener = e -> {
    //   // BoundedRangeModel m = (BoundedRangeModel) e.getSource(); // label.setText(m.getValue() + "%");
    //   label.setText(getString());
    // };
    // addChangeListener(changeListener);
    EventQueue.invokeLater(() -> {
      add(label);
      label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
    });
  }

  @Override protected ChangeListener createChangeListener() {
    return e -> {
      // BoundedRangeModel m = (BoundedRangeModel) e.getSource(); // label.setText(m.getValue() + "%");
      label.setText(getString());
    };
  }
}

class BackgroundTask extends SwingWorker<String, Void> {
  @Override public String doInBackground() {
    int current = 0;
    int lengthOfTask = 100;
    while (current <= lengthOfTask && !isCancelled()) {
      try { // dummy task
        Thread.sleep(50);
      } catch (InterruptedException ex) {
        return "Interrupted";
      }
      setProgress(100 * current / lengthOfTask);
      current++;
    }
    return "Done";
  }
}

class ProgressListener implements PropertyChangeListener {
  private final JProgressBar progressBar;

  protected ProgressListener(JProgressBar progressBar) {
    this.progressBar = progressBar;
    this.progressBar.setValue(0);
  }

  @Override public void propertyChange(PropertyChangeEvent e) {
    String strPropertyName = e.getPropertyName();
    if ("progress".equals(strPropertyName)) {
      progressBar.setIndeterminate(false);
      int progress = (Integer) e.getNewValue();
      progressBar.setValue(progress);
    }
  }
}

@@ -757,131 +757,8 @@
 T);%0A
-  private final JCheckBox check = new JCheckBox(%22setStringPainted%22);%0A  private final JButton button = new JButton(%22Test%22);%0A
   pr
@@ -811,21 +811,22 @@
 er;%0A%0A  p
-ublic
+rivate
  MainPan
@@ -939,24 +939,81 @@
 Border%22));%0A%0A
+    JCheckBox check = new JCheckBox(%22setStringPainted%22);%0A
     check.ad
@@ -1185,24 +1185,66 @@
 );%0A    %7D);%0A%0A
+    JButton button = new JButton(%22Test%22);%0A
     button.a
@@ -3405,21 +3405,34 @@
 l, int h
-align
+orizontalAlignment
 ) %7B%0A    
@@ -3486,13 +3486,26 @@
 ), h
-align
+orizontalAlignment
 );%0A 
@@ -3696,126 +3696,8 @@
 e -%3E
- %7B%0A    //   // BoundedRangeModel m = (BoundedRangeModel) e.getSource(); // label.setText(m.getValue() + %22%25%22);%0A    //  
  lab
@@ -3725,18 +3725,8 @@
 ));%0A
-    // %7D;%0A
     
@@ -3978,120 +3978,8 @@
 e -%3E
- %7B%0A      // BoundedRangeModel m = (BoundedRangeModel) e.getSource(); // label.setText(m.getValue() + %22%25%22);%0A     
  lab
@@ -4007,15 +4007,8 @@
 ));%0A
-    %7D;%0A
   %7D%0A
@@ -4109,16 +4109,44 @@
 ground()
+ throws InterruptedException
  %7B%0A    i
@@ -4255,133 +4255,25 @@
     
-try %7B // dummy task%0A        Thread.sleep(50);%0A      %7D catch (InterruptedException ex) %7B%0A        return %22Interrupted%22;%0A      %7D
+Thread.sleep(50);
 %0A   

statement lambda can be replaced with expression lambda