/*
* Copyright (c) 2006, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ProjectDirectoriesDialog.java,v 1.9 2008/10/03 13:46:30 fros4943 Exp $
*/
package se.sics.cooja.dialogs;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.GUI;
import se.sics.cooja.ProjectConfig;
/**
* This dialog allows a user to manage the project directory configurations. Project
* directories can be added, removed or reordered. The resulting
* configuration can also be viewed.
*
* This dialog reads from the external project configuration files in each project
* directory, as well as from any specified default configuration files.
*
* @author Fredrik Osterlind
*/
public class ProjectDirectoriesDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(ProjectDirectoriesDialog.class);
private List changeableProjectsList = new List();
private List fixedProjectsList = null;
private Vector<File> changeableProjects = null;
private ProjectDirectoriesDialog myDialog;
/**
* Allows user to alter the given project directories list by adding new,
* reordering or removing project directories. Only the changeable project directories
* can be altered.
*
* @param parentContainer
* Parent container
* @param changeableProjects
* Changeable project directories
* @param fixedProjects
* Fixed project directory
* @return Null if dialog aborted, else the new CHANGEABLE project directory list.
*/
public static Vector<File> showDialog(Container parentContainer,
Vector<File> changeableProjects, Vector<File> fixedProjects) {
if (GUI.isVisualizedInApplet()) {
return null;
}
ProjectDirectoriesDialog myDialog = null;
if (parentContainer instanceof Window) {
myDialog = new ProjectDirectoriesDialog((Window) parentContainer, changeableProjects, fixedProjects);
} else if (parentContainer instanceof Dialog) {
myDialog = new ProjectDirectoriesDialog((Dialog) parentContainer, changeableProjects, fixedProjects);
} else if (parentContainer instanceof Frame) {
myDialog = new ProjectDirectoriesDialog((Frame) parentContainer, changeableProjects, fixedProjects);
} else {
logger.fatal("Unknown parent container type: " + parentContainer);
return null;
}
myDialog.setLocationRelativeTo(parentContainer);
if (myDialog != null) {
myDialog.setVisible(true);
}
return myDialog.changeableProjects;
}
/**
* Allows user to alter the given project directories list by adding new,
* reordering or removing project directories. Only the changeable project directories
* may be altered.
*
* @param parentDialog
* Parent dialog
* @param changeableProjects
* Changeable project directories
* @param fixedProjects
* Fixed project directory
* @return Null if dialog aborted, else the new CHANGEABLE project directory list.
*/
public static Vector<File> showDialog(Dialog parentDialog,
Vector<File> changeableProjects, Vector<File> fixedProjects) {
ProjectDirectoriesDialog myDialog = new ProjectDirectoriesDialog(parentDialog,
changeableProjects, fixedProjects);
myDialog.setLocationRelativeTo(parentDialog);
if (myDialog != null) {
myDialog.setVisible(true);
}
return myDialog.changeableProjects;
}
private ProjectDirectoriesDialog(Frame frame, Vector<File> changeableProjects,
Vector<File> fixedProjects) {
super(frame, "Manage Project Directories", ModalityType.APPLICATION_MODAL);
setupDialog(changeableProjects, fixedProjects);
}
private ProjectDirectoriesDialog(Dialog dialog, Vector<File> changeableProjects,
Vector<File> fixedProjects) {
super(dialog, "Manage Project Directories", ModalityType.APPLICATION_MODAL);
setupDialog(changeableProjects, fixedProjects);
}
private ProjectDirectoriesDialog(Window window, Vector<File> changeableProjects,
Vector<File> fixedProjects) {
super(window, "Manage Project Directories", ModalityType.APPLICATION_MODAL);
setupDialog(changeableProjects, fixedProjects);
}
private void setupDialog(Vector<File> changeablePlatforms, Vector<File> fixedProjects) {
myDialog = this;
JPanel mainPane = new JPanel();
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
JPanel smallPane;
JButton button;
// BOTTOM BUTTON PART
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
button = new JButton("Cancel");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changeableProjects = null;
dispose();
}
});
buttonPane.add(button);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
if (fixedProjects == null) {
button = new JButton("Set default");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object[] options = { "Ok", "Cancel" };
String newDefaultProjectDirs = "";
for (String directory : changeableProjectsList.getItems()) {
if (newDefaultProjectDirs != "") {
newDefaultProjectDirs += ";";
}
newDefaultProjectDirs += directory;
}
newDefaultProjectDirs = newDefaultProjectDirs.replace('\\', '/');
String question = "External tools setting DEFAULT_PROJECTDIRS will change from:\n"
+ GUI.getExternalToolsSetting("DEFAULT_PROJECTDIRS")
+ "\n to:\n"
+ newDefaultProjectDirs + "\n\nAre you sure?";
String title = "Change external tools settings?";
int answer = JOptionPane.showOptionDialog(myDialog, question, title,
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null,
options, options[0]);
if (answer != JOptionPane.YES_OPTION) {
return;
}
GUI.setExternalToolsSetting("DEFAULT_PROJECTDIRS",
newDefaultProjectDirs);
}
});
buttonPane.add(button);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
}
button = new JButton("OK");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changeableProjects = new Vector<File>();
for (String directory : changeableProjectsList.getItems()) {
File projectDir = new File(directory);
if (projectDir.exists() && projectDir.isDirectory()) {
changeableProjects.add(projectDir);
} else {
logger.fatal("Can't find project directory: " + projectDir);
}
}
dispose();
}
});
buttonPane.add(button);
this.getRootPane().setDefaultButton(button);
// LIST PART
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS));
listPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JPanel listPane2 = new JPanel();
listPane2.setLayout(new BoxLayout(listPane2, BoxLayout.Y_AXIS));
if (fixedProjects != null) {
fixedProjectsList = new List();
fixedProjectsList.setEnabled(false);
listPane2.add(new JLabel("Fixed:"));
listPane2.add(fixedProjectsList);
}
listPane2.add(new JLabel("Changeable:"));
listPane2.add(changeableProjectsList);
listPane.add(listPane2);
smallPane = new JPanel();
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.Y_AXIS));
button = new JButton("Move up");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectedIndex = changeableProjectsList.getSelectedIndex();
if (selectedIndex <= 0) {
return;
}
File file = new File(changeableProjectsList.getItem(selectedIndex));
removeProjectDir(selectedIndex);
addProjectDir(file, selectedIndex - 1);
changeableProjectsList.select(selectedIndex - 1);
}
});
smallPane.add(button);
button = new JButton("Move down");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectedIndex = changeableProjectsList.getSelectedIndex();
if (selectedIndex < 0) {
return;
}
if (selectedIndex >= changeableProjectsList.getItemCount() - 1) {
return;
}
File file = new File(changeableProjectsList.getItem(selectedIndex));
removeProjectDir(selectedIndex);
addProjectDir(file, selectedIndex + 1);
changeableProjectsList.select(selectedIndex + 1);
}
});
smallPane.add(button);
smallPane.add(Box.createRigidArea(new Dimension(10, 10)));
button = new JButton("Remove");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (changeableProjectsList.getSelectedIndex() < 0) {
return;
}
removeProjectDir(changeableProjectsList.getSelectedIndex());
}
});
smallPane.add(button);
listPane.add(smallPane);
// ADD/REMOVE PART
JPanel addRemovePane = new JPanel();
addRemovePane.setLayout(new BoxLayout(addRemovePane, BoxLayout.X_AXIS));
addRemovePane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
button = new JButton("View resulting config");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ProjectConfig config;
try {
// Create default configuration
config = new ProjectConfig(true);
} catch (FileNotFoundException ex) {
logger.fatal("Could not find default project config file: "
+ GUI.PROJECT_DEFAULT_CONFIG_FILENAME);
return;
} catch (IOException ex) {
logger.fatal("Error when reading default project config file: "
+ GUI.PROJECT_DEFAULT_CONFIG_FILENAME);
return;
}
// Add the fixed project configurations
if (fixedProjectsList != null) {
for (String projectDir : fixedProjectsList.getItems()) {
try {
config.appendProjectDir(new File(projectDir));
} catch (Exception ex) {
logger.fatal("Error when merging configurations: " + ex);
return;
}
}
}
// Add the project directory configurations
for (String projectDir : changeableProjectsList.getItems()) {
try {
config.appendProjectDir(new File(projectDir));
} catch (Exception ex) {
logger.fatal("Error when merging configurations: " + ex);
return;
}
}
// Show merged configuration
ConfigViewer.showDialog(ProjectDirectoriesDialog.this, config);
}
});
addRemovePane.add(button);
addRemovePane.add(Box.createRigidArea(new Dimension(10, 0)));
button = new JButton("Add manually");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ProjectDirectoryInputDialog pathDialog = new ProjectDirectoryInputDialog(ProjectDirectoriesDialog.this);
pathDialog.pack();
pathDialog.setLocationRelativeTo(ProjectDirectoriesDialog.this);
pathDialog.setVisible(true);
File projectPath = pathDialog.getProjectDirectory();
if (projectPath != null) {
addProjectDir(projectPath);
}
}
});
addRemovePane.add(button);
addRemovePane.add(Box.createRigidArea(new Dimension(10, 0)));
button = new JButton("Browse");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new java.io.File(GUI.getExternalToolsSetting("PATH_CONTIKI")));
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.setDialogTitle("Select project directory");
if (fc.showOpenDialog(myDialog) == JFileChooser.APPROVE_OPTION) {
File dir = fc.getSelectedFile();
String selectedPath = null;
try {
selectedPath = dir.getCanonicalPath().replace('\\', '/');
String contikiPath =
new File(GUI.getExternalToolsSetting("PATH_CONTIKI", null)).
getCanonicalPath().replace('\\', '/');
if (contikiPath != null && selectedPath.startsWith(contikiPath)) {
selectedPath = selectedPath.replaceFirst(
contikiPath, GUI.getExternalToolsSetting("PATH_CONTIKI"));
}
addProjectDir(new File(selectedPath));
} catch (IOException ex) {
logger.fatal("Error in path extraction: " + ex);
}
}
}
});
addRemovePane.add(button);
// Add components
Container contentPane = getContentPane();
mainPane.add(listPane);
mainPane.add(addRemovePane);
contentPane.add(mainPane, BorderLayout.CENTER);
contentPane.add(buttonPane, BorderLayout.SOUTH);
// Add fixed project directories if any
if (fixedProjects != null) {
for (File projectDir : fixedProjects) {
fixedProjectsList.add(projectDir.getPath());
}
}
// Add already existing project directories
for (File projectDir : changeablePlatforms) {
addProjectDir(projectDir);
}
pack();
}
private void addProjectDir(File projectDir) {
addProjectDir(projectDir, changeableProjectsList.getItemCount());
}
private void addProjectDir(File projectDir, int index) {
// Check that file exists, is a directory and contains the correct files
if (!projectDir.exists()) {
logger.fatal("Can't find project directory: " + projectDir);
return;
}
if (!projectDir.isDirectory()) {
logger.fatal("Specified path is not a directory: " + projectDir);
return;
}
// File projectConfigFile = new File(projectDir.getPath(),
// GUI.PROJECT_CONFIG_FILENAME);
// if (!projectConfigFile.exists()) {
//
// Object[] options = {"Create",
// "Cancel"};
//
// int n = JOptionPane.showOptionDialog(
// this,
// "No " + GUI.PROJECT_CONFIG_FILENAME + " file exists in specified directory!"
// + "\nCreate an empty " + GUI.PROJECT_CONFIG_FILENAME + " file?",
// "Create project directory configuration?",
// JOptionPane.YES_NO_OPTION,
// JOptionPane.QUESTION_MESSAGE,
// null, options, options[1]);
//
// if (n == JOptionPane.NO_OPTION) {
// return;
// }
//
// try {
// projectConfigFile.createNewFile();
// } catch (IOException e) {
// logger.fatal("Could not create project directory configuration file: "
// + projectConfigFile);
// return;
// }
// }
changeableProjectsList.add(projectDir.getPath(), index);
}
private void removeProjectDir(int index) {
changeableProjectsList.remove(index);
}
}
/**
* Modal frame that shows all keys with their respective values of a given class
* configuration.
*
* @author Fredrik Osterlind
*/
class ConfigViewer extends JDialog {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(ConfigViewer.class);
public static void showDialog(Frame parentFrame, ProjectConfig config) {
ConfigViewer myDialog = new ConfigViewer(parentFrame, config);
myDialog.setLocationRelativeTo(parentFrame);
myDialog.setAlwaysOnTop(true);
Rectangle maxSize = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
if (maxSize != null &&
(myDialog.getSize().getWidth() > maxSize.getWidth()
|| myDialog.getSize().getHeight() > maxSize.getHeight())) {
Dimension newSize = new Dimension();
newSize.height = Math.min((int) maxSize.getHeight(), (int) myDialog.getSize().getHeight());
newSize.width = Math.min((int) maxSize.getWidth(), (int) myDialog.getSize().getWidth());
myDialog.setSize(newSize);
}
if (myDialog != null) {
myDialog.setVisible(true);
}
}
public static void showDialog(Dialog parentDialog, ProjectConfig config) {
ConfigViewer myDialog = new ConfigViewer(parentDialog, config);
myDialog.setLocationRelativeTo(parentDialog);
myDialog.setAlwaysOnTop(true);
if (myDialog != null) {
myDialog.setVisible(true);
}
}
private ConfigViewer(Dialog dialog, ProjectConfig config) {
super(dialog, "Current class configuration", true);
init(config);
}
private ConfigViewer(Frame frame, ProjectConfig config) {
super(frame, "Current class configuration", true);
init(config);
}
private void init(ProjectConfig config) {
JPanel mainPane = new JPanel(new BorderLayout());
JLabel label;
JButton button;
// BOTTOM BUTTON PART
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
button = new JButton("Close");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
}
});
buttonPane.add(button);
// LIST PART
JPanel keyPane = new JPanel();
keyPane.setLayout(new BoxLayout(keyPane, BoxLayout.Y_AXIS));
mainPane.add(keyPane, BorderLayout.WEST);
JPanel valuePane = new JPanel();
valuePane.setLayout(new BoxLayout(valuePane, BoxLayout.Y_AXIS));
mainPane.add(valuePane, BorderLayout.CENTER);
label = new JLabel("KEY");
label.setForeground(Color.RED);
keyPane.add(label);
label = new JLabel("VALUE");
label.setForeground(Color.RED);
valuePane.add(label);
Enumeration<String> allPropertyNames = config.getPropertyNames();
while (allPropertyNames.hasMoreElements()) {
String propertyName = allPropertyNames.nextElement();
keyPane.add(new JLabel(propertyName));
if (config.getStringValue(propertyName).equals("")) {
valuePane.add(new JLabel(" "));
} else {
valuePane.add(new JLabel(config.getStringValue(propertyName)));
}
}
// Add components
Container contentPane = getContentPane();
contentPane.add(new JScrollPane(mainPane), BorderLayout.CENTER);
contentPane.add(buttonPane, BorderLayout.SOUTH);
pack();
/* Respect screen size */
Rectangle maxSize = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
if (maxSize != null && (getSize().width > maxSize.width)) {
setSize(maxSize.width, getSize().height);
}
if (maxSize != null && (getSize().height > maxSize.height)) {
setSize(getSize().width, maxSize.height);
}
}
}