package org.isatools.isacreator.gs.gui;
import org.genomespace.datamanager.core.GSFileMetadata;
import com.explodingpixels.macwidgets.IAppWidgetFactory;
import org.apache.log4j.Logger;
import org.isatools.isacreator.common.UIHelper;
import org.isatools.isacreator.effects.FooterPanel;
import org.isatools.isacreator.effects.HUDTitleBar;
import org.isatools.isacreator.gs.GSDataManager;
import org.isatools.isacreator.gs.GSIdentityManager;
import org.isatools.isacreator.gui.menu.ISAcreatorMenu;
import org.isatools.isacreator.gui.menu.ImportFilesMenu;
import org.isatools.isacreator.managers.ApplicationManager;
import org.isatools.errorreporter.model.ErrorMessage;
import org.jdesktop.fuse.InjectedResource;
import org.jdesktop.fuse.ResourceInjector;
import uk.ac.ebi.utils.collections.Pair;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.List;
/**
* Created by the ISATeam.
* User: agbeltran
* Date: 04/11/2012
* Time: 21:13
*
* @author <a href="mailto:alejandra.gonzalez.beltran@gmail.com">Alejandra Gonzalez-Beltran</a>
*/
public class GSFileChooser extends JComponent implements TreeSelectionListener {
protected static ImageIcon loadISAanimation = new ImageIcon(ImportFilesMenu.class.getResource("/images/gui/isa_load.gif"));
private static Logger log = Logger.getLogger(GSFileChooser.class);
//the file chooser works in two modes: open and save
public enum GSFileChooserMode {
OPEN, SAVE
}
@InjectedResource
private ImageIcon listImage, closeButton, closeButtonOver, selectDir, selectDirOver,
saveSubmission, saveSubmissionOver, newFolderButton, newFolderButtonOver, okButtonIcon, okButtonIconOver,
cancelButtonIcon, cancelButtonIconOver;
@InjectedResource
private Image loadHeader, saveAsHeader;
private GSFileChooserMode mode;
private JLabel status;
private Container loadingImagePanel;
private GSFileMetadata selectedFileMetadata;
private GSFileMetadataTreeNode currentNode;
private JLabel selectDirLabel = null;
private GSTree tree = null;
protected ISAcreatorMenu menu = null;
private GSDataManager gsDataManager = null;
private NewFolderWindow newFolderWindow;
public static final int SELECTED = 0;
public static final int NOT_SELECTED = 1;
public GSFileChooser(ISAcreatorMenu me, GSFileChooserMode mo) {
menu = me;
mode = mo;
ResourceInjector.get("gui-package.style").inject(this);
GSIdentityManager gsIdentityManager = GSIdentityManager.getInstance();
gsDataManager = gsIdentityManager.getGsDataManager();
newFolderWindow = new NewFolderWindow();
}
public int showOpenDialog() {
JFrame frame = createDialog();
frame.pack();
frame.setLocationRelativeTo(ApplicationManager.getCurrentApplicationInstance());
frame.setVisible(true);
frame.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
return NOT_SELECTED;
}
public JFrame createDialog() {
JFrame containerFrame = new JFrame();
containerFrame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent windowEvent) {
if(newFolderWindow.isShowing()) {
newFolderWindow.dispose();
}
}
});
containerFrame.setAlwaysOnTop(true);
containerFrame.setUndecorated(true);
containerFrame.setBackground(UIHelper.BG_COLOR);
instantiatePanel(containerFrame);
return containerFrame;
}
public void instantiatePanel(final JFrame fileSelectionFrame) {
log.info("Instantiating panel... mode=" + mode);
status = new JLabel();
status.setSize(new Dimension(450,40));
UIHelper.renderComponent(status,UIHelper.VER_10_PLAIN,UIHelper.RED_COLOR, false);
Image headerIcon = mode == GSFileChooserMode.OPEN ? loadHeader : saveAsHeader;
HUDTitleBar hud = new HUDTitleBar(headerIcon, headerIcon);
fileSelectionFrame.add(hud, BorderLayout.NORTH);
hud.installListeners();
JPanel centerPanel = new JPanel(new BorderLayout());
JComponent treePanel = getTreePanel();
treePanel.setBorder(new EmptyBorder(10, 2, 7, 2));
centerPanel.add(treePanel, BorderLayout.CENTER);
fileSelectionFrame.add(centerPanel, BorderLayout.CENTER);
// setup center panel with buttons
JPanel southPanel = new JPanel(new BorderLayout());
southPanel.setBackground(UIHelper.BG_COLOR);
final JLabel cancelLabel = new JLabel(closeButton,
JLabel.LEFT);
cancelLabel.setOpaque(false);
cancelLabel.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent event) {
fileSelectionFrame.dispose();
}
public void mouseEntered(MouseEvent event) {
cancelLabel.setIcon(closeButtonOver);
}
public void mouseExited(MouseEvent event) {
cancelLabel.setIcon(closeButton);
}
});
final JLabel newFolder = new JLabel(newFolderButton,
JLabel.CENTER);
if (mode == GSFileChooserMode.SAVE) {
newFolder.setOpaque(false);
newFolder.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent event) {
newFolderWindow = new NewFolderWindow();
if (!newFolderWindow.isShowing()) {
Point displayLocation = newFolder.getLocationOnScreen();
displayLocation.y -= 35;
newFolderWindow.createGUI(displayLocation);
}
newFolderWindow.addPropertyChangeListener("fileNameSelected", new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
if (selectedFileMetadata == null) {
status.setText("Please, select the parent directory");
} else {
String newFolderName = propertyChangeEvent.getNewValue().toString();
if (newFolderName.equals("New folder name")) {
status.setText("Please, enter a valid directory name");
return;
} else if (newFolderName.indexOf('/') != -1) {
status.setText("Folder names must not contain slashes. No folder was created.");
return;
}
newFolderWindow.setVisible(false);
newFolderWindow.dispose();
Pair<GSFileMetadata, ErrorMessage> newDirResult = gsDataManager.mkDir(newFolderName, selectedFileMetadata);
if (newDirResult.snd == null && newDirResult.fst!=null){
GSFileMetadata newDirMetadata = newDirResult.fst;
status.setText("Folder " + newFolderName + " created.");
status.setForeground(UIHelper.GREY_COLOR);
final TreePath path = tree.getSelectionPath();
List<String> acceptableExtensions = new ArrayList<String>();
acceptableExtensions.add("txt");
if (tree.isExpanded(path) || currentNode.childrenHaveBeenInitialised()) {
final GSFileMetadataTreeNode newDirNode =
new GSFileMetadataTreeNode(newDirMetadata, gsDataManager.getDataManagerClient(),
acceptableExtensions);
final DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();
final GSFileMetadataTreeNode parent =
path == null ? (GSFileMetadataTreeNode) treeModel.getRoot()
: (GSFileMetadataTreeNode) path.getLastPathComponent();
final int insertionPoint = getTreeIndex(parent, treeModel, newDirNode, false);
if (insertionPoint == -1) {
status.setText("Duplicate folder name");
status.setForeground(UIHelper.RED_COLOR);
log.error("GenomeSpace error: duplicate folder name");
return;
}
treeModel.insertNodeInto(newDirNode, parent, insertionPoint);
// Make sure the user can see the new directory node:
tree.scrollPathToVisible(new TreePath(newDirNode.getPath()));
}
if (tree.isCollapsed(path)) tree.expandPath(path);
}else{
status.setText("<html>Folder " + newFolderName + " not created. "+newDirResult.snd.getMessage()+"</html>");
}
}
}
});
}
public void mouseEntered(MouseEvent event) {
newFolder.setIcon(newFolderButtonOver);
}
public void mouseExited(MouseEvent event) {
newFolder.setIcon(newFolderButton);
}
});
}
if (mode == GSFileChooserMode.OPEN) {
selectDirLabel = new JLabel(selectDir,
JLabel.RIGHT);
} else {
selectDirLabel = new JLabel(saveSubmission,
JLabel.RIGHT);
}
selectDirLabel.setOpaque(false);
selectDirLabel.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent event) {
if (selectedFileMetadata != null) {
fileSelectionFrame.setVisible(false);
firePropertyChange("selectedFileMetadata", "", selectedFileMetadata);
fileSelectionFrame.dispose();
}
}
public void mouseEntered(MouseEvent event) {
if (mode == GSFileChooserMode.SAVE) {
selectDirLabel.setIcon(saveSubmissionOver);
} else {
selectDirLabel.setIcon(selectDirOver);
}
}
public void mouseExited(MouseEvent event) {
if (mode == GSFileChooserMode.SAVE) {
selectDirLabel.setIcon(saveSubmission);
} else {
selectDirLabel.setIcon(selectDir);
}
}
});
southPanel.add(cancelLabel, BorderLayout.WEST);
if (mode == GSFileChooserMode.SAVE) {
southPanel.add(newFolder, BorderLayout.CENTER);
}
southPanel.add(selectDirLabel, BorderLayout.EAST);
southPanel.add(status, BorderLayout.NORTH);
centerPanel.add(southPanel, BorderLayout.SOUTH);
FooterPanel footer = new FooterPanel(fileSelectionFrame);
fileSelectionFrame.add(footer, BorderLayout.SOUTH);
}
private JComponent getTreePanel() {
//set up central panel with files - treePanel
tree = new GSTree(gsDataManager.getDataManagerClient(), new ArrayList<String>());
this.currentNode = (GSFileMetadataTreeNode) tree.getModel().getRoot();
tree.setEditable(true);
tree.addTreeSelectionListener(this);
JScrollPane treeScrollPane = new JScrollPane(tree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
treeScrollPane.setBorder(new EmptyBorder(2, 2, 2, 2));
treeScrollPane.setPreferredSize(new Dimension(450, 300));
IAppWidgetFactory.makeIAppScrollPane(treeScrollPane);
return treeScrollPane;
}
public GSFileMetadata getSelectedFileMetadata() {
return selectedFileMetadata;
}
private Container createLoadingImagePanel() {
if (loadingImagePanel == null) {
loadingImagePanel = UIHelper.wrapComponentInPanel(new JLabel(loadISAanimation));
}
return loadingImagePanel;
}
public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
status.setText("");
currentNode = (GSFileMetadataTreeNode) tree.getLastSelectedPathComponent();
if (currentNode == null) {
selectedFileMetadata = null;
selectDirLabel.setEnabled(false);
} else {
final boolean isFolder = currentNode.getFileMetadata().isDirectory();
if (!isFolder) {
status.setText("Please, select a folder with an ISA-tab dataset");
selectDirLabel.setEnabled(false);
} else {
selectedFileMetadata = currentNode.getFileMetadata();
selectDirLabel.setEnabled(true);
}
}
}
private int getTreeIndex(final GSFileMetadataTreeNode parent,
final DefaultTreeModel treeModel,
final GSFileMetadataTreeNode newDirNode,
final boolean allowDups) {
final String newFolderName = newDirNode.toString();
int insertIndex = 0;
final Enumeration iter = parent.children();
final Set<String> alreadySeen = new HashSet<String>();
while (iter.hasMoreElements()) {
final GSFileMetadataTreeNode childNode = (GSFileMetadataTreeNode) iter.nextElement();
final GSFileMetadata childMetadata = childNode.getFileMetadata();
if (!childMetadata.isDirectory())
continue;
final String folderName = childMetadata.getName();
if (alreadySeen.contains(folderName))
continue;
alreadySeen.add(folderName);
final int comp = folderName.compareToIgnoreCase(newFolderName);
if (comp == 0 && !allowDups)
return -1; // We don't allow duplicate names!
if (comp < 0)
++insertIndex;
}
return insertIndex;
}
class NewFolderWindow extends JFrame {
public void createGUI(Point position) {
setUndecorated(true);
setAlwaysOnTop(true);
setPreferredSize(new Dimension(250, 30));
setLayout(new BorderLayout());
setBorder(new LineBorder(UIHelper.LIGHT_GREEN_COLOR, 2));
Box container = Box.createHorizontalBox();
container.setBorder(new EmptyBorder(4, 4, 4, 4));
setLocation(position);
final JTextField fileNameTxt = new JTextField("New folder name...", 30);
UIHelper.renderComponent(fileNameTxt, UIHelper.VER_11_BOLD, UIHelper.GREY_COLOR, false);
fileNameTxt.setBorder(new MatteBorder(0, 0, 2, 0, UIHelper.LIGHT_GREEN_COLOR));
fileNameTxt.setBackground(UIHelper.BG_COLOR);
UIHelper.renderComponent(fileNameTxt, UIHelper.VER_12_PLAIN, UIHelper.DARK_GREEN_COLOR, false);
container.add(fileNameTxt);
createButtonPanel(container, fileNameTxt);
add(container, BorderLayout.NORTH);
pack();
setVisible(true);
}
private void createButtonPanel(Box container, final JTextField fileNameTxt) {
final JLabel okButton = new JLabel(okButtonIcon);
okButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent mouseEvent) {
okButton.setIcon(okButtonIconOver);
}
@Override
public void mouseExited(MouseEvent mouseEvent) {
okButton.setIcon(okButtonIcon);
}
@Override
public void mousePressed(MouseEvent mouseEvent) {
okButton.setIcon(okButtonIcon);
firePropertyChange("fileNameSelected", "", fileNameTxt.getText());
}
});
final JLabel cancelButton = new JLabel(cancelButtonIcon);
cancelButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent mouseEvent) {
cancelButton.setIcon(cancelButtonIconOver);
}
@Override
public void mouseExited(MouseEvent mouseEvent) {
cancelButton.setIcon(cancelButtonIcon);
}
@Override
public void mousePressed(MouseEvent mouseEvent) {
cancelButton.setIcon(cancelButtonIcon);
setVisible(false);
NewFolderWindow.this.dispose();
}
});
container.add(okButton);
container.add(cancelButton);
}
}
}