/*
* JFileSync
* Copyright (C) 2002-2007, Jens Heidrich
*
* This program 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; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301, USA
*/
package jfs.gui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.List;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import jfs.conf.JFSConfig;
import jfs.conf.JFSDirectoryPair;
import jfs.conf.JFSSyncMode;
import jfs.conf.JFSSyncModes;
import jfs.conf.JFSText;
/**
* This dialog is responsible for changing options within the configuration object (aka user's profile) currently used.
*
* @author Jens Heidrich
* @version $Id: JFSConfigView.java,v 1.26 2007/06/06 19:51:33 heidrich Exp $
*/
public class JFSConfigView extends JDialog implements ActionListener, ListSelectionListener {
/**
* The UID.
*/
private static final long serialVersionUID = 50L;
/**
* The new configuration object.
*/
private final JFSConfig configNew;
/**
* The title text field.
*/
private final JTextField title;
/**
* The synchronization mode box.
*/
@SuppressWarnings("rawtypes")
private final JComboBox syncMode;
/**
* The synchronization modes.
*/
private final List<JFSSyncMode> syncModeList;
/**
* The table of directory pairs.
*/
private final JTable directoryTable;
/**
* Number of directory pairs.
*/
private final JLabel directoryLabel;
/**
* The up button.
*/
private final JButton upButton;
/**
* The down button.
*/
private final JButton downButton;
/**
* The change button.
*/
private final JButton changeButton;
/**
* The remove button.
*/
private final JButton removeButton;
/**
* Initializes the config view.
*
* @param frame
* The main frame.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public JFSConfigView(JFrame frame) {
super(frame, true);
JFSConfig config = JFSConfig.getInstance();
// Clone the existing configuration object:
configNew = (JFSConfig) config.clone();
// Get the translation object:
JFSText t = JFSText.getInstance();
// Create the modal dialog:
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setTitle(t.get("profile.title")+config.getTitle());
setResizable(false);
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
// A reference to the corresponding selection models of the table:
ListSelectionModel selection;
// Initialize directory pair table:
JFSDirectoryTable jfsDirectoryTable = new JFSDirectoryTable(configNew);
directoryTable = jfsDirectoryTable.getJTable();
selection = directoryTable.getSelectionModel();
selection.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
selection.addListSelectionListener(this);
// Call dialog if row is double-clicked:
final JFSConfigView configView = this;
directoryTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount()==2) {
int row = directoryTable.rowAtPoint(e.getPoint());
JFSDirectoryPair pair = configNew.getDirectoryList().get(row);
new JFSConfigDirectoryView(configView, configNew, pair);
}
}
});
// Create directory panel:
JPanel directoryPanel = new JPanel(new BorderLayout());
directoryPanel.setBorder(new TitledBorder(t.get("profile.dir.table.title")));
directoryPanel.add(new JScrollPane(directoryTable), BorderLayout.CENTER);
JPanel directoryStatePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
directoryLabel = new JLabel();
directoryStatePanel.add(directoryLabel);
JPanel directoryButtonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
upButton = JFSSupport.getButton("button.up", "button.up", this);
downButton = JFSSupport.getButton("button.down", "button.down", this);
JButton addButton = JFSSupport.getButton("button.add", "button.add", this);
changeButton = JFSSupport.getButton("button.change", "button.change", this);
removeButton = JFSSupport.getButton("button.remove", "button.remove", this);
directoryButtonPanel.add(upButton);
directoryButtonPanel.add(downButton);
directoryButtonPanel.add(addButton);
directoryButtonPanel.add(changeButton);
directoryButtonPanel.add(removeButton);
JPanel directoryStateAndButtonPanel = new JPanel(new BorderLayout());
directoryStateAndButtonPanel.add(directoryStatePanel, BorderLayout.WEST);
directoryStateAndButtonPanel.add(directoryButtonPanel, BorderLayout.EAST);
directoryPanel.add(directoryStateAndButtonPanel, BorderLayout.SOUTH);
// Create options panel:
JLabel titleLabel = new JLabel(t.get("profile.title"));
title = new JTextField(configNew.getTitle(), 40);
// Set-up modes:
JLabel syncModeLabel = new JLabel(t.get("profile.syncMode"));
JFSSyncModes modes = JFSSyncModes.getInstance();
syncMode = new JComboBox();
syncModeList = new Vector<JFSSyncMode>(modes.getModes());
for (JFSSyncMode mode : syncModeList) {
syncMode.addItem(t.get(mode.getAlias()));
}
// Determine and select current mode:
JFSSyncMode currentMode = modes.getCurrentMode();
int currentIndex = syncModeList.indexOf(currentMode);
if (currentIndex!=-1) {
syncMode.setSelectedIndex(currentIndex);
}
// Set-up panels:
JPanel row1Panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
row1Panel.add(titleLabel);
row1Panel.add(title);
JPanel row2Panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
row2Panel.add(syncModeLabel);
row2Panel.add(syncMode);
JPanel row3Panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
row3Panel.add(JFSSupport.getButton("profile.advanced.button", "ADVANCED", this));
row3Panel.add(JFSSupport.getButton("profile.filter.includes", "INCLUDES", this));
row3Panel.add(JFSSupport.getButton("profile.filter.excludes", "EXCLUDES", this));
row3Panel.add(JFSSupport.getButton("server.title", "server.title", this));
JPanel optionsPanel = new JPanel(new GridLayout(3, 1));
optionsPanel.setBorder(new TitledBorder(t.get("profile.option.heading")));
optionsPanel.add(row1Panel);
optionsPanel.add(row2Panel);
optionsPanel.add(row3Panel);
// Create buttons in a separate panel:
JPanel buttonPanel = new JPanel();
buttonPanel.add(JFSSupport.getButton("button.ok", "button.ok", this));
buttonPanel.add(JFSSupport.getButton("button.cancel", "button.cancel", this));
// Add all panels:
cp.add(optionsPanel, BorderLayout.NORTH);
cp.add(directoryPanel, BorderLayout.CENTER);
cp.add(buttonPanel, BorderLayout.SOUTH);
// First update and button check:
update();
checkButtons();
// Pack and activate dialog:
directoryPanel.setPreferredSize(new Dimension(500, 300));
pack();
JFSSupport.center(frame, this);
this.setVisible(true);
}
/**
* @see ActionListener#actionPerformed(ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent event) {
String cmd = event.getActionCommand();
if ("button.up".equals(cmd)) {
int row = directoryTable.getSelectedRow();
// If a row is selected and it is not the first one then
// move it one position upwards:
if (row>0) {
JFSDirectoryPair pair = configNew.removeDirectoryPair(row);
configNew.insertDirectoryPair(pair, row-1);
directoryTable.setRowSelectionInterval(row-1, row-1);
update();
}
}
if ("button.down".equals(cmd)) {
int row = directoryTable.getSelectedRow();
// If a row is selected and it is not the last one then
// move it one position upwards:
if ((row>-1)&&(row<(directoryTable.getRowCount()-1))) {
JFSDirectoryPair pair = configNew.removeDirectoryPair(row);
// If 'row' is the last element just add a new
// last element, otherwise insert 'pair' at 'row+1':
if (row==(directoryTable.getRowCount()-1)) {
configNew.addDirectoryPair(pair);
} else {
configNew.insertDirectoryPair(pair, row+1);
}
directoryTable.setRowSelectionInterval(row+1, row+1);
update();
}
}
if ("button.add".equals(cmd)) {
new JFSConfigDirectoryView(this, configNew, new JFSDirectoryPair("", ""));
update();
checkButtons();
}
if ("button.change".equals(cmd)&&!directoryTable.getSelectionModel().isSelectionEmpty()) {
JFSDirectoryPair pair = configNew.getDirectoryList().get(directoryTable.getSelectedRow());
new JFSConfigDirectoryView(this, configNew, pair);
update();
}
if ("button.remove".equals(cmd)) {
ListSelectionModel model = directoryTable.getSelectionModel();
// If a row is selected remove it from the table:
if (!model.isSelectionEmpty()) {
int row = model.getLeadSelectionIndex();
configNew.removeDirectoryPair(row);
if (row>0) {
model.setLeadSelectionIndex(row-1);
} else if ((row==0)&&(directoryTable.getRowCount()>0)) {
model.setLeadSelectionIndex(0);
} else {
model.clearSelection();
}
update();
}
}
if ("button.cancel".equals(cmd)||"button.ok".equals(cmd)) {
setVisible(false);
dispose();
}
if ("button.ok".equals(cmd)) {
// Update the new configuration object:
configNew.setTitle(title.getText());
JFSSyncMode mode = syncModeList.get(syncMode.getSelectedIndex());
configNew.setSyncMode((byte) mode.getId());
// Transfer the data to the current object and update all
// configuration object observers:
JFSConfig config = JFSConfig.getInstance();
configNew.transferContentTo(config);
}
if ("ADVANCED".equals(cmd)) {
new JFSConfigAdvancedView(this, configNew);
}
if ("INCLUDES".equals(cmd)) {
new JFSConfigFilterView(this, configNew, true);
}
if ("EXCLUDES".equals(cmd)) {
new JFSConfigFilterView(this, configNew, false);
}
if ("server.title".equals(cmd)) {
new JFSConfigServerView(this, configNew);
}
}
/**
* Launches a dialog to create a new directory if the specified one doesn't exist.
*
* @param component
* The frame to attach the dialog.
* @param dir
* The directory to create.
*/
public static void createDirectoryDialog(Component component, String dir) {
// Test for existence:
for (String schema : JFSConfigDirectoryView.OTHER_PRODUCER_CODES) {
if (dir.startsWith(schema)) {
dir = dir.substring((schema+"://").length());
} // if
} // for
// No URL given
if (!dir.matches("[a-z][a-z][a-z]*://.*")) {
File file = new File(dir);
if (!file.exists()) {
// Create dialog:
JFSText t = JFSText.getInstance();
JPanel panel = new JPanel(new GridLayout(3, 1));
JLabel msg = new JLabel(t.get("profile.dir.create.message"));
JLabel question = new JLabel(t.get("profile.dir.create.question"));
JTextField directory = new JTextField(dir);
panel.add(msg);
panel.add(question);
panel.add(directory);
int result = JOptionPane.showConfirmDialog(component, panel, t.get("profile.dir.create.title"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
if (result==JOptionPane.OK_OPTION) {
if (!file.mkdirs()) {
JLabel failed = new JLabel(t.get("profile.dir.message.failed"));
JOptionPane.showMessageDialog(component, failed, t.get("profile.dir.create.title"),
JOptionPane.WARNING_MESSAGE);
}
}
}
}
}
/**
* Called whenever values of the table change.
*/
private void update() {
// Get the translation object:
JFSText t = JFSText.getInstance();
// Update directory label:
directoryLabel.setText(configNew.getDirectoryList().size()+" "+t.get("general.objectNo"));
// Update table:
directoryTable.revalidate();
directoryTable.repaint();
}
/**
* Checks buttons whether it makes sense to activate or deactivate them.
*/
private void checkButtons() {
if (directoryTable.getSelectionModel().isSelectionEmpty()) {
upButton.setEnabled(false);
downButton.setEnabled(false);
changeButton.setEnabled(false);
removeButton.setEnabled(false);
} else {
if (directoryTable.getSelectedRow()==0) {
upButton.setEnabled(false);
} else {
upButton.setEnabled(true);
}
if (directoryTable.getSelectedRow()==directoryTable.getModel().getRowCount()-1) {
downButton.setEnabled(false);
} else {
downButton.setEnabled(true);
}
changeButton.setEnabled(true);
removeButton.setEnabled(true);
}
}
/**
* @see ListSelectionListener#valueChanged(ListSelectionEvent)
*/
@Override
public void valueChanged(ListSelectionEvent e) {
checkButtons();
}
}