Java tutorial
/* This Source Code Form is subject to the terms of the Mozilla * Public License, v. 2.0. If a copy of the MPL was not distributed * with this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2017 Ilya Zemskov */ package ru.develgame.jflickrorganizer; import com.flickr4java.flickr.photos.Photo; import java.awt.Component; import java.awt.event.ItemEvent; import java.io.File; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import javax.annotation.PostConstruct; import javax.naming.directory.InvalidAttributesException; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.JTree; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreeSelectionModel; import org.springframework.beans.factory.annotation.Autowired; import ru.develgame.jflickrorganizer.Common.Authorizer; import ru.develgame.jflickrorganizer.Threads.GetPhotoListRunnable; import ru.develgame.jflickrorganizer.Common.LocaleMessages; import ru.develgame.jflickrorganizer.Common.Status; import ru.develgame.jflickrorganizer.DataModel.AlbumFilter; import ru.develgame.jflickrorganizer.DataModel.ListFilters; import ru.develgame.jflickrorganizer.DataModel.TablePhotosDataModel; import static ru.develgame.jflickrorganizer.DataModel.TablePhotosDataModel.*; import ru.develgame.jflickrorganizer.DataModel.TreeAlbumsDataModel; import ru.develgame.jflickrorganizer.DataModel.VisibilityComboBoxDataModel; import ru.develgame.jflickrorganizer.DataModel.VisibilityComboBoxDataModel.WrapperVisibility; import ru.develgame.jflickrorganizer.DataModel.VisibilityFilter; import ru.develgame.jflickrorganizer.Threads.BackupRunnable; import ru.develgame.jflickrorganizer.Threads.BackupSetsRunnable; import ru.develgame.jflickrorganizer.entities.Album; import ru.develgame.jflickrorganizer.repositories.UserRepository; /** * * @author Ilya Zemskov */ public abstract class MainForm extends javax.swing.JFrame { @Autowired private TablePhotosDataModel tablePhotosDataModel; @Autowired private TreeAlbumsDataModel treeAlbumsDataModel; @Autowired private ListFilters listFilters; @Autowired private UserRepository userRepository; @Autowired private Authorizer authorizer; @Autowired private VisibilityComboBoxDataModel visibilityComboBoxDataModel; private AlbumFilter albumFilter; private VisibilityFilter visibilityFilter; /** * Creates new form MainForm */ public MainForm() { initComponents(); setLocationRelativeTo(null); } @PostConstruct public void init() { jTablePhotos.setModel(tablePhotosDataModel); jTablePhotos.setRowHeight(COLUMN_PIC_MIN_HEIGHT); if (authorizer.getUser().getSyncFolder() != null) jTextFieldBackupFolder.setText(authorizer.getUser().getSyncFolder()); jTablePhotos.getTableHeader().setReorderingAllowed(false); jScrollPane2.getViewport().setBackground(jTablePhotos.getBackground()); jTreeAlbums.setModel(treeAlbumsDataModel); jTreeAlbums.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); jTreeAlbums.setCellRenderer(new AlbumTreeCellRender(jTreeAlbums.getCellRenderer())); jTreeAlbums.setSelectionRow(0); albumFilter = new AlbumFilter(null); listFilters.addCondition(albumFilter); jTreeAlbums.addTreeSelectionListener(e -> { Album selectedAlbum = ((TreeAlbumsDataModel.AlbumNode) jTreeAlbums.getLastSelectedPathComponent()) .getAlbum(); AlbumFilter newAlbumFilter = new AlbumFilter(selectedAlbum); listFilters.replaceFilter(albumFilter, newAlbumFilter); albumFilter = newAlbumFilter; tablePhotosDataModel.loadData(); // TODO - updateStatusBar }); jComboBoxVisibility.setModel(visibilityComboBoxDataModel); visibilityFilter = new VisibilityFilter((WrapperVisibility) jComboBoxVisibility.getSelectedItem()); listFilters.addCondition(visibilityFilter); jComboBoxVisibility.addItemListener(e -> { if (e.getStateChange() == ItemEvent.SELECTED) { VisibilityFilter newVisibilityFilter = new VisibilityFilter( (WrapperVisibility) jComboBoxVisibility.getSelectedItem()); listFilters.replaceFilter(visibilityFilter, newVisibilityFilter); visibilityFilter = newVisibilityFilter; tablePhotosDataModel.loadData(); } }); updateStatusBar(); tablePhotosDataModel.addTableModelListener(e -> { updateStatusBar(); }); DateTableCellRenderer dateTableCellRenderer = new DateTableCellRenderer(); jTablePhotos.getColumnModel().getColumn(COLUMN_DATE_TAKEN).setCellRenderer(dateTableCellRenderer); jTablePhotos.getColumnModel().getColumn(COLUMN_DATE_UPLOADED).setCellRenderer(dateTableCellRenderer); jButtonChooseBackupFolder.setEnabled(!authorizer.isOfflineMode()); jButtonBackup.setEnabled(!authorizer.isOfflineMode()); jTextFieldBackupFolder.setEnabled(!authorizer.isOfflineMode()); jLabelBackupFolder.setEnabled(!authorizer.isOfflineMode()); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jLabelBackupFolder = new javax.swing.JLabel(); jTextFieldBackupFolder = new javax.swing.JTextField(); jButtonChooseBackupFolder = new javax.swing.JButton(); jButtonBackup = new javax.swing.JButton(); jScrollPane1 = new javax.swing.JScrollPane(); jTreeAlbums = new javax.swing.JTree(); jScrollPane2 = new javax.swing.JScrollPane(); jTablePhotos = new JTable() { @Override public Component prepareRenderer(TableCellRenderer renderer, int row, int column) { Component component = super.prepareRenderer(renderer, row, column); int rendererWidth = component.getPreferredSize().width + 5; TableColumn tableColumn = getColumnModel().getColumn(column); tableColumn.setPreferredWidth( Math.max(rendererWidth + getIntercellSpacing().width, tableColumn.getPreferredWidth())); return component; } }; jComboBoxVisibility = new javax.swing.JComboBox<>(); jPanel1 = new javax.swing.JPanel(); jLabelAll = new javax.swing.JLabel(); jMenuBar1 = new javax.swing.JMenuBar(); jMenu1 = new javax.swing.JMenu(); jMenuItemSetPassword = new javax.swing.JMenuItem(); jMenuItemExit = new javax.swing.JMenuItem(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("MainForm"); // NOI18N setTitle(bundle.getString("MainForm.title")); // NOI18N setMinimumSize(new java.awt.Dimension(1024, 717)); setName("Form"); // NOI18N jLabelBackupFolder.setText(bundle.getString("MainForm.jLabelBackupFolder.text")); // NOI18N jLabelBackupFolder.setName("jLabelBackupFolder"); // NOI18N jTextFieldBackupFolder.setName("jTextFieldBackupFolder"); // NOI18N jButtonChooseBackupFolder.setText(bundle.getString("MainForm.jButtonChooseBackupFolder.text")); // NOI18N jButtonChooseBackupFolder.setName("jButtonChooseBackupFolder"); // NOI18N jButtonChooseBackupFolder.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonChooseBackupFolderActionPerformed(evt); } }); jButtonBackup.setText(bundle.getString("MainForm.jButtonBackup.text")); // NOI18N jButtonBackup.setName("jButtonBackup"); // NOI18N jButtonBackup.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonBackupActionPerformed(evt); } }); jScrollPane1.setName("jScrollPane1"); // NOI18N jTreeAlbums.setName("jTreeAlbums"); // NOI18N jScrollPane1.setViewportView(jTreeAlbums); jScrollPane2.setName("jScrollPane2"); // NOI18N jTablePhotos.setAutoCreateRowSorter(true); jTablePhotos.setModel(new javax.swing.table.DefaultTableModel(new Object[][] { }, new String[] { })); jTablePhotos.setToolTipText(bundle.getString("MainForm.jTablePhotos.toolTipText")); // NOI18N jTablePhotos.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF); jTablePhotos.setName("jTablePhotos"); // NOI18N jTablePhotos.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); jScrollPane2.setViewportView(jTablePhotos); jComboBoxVisibility.setName("jComboBoxVisibility"); // NOI18N jPanel1.setName("jPanel1"); // NOI18N jLabelAll.setText(bundle.getString("MainForm.jLabelAll.text")); // NOI18N jLabelAll.setName("jLabelAll"); // NOI18N javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout .setHorizontalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabelAll).addContainerGap())); jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE).addComponent(jLabelAll))); jMenuBar1.setName("jMenuBar1"); // NOI18N jMenu1.setText(bundle.getString("MainForm.jMenu1.text")); // NOI18N jMenu1.setName("jMenu1"); // NOI18N jMenuItemSetPassword.setText(bundle.getString("MainForm.jMenuItemSetPassword.text")); // NOI18N jMenuItemSetPassword.setName("jMenuItemSetPassword"); // NOI18N jMenuItemSetPassword.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenuItemSetPasswordActionPerformed(evt); } }); jMenu1.add(jMenuItemSetPassword); jMenuItemExit.setText(bundle.getString("MainForm.jMenuItemExit.text")); // NOI18N jMenuItemExit.setName("jMenuItemExit"); // NOI18N jMenuItemExit.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenuItemExitActionPerformed(evt); } }); jMenu1.add(jMenuItemExit); jMenuBar1.add(jMenu1); setJMenuBar(jMenuBar1); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addComponent(jLabelBackupFolder) .addGap(68, 68, 68).addComponent(jTextFieldBackupFolder) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jButtonChooseBackupFolder) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jButtonBackup)) .addGroup(layout.createSequentialGroup() .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 213, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 784, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(jComboBoxVisibility, javax.swing.GroupLayout.PREFERRED_SIZE, 271, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, Short.MAX_VALUE))))) .addContainerGap()) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup( javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup().addContainerGap().addGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jTextFieldBackupFolder, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jButtonBackup).addComponent(jButtonChooseBackupFolder) .addComponent(jLabelBackupFolder)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jComboBoxVisibility, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 590, Short.MAX_VALUE)) .addComponent(jScrollPane1)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))); pack(); }// </editor-fold>//GEN-END:initComponents private void jButtonChooseBackupFolderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonChooseBackupFolderActionPerformed JFileChooser jFileChooserSaveBackup = new JFileChooser(); jFileChooserSaveBackup.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int returnVal = jFileChooserSaveBackup.showSaveDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { jTextFieldBackupFolder.setText(jFileChooserSaveBackup.getSelectedFile().getAbsolutePath()); } }//GEN-LAST:event_jButtonChooseBackupFolderActionPerformed private void jButtonBackupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonBackupActionPerformed if (jTextFieldBackupFolder.getText().isEmpty()) { JOptionPane.showMessageDialog(this, LocaleMessages.getMessage("MainForm.Warning.BackupFolderEmpty"), LocaleMessages.getMessage("WarningTitle"), JOptionPane.WARNING_MESSAGE); return; } File backupFolder = new File(jTextFieldBackupFolder.getText()); if (!backupFolder.exists()) { JOptionPane.showMessageDialog(this, LocaleMessages.getMessage("MainForm.Warning.BackupFolderNotExists"), LocaleMessages.getMessage("WarningTitle"), JOptionPane.WARNING_MESSAGE); return; } if (!backupFolder.isDirectory()) { JOptionPane.showMessageDialog(this, LocaleMessages.getMessage("MainForm.Warning.BackupFolderNotDirectory"), LocaleMessages.getMessage("WarningTitle"), JOptionPane.WARNING_MESSAGE); return; } try { // === Get photo list === GetPhotoListRunnable photoListRunnable = getGetPhotoListRunnable(); ProgressForm indeterminateProgressForm = new ProgressForm(this, true, LocaleMessages.getMessage("ProgressForm.GetPhotosList"), photoListRunnable, true); indeterminateProgressForm.setVisible(true); indeterminateProgressForm.dispose(); if (photoListRunnable.getStatus() != Status.STATUS_OK) { if (photoListRunnable.getStatus() == Status.STATUS_CANCELED) return; JOptionPane.showMessageDialog(this, LocaleMessages.getMessage("MainForm.Error.GetPhotoList", photoListRunnable.getError()), LocaleMessages.getMessage("ErrorTitle"), JOptionPane.ERROR_MESSAGE); return; } // === Backup photos === BackupRunnable backupRunnable = getBackupRunnable(photoListRunnable.getPhotos(), backupFolder); ProgressForm progressForm = new ProgressForm(this, true, LocaleMessages.getMessage("ProgressForm.BackupPhotos"), backupRunnable, false); progressForm.setVisible(true); progressForm.dispose(); if (backupRunnable.getStatus() != Status.STATUS_OK) { if (backupRunnable.getStatus() == Status.STATUS_CANCELED) { tablePhotosDataModel.loadData(); return; } JOptionPane.showMessageDialog(this, LocaleMessages.getMessage("MainForm.Error.BackupPhotos", backupRunnable.getError()), LocaleMessages.getMessage("ErrorTitle"), JOptionPane.ERROR_MESSAGE); return; } // === Backup sets === BackupSetsRunnable backupSetsRunnable = getBackupSetsRunnable(); ProgressForm indeterminateProgressFormBackupSets = new ProgressForm(this, true, LocaleMessages.getMessage("ProgressForm.BackupSets"), backupSetsRunnable, true); indeterminateProgressFormBackupSets.setVisible(true); indeterminateProgressFormBackupSets.dispose(); if (backupSetsRunnable.getStatus() != Status.STATUS_OK) { if (backupSetsRunnable.getStatus() == Status.STATUS_CANCELED) { treeAlbumsDataModel.loadData(); jTreeAlbums.setSelectionRow(0); tablePhotosDataModel.loadData(); return; } JOptionPane.showMessageDialog(this, LocaleMessages.getMessage("MainForm.Error.BackupPhotos", backupSetsRunnable.getError()), LocaleMessages.getMessage("ErrorTitle"), JOptionPane.ERROR_MESSAGE); return; } JOptionPane.showMessageDialog(this, LocaleMessages.getMessage("MainForm.Info.BackupPhotos"), LocaleMessages.getMessage("InformationTitle"), JOptionPane.INFORMATION_MESSAGE); authorizer.getUser().setSyncFolder(jTextFieldBackupFolder.getText()); userRepository.save(authorizer.getUser()); treeAlbumsDataModel.loadData(); jTreeAlbums.setSelectionRow(0); tablePhotosDataModel.loadData(); } catch (InvalidAttributesException ex) { JOptionPane.showMessageDialog(this, LocaleMessages.getMessage("MainForm.Error.BackupPhotos", ex.getMessage()), LocaleMessages.getMessage("ErrorTitle"), JOptionPane.ERROR_MESSAGE); return; } }//GEN-LAST:event_jButtonBackupActionPerformed private void jMenuItemSetPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemSetPasswordActionPerformed PasswordForm passwordForm = new PasswordForm(this, true); passwordForm.setVisible(true); if (passwordForm.getAnswer()) { String hashedPass = ""; try { MessageDigest m = MessageDigest.getInstance("SHA-1"); m.reset(); m.update(passwordForm.getPassword().getBytes()); hashedPass = new String(m.digest()); } catch (NoSuchAlgorithmException ex) { // TODO return; } authorizer.getUser().setPass(hashedPass); userRepository.save(authorizer.getUser()); } passwordForm.dispose(); }//GEN-LAST:event_jMenuItemSetPasswordActionPerformed private void jMenuItemExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemExitActionPerformed this.setVisible(false); this.dispose(); }//GEN-LAST:event_jMenuItemExitActionPerformed private void updateStatusBar() { jLabelAll.setText(LocaleMessages.getMessage("MainForm.StatusBar.All", String.format("%-10s", jTablePhotos.getRowCount()))); } private static class AlbumTreeCellRender extends DefaultTreeCellRenderer { private TreeCellRenderer renderer; public AlbumTreeCellRender(TreeCellRenderer renderer) { this.renderer = renderer; } @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { return renderer.getTreeCellRendererComponent(tree, value, selected, expanded, false, row, hasFocus); } } private static class DateTableCellRenderer extends DefaultTableCellRenderer { private final SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy"); @Override public Component getTableCellRendererComponent(JTable jtable, Object o, boolean bln, boolean bln1, int i, int i1) { if (o instanceof Date) { o = dateFormat.format(o); } return super.getTableCellRendererComponent(jtable, o, bln, bln1, i, i1); } } protected abstract GetPhotoListRunnable getGetPhotoListRunnable(); protected abstract BackupRunnable getBackupRunnable(List<Photo> photos, File backupFolder); protected abstract BackupSetsRunnable getBackupSetsRunnable(); // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton jButtonBackup; private javax.swing.JButton jButtonChooseBackupFolder; private javax.swing.JComboBox<WrapperVisibility> jComboBoxVisibility; private javax.swing.JLabel jLabelAll; private javax.swing.JLabel jLabelBackupFolder; private javax.swing.JMenu jMenu1; private javax.swing.JMenuBar jMenuBar1; private javax.swing.JMenuItem jMenuItemExit; private javax.swing.JMenuItem jMenuItemSetPassword; private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTable jTablePhotos; private javax.swing.JTextField jTextFieldBackupFolder; private javax.swing.JTree jTreeAlbums; // End of variables declaration//GEN-END:variables }