package com.jakeapp.gui.swing.models; import com.jakeapp.core.domain.FileObject; import com.jakeapp.core.domain.Tag; import com.jakeapp.gui.swing.JakeMainApp; import com.jakeapp.gui.swing.globals.JakeContext; import com.jakeapp.gui.swing.callbacks.FilesChangedCallback; import com.jakeapp.gui.swing.exceptions.InvalidTagStringFormatException; import com.jakeapp.gui.swing.helpers.FileObjectLockedCell; import com.jakeapp.gui.swing.helpers.FolderObject; import com.jakeapp.gui.swing.helpers.ProjectFilesTreeNode; import com.jakeapp.gui.swing.helpers.TagHelper; import com.jakeapp.jake.fss.IModificationListener; import org.apache.log4j.Logger; import org.jdesktop.swingx.treetable.TreeTableModel; import javax.swing.*; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.tree.TreePath; import java.util.ArrayList; import java.util.List; import java.util.Set; public class FolderTreeTableModel implements TreeTableModel, FilesChangedCallback { private static final Logger log = Logger.getLogger(FolderTreeTableModel.class); private ProjectFilesTreeNode root; private List<TreeModelListener> listeners = new ArrayList<TreeModelListener>(); public FolderTreeTableModel(ProjectFilesTreeNode root) { this.root = root; JakeMainApp.getCore().addFilesChangedListener(this, JakeContext.getProject()); } public void setRoot(ProjectFilesTreeNode node) { this.root = node; fireReload(); } public void fireReload() { for (TreeModelListener l : listeners) { // TODO: Modify only CHANGED nodes // Right now, we are reloading all nodes (crappy performance & flickering) TreeModelEvent e = new TreeModelEvent(this, new TreePath(root)); l.treeStructureChanged(e); } } @Override public Class<?> getColumnClass(int columnIndex) { switch (columnIndex) { case 0: return FileObjectLockedCell.class; case 1: return Icon.class; case 2: return ProjectFilesTreeNode.class; case 3: return String.class; case 4: return String.class; case 5: return String.class; default: return null; } } @Override public int getColumnCount() { return 6; } @Override public String getColumnName(int column) { switch (column) { case 0: return ""; case 1: return ""; case 2: return "Name"; case 3: return "Size"; case 4: return "Last Modified"; case 5: return "LastModBy"; default: return null; } } @Override public int getHierarchicalColumn() { // Third column is the hierarchical one (filename) return 2; } @Override public Object getValueAt(Object node, int column) { if (!(node instanceof ProjectFilesTreeNode)) throw new IllegalArgumentException("Not a ProjectFilesTreeNode but a " + node.getClass().toString()); ProjectFilesTreeNode ournode = (ProjectFilesTreeNode) node; if (ournode.isFile()) { switch (column) { case 0: return new FileObjectLockedCell(ournode.getFileObject()); case 1: // return new FileObjectStatusCell(ournode.getFileObject()); case 2: return ournode; case 3: // TODO: fix, change to attributed //return FileUtilities.getSize(JakeMainApp.getCore().getFileSize(ournode.getFileObject())); case 4: //return TimeUtilities.getRelativeTime(JakeMainApp.getApp().getCore().getFileLastModified(ournode.getFileObject())); case 5: return TagHelper.tagsToString(JakeMainApp.getCore().getTagsForFileObject(ournode.getFileObject())); default: return "INVALIDCOLUMN"; } } else { switch (column) { case 0: return null; case 1: return null; case 2: return ournode; case 3: return ""; case 4: return ""; case 5: return ""; default: return "INVALIDCOLUMN"; } } } @Override public boolean isCellEditable(Object node, int column) { // LastModBy are editable, but only for files ProjectFilesTreeNode ournode = (ProjectFilesTreeNode) node; return column == 5 && ournode.isFile(); } @Override public void setValueAt(Object value, Object node, int column) { ProjectFilesTreeNode ournode = (ProjectFilesTreeNode) node; if (column == 5 && ournode.isFile()) { // Change tags FileObject fileobj = ournode.getFileObject(); try { Set<Tag> tags = TagHelper.stringToTags(fileobj, (String) value); JakeMainApp.getCore().setTagsForFileObject(fileobj, tags); } catch (InvalidTagStringFormatException e) { log.warn("Invalid tag string ('" + value + "')"); } } } @Override public ProjectFilesTreeNode getRoot() { return root; } @Override public ProjectFilesTreeNode getChild(Object parent, int index) { if (!(parent instanceof ProjectFilesTreeNode)) throw new IllegalArgumentException("Not a ProjectFilesTreeNode"); ProjectFilesTreeNode ournode = (ProjectFilesTreeNode) parent; // Files have no children if (ournode.isFile()) return null; FolderObject fo = ournode.getFolderObject(); return new ProjectFilesTreeNode(fo.getAllChildren().get(index)); } @Override public int getChildCount(Object parent) { if (!(parent instanceof ProjectFilesTreeNode)) throw new IllegalArgumentException("Not a ProjectFilesTreeNode"); ProjectFilesTreeNode ournode = (ProjectFilesTreeNode) parent; // Files have no children if (ournode.isFile()) return 0; FolderObject fo = ournode.getFolderObject(); if (fo != null) { return fo.getAllChildren().size(); } else { log.warn("ournode.getFolderObject() returned NULL with ournode: " + ournode); return 0; } } @Override public boolean isLeaf(Object node) { // ALL leaves must be files and all files must be leaves if (!(node instanceof ProjectFilesTreeNode)) throw new IllegalArgumentException("Not a ProjectFilesTreeNode"); ProjectFilesTreeNode ournode = (ProjectFilesTreeNode) node; return ournode.isFile(); } @Override public void valueForPathChanged(TreePath path, Object newValue) { // TODO: WTF is this good for? } @Override public int getIndexOfChild(Object parent, Object child) { // TODO: WTF is this good for? return 0; } @Override public void addTreeModelListener(TreeModelListener l) { log.debug("TreeModelListener added"); listeners.add(l); } @Override public void removeTreeModelListener(TreeModelListener l) { listeners.remove(l); } @Override public void filesChanged(String relpath, IModificationListener.ModifyActions action) { // try { // log.debug("Hooray, our files changed!"); // //ProjectFilesTreeNode node = new ProjectFilesTreeNode(JakeMainApp.getCore().getFolder( // // JakeMainApp.getProject(), // // null)); // //this.setRoot(node); // } catch (ProjectFolderMissingException e) { // log.error("Couldn't find project root folder"); // } } }