package org.freeplane.plugin.workspace.components.dialog;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.NoSuchElementException;
import javax.swing.ComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.border.MatteBorder;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import org.freeplane.core.util.LogUtils;
import org.freeplane.core.util.TextUtils;
import org.freeplane.plugin.workspace.URIUtils;
import org.freeplane.plugin.workspace.WorkspaceController;
import org.freeplane.plugin.workspace.model.AWorkspaceTreeNode;
import org.freeplane.plugin.workspace.model.IResultProcessor;
import org.freeplane.plugin.workspace.model.project.AWorkspaceProject;
import org.freeplane.plugin.workspace.model.project.ProjectLoader;
import org.freeplane.plugin.workspace.nodes.ProjectRootNode;
import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
public class ImportProjectDialogPanel extends JPanel {
private static final SimpleDateFormat format = new SimpleDateFormat("M/d/yy HH:mm");
private static final long serialVersionUID = 1L;
private JTextField txtProjectName;
private JTextField txtProjectPath;
private JComboBox projectVersions;
private ProjectVersionsModel versionModel;
private JLabel lblWarn;
private JLabel lblProjectName;
private Component confirmButton;
/***********************************************************************************
* CONSTRUCTORS
**********************************************************************************/
public ImportProjectDialogPanel() {
setPreferredSize(new Dimension(400, 180));
setLayout(new FormLayout(new ColumnSpec[] {
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.DEFAULT_COLSPEC,
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("max(100dlu;min):grow"),
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.DEFAULT_COLSPEC,
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.RELATED_GAP_COLSPEC,},
new RowSpec[] {
FormFactory.RELATED_GAP_ROWSPEC,
RowSpec.decode("fill:max(50dlu;pref)"),
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
RowSpec.decode("fill:default"),
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,}));
JPanel panel = new JPanel();
panel.setBorder(new MatteBorder(0, 0, 1, 0, (Color) new Color(0, 0, 0)));
panel.setBackground(Color.WHITE);
add(panel, "1, 1, 8, 2, fill, fill");
panel.setLayout(new FormLayout(new ColumnSpec[] {
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("default:grow"),},
new RowSpec[] {
FormFactory.RELATED_GAP_ROWSPEC,
RowSpec.decode("fill:default:grow"),}));
JLabel lblNewLabel = new JLabel(TextUtils.getText(ImportProjectDialogPanel.class.getSimpleName().toLowerCase(Locale.ENGLISH)+".help"));
lblNewLabel.setVerticalAlignment(SwingConstants.TOP);
panel.add(lblNewLabel, "2, 2");
lblWarn = new JLabel(TextUtils.getText(ImportProjectDialogPanel.class.getSimpleName().toLowerCase(Locale.ENGLISH)+".warn1"));
add(lblWarn, "2, 4, 5, 1");
URL url = this.getClass().getResource("/images/16x16/dialog-warning-4.png");
if(url != null) {
lblWarn.setIcon(new ImageIcon(url));
}
lblWarn.setVisible(false);
JLabel lblProjectPath = new JLabel(TextUtils.getText(ImportProjectDialogPanel.class.getSimpleName().toLowerCase(Locale.ENGLISH)+".path.label"));
lblProjectPath.setHorizontalAlignment(SwingConstants.RIGHT);
add(lblProjectPath, "2, 6, right, default");
txtProjectPath = new JTextField();
add(txtProjectPath, "4, 6, fill, default");
txtProjectPath.setColumns(10);
txtProjectPath.setEditable(false);
JButton btnBrowse = new JButton("...");
btnBrowse.setToolTipText(TextUtils.getText(ImportProjectDialogPanel.class.getSimpleName().toLowerCase(Locale.ENGLISH)+".button.tip"));
btnBrowse.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
File home = URIUtils.getAbsoluteFile(getProjectPath());
while(home != null && !home.exists()) {
home = home.getParentFile();
}
JFileChooser chooser = new JFileChooser(home == null ? getDefaultProjectPath() : home.getAbsolutePath());
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setMultiSelectionEnabled(false);
chooser.setFileHidingEnabled(true);
int response = chooser.showOpenDialog(ImportProjectDialogPanel.this);
if(response == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
setProjectPath(file.getAbsolutePath());
}
}
});
add(btnBrowse, "6, 6");
lblProjectName = new JLabel(TextUtils.getText(ImportProjectDialogPanel.class.getSimpleName().toLowerCase(Locale.ENGLISH)+".name.label"));
lblProjectName.setEnabled(false);
add(lblProjectName, "2, 8, right, default");
projectVersions = new JComboBox();
projectVersions.setModel(getComboBoxModel());
projectVersions.setEnabled(false);
add(projectVersions, "4, 8, 3, 1, fill, default");
projectVersions.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
enableConfirmation();
}
});
}
/***********************************************************************************
* METHODS
**********************************************************************************/
private void setProjectPath(String path) {
txtProjectPath.setText(path);
updateProjectVersions();
}
@Override
public void paint(Graphics g) {
enableConfirmation();
super.paint(g);
}
protected void updateProjectVersions() {
File home = new File(txtProjectPath.getText());
getComboBoxModel().clear();
File _data = new File(home, "_data");
if(_data.exists()) {
readVersions(_data);
}
enableControlls(getComboBoxModel().getSize() > 0);
}
protected void enableControlls(boolean enabled) {
if(getComboBoxModel().getSize() > 0) {
projectVersions.setSelectedIndex(0);
}
lblWarn.setText(TextUtils.getText(ImportProjectDialogPanel.class.getSimpleName().toLowerCase(Locale.ENGLISH)+".warn1"));
lblWarn.setVisible(!enabled);
projectVersions.setEnabled(enabled);
lblProjectName.setEnabled(enabled);
enableConfirmation();
}
private void enableConfirmation() {
if(confirmButton != null) {
if(getComboBoxModel().getSelectedItem() == null) {
confirmButton.setEnabled(false);
if(projectVersions.isEnabled()) {
lblWarn.setText(TextUtils.getText(ImportProjectDialogPanel.class.getSimpleName().toLowerCase(Locale.ENGLISH)+".warn2"));
lblWarn.setVisible(true);
}
}
else {
if(WorkspaceController.getCurrentModel().getProject(getComboBoxModel().getSelectedItem().getProject().getProjectID()) != null) {
lblWarn.setText(TextUtils.getText(ImportProjectDialogPanel.class.getSimpleName().toLowerCase(Locale.ENGLISH)+".warn3"));
lblWarn.setVisible(true);
confirmButton.setEnabled(false);
}
else {
confirmButton.setEnabled(true);
lblWarn.setVisible(false);
}
}
}
}
private void readVersions(File home) {
for(File folder : home.listFiles(new FileFilter() {
public boolean accept(File pathname) {
if(pathname.isDirectory()) {
return true;
}
return false;
}
})) {
File settings = new File(folder, "settings.xml");
if(settings.exists()) {
AWorkspaceProject project /*= WorkspaceController.getProjectFromCache(folder.getName());
if(project == null) {
project*/ = AWorkspaceProject.create(folder.getName(), home.getParentFile().toURI());
//}
String item = new TempProjectLoader().getMetaInfo(project);
if(item == null) {
continue;
}
getComboBoxModel().addItem(new VersionItem(project, item, new Date(settings.lastModified())));
}
}
}
protected ProjectVersionsModel getComboBoxModel() {
if(this.versionModel == null) {
this.versionModel = new ProjectVersionsModel();
}
return this.versionModel;
}
protected String getDefaultProjectPath() {
File base = URIUtils.getAbsoluteFile(WorkspaceController.getDefaultProjectHome());
return base.getAbsolutePath();
}
public String getProjectName() {
return txtProjectName.getText().trim();
}
public AWorkspaceProject getProject() {
VersionItem item = (VersionItem) projectVersions.getSelectedItem();
if(item == null) {
return null;
}
return item.getProject();
}
protected URI getProjectPath() {
if(txtProjectPath.getText().length()==0) {
return null;
}
return new File(txtProjectPath.getText()).toURI();
}
public void setConfirmButton(Component comp) {
this.confirmButton = comp;
}
/***********************************************************************************
* INTERNAL TYPES
**********************************************************************************/
class TempProjectLoader extends ProjectLoader {
StringBuilder versionString;
public String getMetaInfo(AWorkspaceProject project) {
try {
versionString = new StringBuilder();
LOAD_RETURN_TYPE retType = this.loadProject(project);
if(LOAD_RETURN_TYPE.EXISTING_PROJECT.equals(retType)) {
return versionString.length() == 0 ? null : versionString.toString();
}
} catch (IOException e) {
LogUtils.warn(e);
}
return null;
}
@Override
public IResultProcessor getDefaultResultProcessor() {
return new IResultProcessor() {
public void process(AWorkspaceTreeNode parent, AWorkspaceTreeNode node) {
if(node == null) {
return;
}
if(node instanceof ProjectRootNode) {
versionString.append(node.getName());
}
if(parent == null) {
return;
}
parent.addChildNode(node);
}
public void setProject(AWorkspaceProject project) {
}
};
}
}
protected class ProjectVersionsModel implements ComboBoxModel {
private List<VersionItem> items = new ArrayList<VersionItem>();
private List<ListDataListener> listeners = new ArrayList<ListDataListener>();
private int selectedIndex = -1;
/***********************************************************************************
* CONSTRUCTORS
**********************************************************************************/
/***********************************************************************************
* METHODS
**********************************************************************************/
/***********************************************************************************
* REQUIRED METHODS FOR INTERFACES
**********************************************************************************/
public int getSize() {
return items.size();
}
public Object getElementAt(int index) {
return items.get(index);
}
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
public void setSelectedItem(Object anItem) {
int idx = items.indexOf(anItem);
if(idx == -1) {
throw new NoSuchElementException();
}
this.selectedIndex = idx;
}
public VersionItem getSelectedItem() {
if(this.selectedIndex == -1) {
return null;
}
return items.get(selectedIndex);
}
public void clear() {
int endIdx = items.size();
this.items.clear();
fireItemsRemoved(0, endIdx);
}
private void validateSelection() {
if(selectedIndex >= items.size()) {
selectedIndex = items.size()-1;
}
}
public void setSelectedIndex(int index) {
if(index < 0 || index >= items.size()) {
throw new IndexOutOfBoundsException();
}
this.selectedIndex = index;
}
public void addItem(VersionItem item) {
for(VersionItem it : items) {
if(it.compareTo(item) < 0) {
insertItem(item, items.indexOf(it));
return;
}
}
insertItem(item, items.size());
}
private void insertItem(VersionItem item, int index) {
if(item == null) {
return;
}
if(index < 0 || index > items.size()) {
throw new IndexOutOfBoundsException();
}
items.add(index, item);
fireItemsAdded(index, index);
}
public void removeItem(VersionItem anItem) {
if(anItem == null) {
return;
}
int idx = items.indexOf(anItem);
if(idx == -1) {
return;
}
removeItem(idx);
}
public VersionItem removeItem(int index) {
if(index < 0 || index >= items.size()) {
throw new IndexOutOfBoundsException();
}
VersionItem obj = items.remove(index);
fireItemsRemoved(index, index);
return obj;
}
protected void fireItemsAdded(int startIndex, int endIndex) {
ListDataEvent event = new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, startIndex, endIndex);
for (int i = items.size()-1; i >= 0; i--) {
listeners.get(i).intervalAdded(event);
}
}
protected void fireItemsRemoved(int startIndex, int endIndex) {
validateSelection();
ListDataEvent event = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, startIndex, endIndex);
for (int i = items.size()-1; i >= 0; i--) {
listeners.get(i).intervalRemoved(event);
}
}
protected void fireItemsChanged(int startIndex, int endIndex) {
ListDataEvent event = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, startIndex, endIndex);
for (int i = items.size()-1; i >= 0; i--) {
listeners.get(i).contentsChanged(event);
}
}
}
public class VersionItem implements Comparable<VersionItem> {
private final AWorkspaceProject project;
private final Date latestUse;
private final String name;
/***********************************************************************************
* CONSTRUCTORS
**********************************************************************************/
public VersionItem(AWorkspaceProject prj, String name, Date version) {
if(prj == null || name == null || version == null) {
throw new IllegalArgumentException("NULLPointer");
}
this.project = prj;
this.latestUse = version;
this.name = name;
}
/***********************************************************************************
* METHODS
**********************************************************************************/
public AWorkspaceProject getProject() {
return project;
}
public String toString() {
return this.name + " [" +format.format(latestUse) + "]";
}
/***********************************************************************************
* REQUIRED METHODS FOR INTERFACES
**********************************************************************************/
public int compareTo(VersionItem o) {
return (int) (latestUse.getTime()-o.latestUse.getTime());
}
}
}