Java tutorial
/* * Copyright 2004 - 2008 Christian Sprajc. All rights reserved. * * This file is part of PowerFolder. * * PowerFolder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * PowerFolder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PowerFolder. If not, see <http://www.gnu.org/licenses/>. * * $Id$ */ package de.dal33t.powerfolder.ui.dialog; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.List; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JRadioButton; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.factories.ButtonBarFactory; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import de.dal33t.powerfolder.Controller; import de.dal33t.powerfolder.disk.SyncProfile; import de.dal33t.powerfolder.disk.SyncProfileConfiguration; import de.dal33t.powerfolder.ui.panel.SyncProfileSelectorPanel; import de.dal33t.powerfolder.util.Translation; /** * Dialog for creatigng or editing profile configuration. User can select a * default profile and then adjust the configuration. * * @author <a href="mailto:hglasgow@powerfolder.com">Harry Glasgow</a> * @version $Revision: 2.01 $ */ public class CreateEditSyncProfileDialog extends BaseDialog implements ActionListener, KeyListener { private JTextField syncProfileName; private JComboBox<String> syncProfilesCombo; private JCheckBox autoDownloadBox; private JCheckBox syncDeletionBox; private SpinnerNumberModel scanTimeModel; private JSpinner scanTimeSpinner; private SyncProfileSelectorPanel syncProfileSelectorPanel; private JLabel scanInfoLabel; private JRadioButton periodicRadioButton; private JRadioButton dailyRadioButton; private JRadioButton instantRadioButton; private SpinnerNumberModel hourModel; private JSpinner hourSpinner; private JComboBox<String> dayCombo; private JComboBox<String> timeTypeCombo; private final boolean create; private JButton saveButton; private final SyncProfileConfiguration originalConfiguration; private final String originalProfileName; /** * Constructor. * * @param controller * @param syncProfileSelectorPanel */ public CreateEditSyncProfileDialog(Controller controller, SyncProfileSelectorPanel syncProfileSelectorPanel, boolean create) { super(Senior.NONE, controller, true); this.syncProfileSelectorPanel = syncProfileSelectorPanel; this.create = create; originalConfiguration = syncProfileSelectorPanel.getSyncProfile().getConfiguration(); originalProfileName = syncProfileSelectorPanel.getSyncProfile().getName(); } /** * Gets the title of the dialog. * * @return */ public String getTitle() { if (create) { return Translation.getTranslation("exp.dialog.create_edit_profile.title_create"); } else { return Translation.getTranslation("exp.dialog.create_edit_profile.title_edit"); } } /** * Gets the icon for the dialog. * * @return */ protected Icon getIcon() { return null; } /** * Creates the visual component. * * @return */ protected JComponent getContent() { initComponents(); FormLayout layout = new FormLayout("right:pref, 3dlu, pref", "pref, 15dlu, pref, 15dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref"); PanelBuilder builder = new PanelBuilder(layout); builder.setDefaultDialogBorder(); CellConstraints cc = new CellConstraints(); // Profile name builder.add(new JLabel(Translation.getTranslation("exp.dialog.create_edit_profile.profile_name")), cc.xy(1, 1)); builder.add(syncProfileName, cc.xy(3, 1)); builder.add(new JLabel(Translation.getTranslation("exp.dialog.create_edit_profile.configure_from")), cc.xy(1, 3)); builder.add(createSyncComboPanel(), cc.xy(3, 3)); builder.addSeparator(Translation.getTranslation("exp.dialog.create_edit_profile.synchronization"), cc.xyw(1, 5, 3)); builder.add(autoDownloadBox, cc.xy(3, 7)); builder.add(syncDeletionBox, cc.xy(3, 9)); builder.addSeparator(Translation.getTranslation("exp.dialog.create_edit_profile.change_detection"), cc.xyw(1, 11, 3)); builder.add(instantRadioButton, cc.xy(3, 13)); builder.add(periodicRadioButton, cc.xy(3, 15)); builder.add(new JLabel(Translation.getTranslation("exp.dialog.create_edit_profile.time_between_scans")), cc.xy(1, 17)); builder.add(createRegularPanel(), cc.xy(3, 17)); builder.add(dailyRadioButton, cc.xy(3, 19)); builder.add(new JLabel(Translation.getTranslation("exp.dialog.create_edit_profile.hour_day_sync")), cc.xy(1, 21)); builder.add(createDailyComboPanel(), cc.xy(3, 21)); ButtonGroup bg = new ButtonGroup(); bg.add(periodicRadioButton); bg.add(dailyRadioButton); bg.add(instantRadioButton); return builder.getPanel(); } private Component createSyncComboPanel() { FormLayout layout = new FormLayout("pref", "pref"); PanelBuilder builder = new PanelBuilder(layout); CellConstraints cc = new CellConstraints(); builder.add(syncProfilesCombo, cc.xy(1, 1)); return builder.getPanel(); } public Component createDailyComboPanel() { FormLayout layout = new FormLayout("pref, 3dlu, pref", "pref"); PanelBuilder builder = new PanelBuilder(layout); CellConstraints cc = new CellConstraints(); builder.add(hourSpinner, cc.xy(1, 1)); builder.add(dayCombo, cc.xy(3, 1)); return builder.getPanel(); } public Component createRegularPanel() { FormLayout layout = new FormLayout("pref, 3dlu, pref", "pref"); PanelBuilder builder = new PanelBuilder(layout); CellConstraints cc = new CellConstraints(); builder.add(scanTimeSpinner, cc.xy(1, 1)); builder.add(scanInfoLabel, cc.xy(3, 1)); builder.add(timeTypeCombo, cc.xy(3, 1)); return builder.getPanel(); } /** * Initialize the dialog components. */ private void initComponents() { SyncProfile initialProfile = syncProfileSelectorPanel.getSyncProfile(); // Profile name syncProfileName = new JTextField(); if (create) { String suggestedName = calculateBestName(initialProfile.getName()); syncProfileName.setText(suggestedName); } else { syncProfileName.setText(initialProfile.getName()); } syncProfileName.addKeyListener(this); syncProfilesCombo = new JComboBox<>(); syncProfilesCombo.addItem(""); for (SyncProfile syncProfile : SyncProfile.getSyncProfilesCopy()) { syncProfilesCombo.addItem(syncProfile.getName()); } syncProfilesCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { preselectDefaults(); } }); autoDownloadBox = new JCheckBox(Translation.getTranslation("exp.dialog.create_edit_profile.auto_download")); syncDeletionBox = new JCheckBox(Translation.getTranslation("exp.dialog.create_edit_profile.sync_deletion")); scanTimeModel = new SpinnerNumberModel(0, 0, 9999, 1); scanTimeSpinner = new JSpinner(scanTimeModel); scanInfoLabel = new JLabel( Translation.getTranslation("exp.dialog.create_edit_profile.change_detection_manual")); scanTimeModel.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { infoTypeVisible(); } }); periodicRadioButton = new JRadioButton( Translation.getTranslation("exp.dialog.create_edit_profile.periodic_sync")); periodicRadioButton.addActionListener(this); dailyRadioButton = new JRadioButton( Translation.getTranslation("exp.dialog.create_edit_profile.daily_sync")); dailyRadioButton.addActionListener(this); instantRadioButton = new JRadioButton( Translation.getTranslation("exp.dialog.create_edit_profile.instant_sync")); instantRadioButton.addActionListener(this); dayCombo = new JComboBox<>(new String[] { Translation.getTranslation("exp.dialog.create_edit_profile.every_day"), Translation.getTranslation("general.sunday"), Translation.getTranslation("general.monday"), Translation.getTranslation("general.tuesday"), Translation.getTranslation("general.wednesday"), Translation.getTranslation("general.thursday"), Translation.getTranslation("general.friday"), Translation.getTranslation("general.saturday"), Translation.getTranslation("exp.dialog.create_edit_profile.weekdays"), Translation.getTranslation("exp.dialog.create_edit_profile.weekends") }); dayCombo.setMaximumRowCount(10); hourModel = new SpinnerNumberModel(12, 0, 23, 1); hourSpinner = new JSpinner(hourModel); dayCombo.addActionListener(this); timeTypeCombo = new JComboBox<>(new String[] { Translation.getTranslation("general.hours"), Translation.getTranslation("general.minutes"), Translation.getTranslation("general.seconds") }); timeTypeCombo.addActionListener(this); // Initialise settings. SyncProfile syncProfile = syncProfileSelectorPanel.getSyncProfile(); SyncProfileConfiguration configuration = syncProfile.getConfiguration(); autoDownloadBox.setSelected(configuration.isAutoDownload()); syncDeletionBox.setSelected(configuration.isSyncDeletion()); scanTimeModel.setValue(configuration.getTimeBetweenRegularScans()); dailyRadioButton.setSelected(configuration.isDailySync()); periodicRadioButton.setSelected(configuration.isPeriodicSync()); instantRadioButton.setSelected(configuration.isInstantSync()); hourModel.setValue(configuration.getDailyHour()); dayCombo.setSelectedIndex(configuration.getDailyDay()); if (configuration.getRegularTimeType().equals(SyncProfileConfiguration.REGULAR_TIME_TYPE_HOURS)) { timeTypeCombo.setSelectedIndex(0); } else if (configuration.getRegularTimeType().equals(SyncProfileConfiguration.REGULAR_TIME_TYPE_SECONDS)) { timeTypeCombo.setSelectedIndex(2); } else { timeTypeCombo.setSelectedIndex(1); } scanTimeSpinner.setEnabled(configuration.isPeriodicSync()); hourSpinner.setEnabled(configuration.isDailySync()); dayCombo.setEnabled(configuration.isDailySync()); timeTypeCombo.setEnabled(configuration.isPeriodicSync()); infoTypeVisible(); } /** * Show scanInfoLabel and timeTypeCombo depending on scanTimeModel value. */ private void infoTypeVisible() { if (scanTimeModel.getNumber().intValue() == 0) { scanInfoLabel.setVisible(true); timeTypeCombo.setVisible(false); } else { scanInfoLabel.setVisible(false); timeTypeCombo.setVisible(true); } } /** * Create a suggested profile name based on current profile. Like 'Automatic * download (copy)', or 'Manual synchronization (copy 6)'. * * @param profileName * @return */ private static String calculateBestName(String profileName) { int copy = 0; boolean unique; String profileNameCopy; do { unique = true; if (copy == 0) { profileNameCopy = Translation.getTranslation("exp.dialog.create_edit_profile.suggestNameTemplate0", profileName); } else { profileNameCopy = Translation.getTranslation("exp.dialog.create_edit_profile.suggestNameTemplateN", profileName, String.valueOf(copy)); } for (SyncProfile loopSyncProfile : SyncProfile.getSyncProfilesCopy()) { String loopProfileName = loopSyncProfile.getName(); if (loopProfileName.equalsIgnoreCase(profileNameCopy)) { unique = false; break; } } copy++; } while (!unique); return profileNameCopy; } /** * Sets configuration settings based on the current combo selection. */ private void preselectDefaults() { int index = syncProfilesCombo.getSelectedIndex() - 1; // Remove blank // initial entry List<SyncProfile> syncProfileList = SyncProfile.getSyncProfilesCopy(); if (index >= 0 && index < syncProfileList.size()) { SyncProfile syncProfile = SyncProfile.getSyncProfilesCopy().get(index); SyncProfileConfiguration configuration = syncProfile.getConfiguration(); autoDownloadBox.setSelected(configuration.isAutoDownload()); syncDeletionBox.setSelected(configuration.isSyncDeletion()); scanTimeModel.setValue(configuration.getTimeBetweenRegularScans()); periodicRadioButton.setSelected(configuration.isPeriodicSync()); periodicRadioButton.setSelected(configuration.isInstantSync()); dailyRadioButton.setSelected(configuration.isDailySync()); hourModel.setValue(configuration.getDailyHour()); dayCombo.setSelectedIndex(configuration.getDailyDay()); if (configuration.getRegularTimeType().equals(SyncProfileConfiguration.REGULAR_TIME_TYPE_HOURS)) { timeTypeCombo.setSelectedIndex(0); } else if (configuration.getRegularTimeType() .equals(SyncProfileConfiguration.REGULAR_TIME_TYPE_SECONDS)) { timeTypeCombo.setSelectedIndex(2); } else { timeTypeCombo.setSelectedIndex(1); } enableTimeDate(); syncProfilesCombo.setSelectedIndex(0); } } /** * The OK / Cancel buttons. * * @return */ protected Component getButtonBar() { saveButton = new JButton(Translation.getTranslation("general.save")); saveButton.setMnemonic(Translation.getTranslation("general.save.key").trim().charAt(0)); saveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { savePressed(); } }); configureSaveButton(); JButton cancelButton = createCancelButton(new ActionListener() { public void actionPerformed(ActionEvent e) { cancelPressed(); } }); return ButtonBarFactory.buildCenteredBar(saveButton, cancelButton); } protected JButton getDefaultButton() { return saveButton; } // Methods for FolderPreferencesPanel ************************************** /** * If user clicks save, update the profile in the selector panel. */ private void savePressed() { String timeType = SyncProfileConfiguration.REGULAR_TIME_TYPE_MINUTES; if (timeTypeCombo.getSelectedIndex() == 0) { timeType = SyncProfileConfiguration.REGULAR_TIME_TYPE_HOURS; } else if (timeTypeCombo.getSelectedIndex() == 2) { timeType = SyncProfileConfiguration.REGULAR_TIME_TYPE_SECONDS; } boolean instantMode = instantRadioButton.isSelected(); boolean dailyMode = !instantMode && dailyRadioButton.isSelected(); SyncProfileConfiguration newConfiguration = new SyncProfileConfiguration(autoDownloadBox.isSelected(), autoDownloadBox.isSelected(), syncDeletionBox.isSelected(), syncDeletionBox.isSelected(), scanTimeModel.getNumber().intValue(), dailyMode, hourModel.getNumber().intValue(), dayCombo.getSelectedIndex(), timeType, instantMode); String newProfileName = syncProfileName.getText().trim(); if (create) { // Name and config must be unique. if (checkDuplicateProfileName(newProfileName) || checkDuplicateConfiguration(newConfiguration)) { return; } // Store new profile SyncProfile syncProfile = SyncProfile.retrieveSyncProfile(newProfileName, newConfiguration); syncProfileSelectorPanel.setSyncProfile(syncProfile, true); } else { // If no change, do nothing. if (originalProfileName.equals(newProfileName) && originalConfiguration.equals(newConfiguration)) { close(); } // Get the current sync profile. SyncProfile syncProfile = syncProfileSelectorPanel.getSyncProfile(); if (!originalConfiguration.equals(newConfiguration)) { // Check new configuration is unique. if (checkDuplicateConfiguration(newConfiguration)) { return; } // Update the profile with configuration changes. syncProfile.setConfiguration(newConfiguration); // Set in the selector panel so it gets persisted. syncProfileSelectorPanel.setSyncProfile(syncProfile, true); } if (!originalProfileName.equals(newProfileName)) { // Check new profileName is unique. if (checkDuplicateProfileName(newProfileName)) { return; } // Update the profile with name change. syncProfile.setName(newProfileName); // Set in the selector panel so it sees the name change. syncProfileSelectorPanel.setSyncProfile(syncProfile, true); } } close(); } /** * Check if there are already profiles with this name. * * @param profileName * name to check * @return true if a profile already exists with this name */ private boolean checkDuplicateProfileName(String profileName) { for (SyncProfile syncProfile : SyncProfile.getSyncProfilesCopy()) { if (syncProfile.getName().equals(profileName)) { String title = Translation.getTranslation("exp.dialog.create_edit_profile.duplicate_profile_title"); String message = Translation.getTranslation("exp.dialog.create_edit_profile.cannot_save_name", syncProfile.getName()); DialogFactory.genericDialog(getController(), title, message, GenericDialogType.ERROR); return true; } } return false; } /** * Check if there are already profiles with this configuration. * * @param newConfiguration * @return */ private boolean checkDuplicateConfiguration(SyncProfileConfiguration newConfiguration) { for (SyncProfile syncProfile : SyncProfile.getSyncProfilesCopy()) { if (syncProfile.getConfiguration().equals(newConfiguration)) { String title = Translation.getTranslation("exp.dialog.create_edit_profile.duplicate_profile_title"); String message = Translation.getTranslation("exp.dialog.create_edit_profile.cannot_save_profile", syncProfile.getName()); DialogFactory.genericDialog(getController(), title, message, GenericDialogType.ERROR); return true; } } return false; } /** * User does not want to commit any change. */ private void cancelPressed() { close(); } public void actionPerformed(ActionEvent e) { if (e.getSource().equals(periodicRadioButton) || e.getSource().equals(dailyRadioButton) || e.getSource().equals(instantRadioButton)) { enableTimeDate(); } } private void enableTimeDate() { scanTimeSpinner.setEnabled(periodicRadioButton.isSelected()); scanInfoLabel.setEnabled(periodicRadioButton.isSelected()); timeTypeCombo.setEnabled(periodicRadioButton.isSelected()); hourSpinner.setEnabled(dailyRadioButton.isSelected()); dayCombo.setEnabled(dailyRadioButton.isSelected()); } public void keyTyped(KeyEvent e) { if (e.getSource() == syncProfileName) { configureSaveButton(); } } private void configureSaveButton() { // Enable the OK button if a neam is entered. saveButton.setEnabled(syncProfileName.getText().trim().length() > 0); } public void keyPressed(KeyEvent e) { // Not required } public void keyReleased(KeyEvent e) { // Veto any comma (,) characters, because these may make the config // fail. // Commas are used to separate profile fields. String text = syncProfileName.getText(); while (text.endsWith(SyncProfile.FIELD_LIST_DELIMITER)) { syncProfileName.removeKeyListener(this); syncProfileName.setText(text.substring(0, text.length() - 1)); syncProfileName.addKeyListener(this); // Keep going; user may have held key to get auto-repeat! text = syncProfileName.getText(); } } }