package zander.ui.library; import java.awt.BorderLayout; import java.awt.Window; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import zander.library.Library; import zander.library.Library.SyncStatus; import zander.ui.ErrorDialog; import zander.ui.UIUtils; public class LibrarySyncDialog extends JDialog { private static final long serialVersionUID = -7042632100445849219L; public static final int STATUS_OK = 0; public static final int STATUS_CANCELED = 1; public static final int STATUS_FAILED = 2; private final Library library; private JLabel messageLabel; private JProgressBar progressBar; private JTextArea statusArea; private JScrollPane statusScroll; private JPanel statusPanel; private JButton cancelButton; private JPanel buttonPanel; private final JPanel content; private SyncStatus status; private String lastNote = ""; public LibrarySyncDialog(Window parent, Library library) { super(parent, "Sync Library"); this.library = library; messageLabel = new JLabel("Syncing Library..."); progressBar = new JProgressBar(0, 1); progressBar.setValue(0); progressBar.setStringPainted(true); statusArea = new JTextArea(10, 15); statusArea.setEditable(false); statusScroll = new JScrollPane(statusArea); statusPanel = new JPanel(); statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.Y_AXIS)); statusPanel.add(progressBar); statusPanel.add(statusScroll); cancelButton = new JButton("Cancel"); cancelButton.addActionListener((e) -> { if (status != null && status.isStarted() && !status.isDone()) { status.cancel(); } dispose(); }); buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); buttonPanel.add(Box.createHorizontalGlue()); buttonPanel.add(cancelButton); content = new JPanel(new BorderLayout()); content.add(messageLabel, BorderLayout.PAGE_START); content.add(statusPanel, BorderLayout.CENTER); content.add(buttonPanel, BorderLayout.PAGE_END); setContentPane(content); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setModalityType(JDialog.DEFAULT_MODALITY_TYPE); setAlwaysOnTop(true); setMinimumSize(getPreferredSize()); UIUtils.centerWindow(this, parent); } public Library getLibrary() { return library; } private void addMessage(String m) { String t = statusArea.getText(); if (t.isBlank()) { statusArea.setText(m); } else { statusArea.setText(t + "\n" + m); } } private void syncUpdateAction(SyncStatus status) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater(() -> syncUpdateAction(status)); } else { if (status.isFailed()) { dispose(); ErrorDialog ed = new ErrorDialog("Sync Failed", "Failed to sync local cahce to remote store!", status.getError()); ed.setVisible(true); } else if (status.isDone()) { dispose(); } else { if (status.getTotal() < 0) { progressBar.setIndeterminate(true); } else { progressBar.setIndeterminate(false); progressBar.setMaximum(status.getTotal()); } progressBar.setValue(status.getCurrent()); String note = status.getNote(); if (note != null && !note.isBlank() && !note.equals(lastNote)) { addMessage(note); lastNote = note; } } } } public int sync() { status = library.syncLocalToRemoteAsync(this::syncUpdateAction); setVisible(true); dispose(); if (status.isFailed()) { return STATUS_FAILED; } else if (status.isCanceled()) { return STATUS_CANCELED; } return STATUS_OK; } }