/* * Copyright 2011 Uwe Krueger. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mandelsoft.mand.tool; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.beans.PropertyChangeListener; import javax.swing.DropMode; import javax.swing.TransferHandler; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.tree.TreePath; import com.mandelsoft.mand.QualifiedMandelName; import com.mandelsoft.mand.scan.MandelScanner; import com.mandelsoft.mand.util.MandelListFolder; import com.mandelsoft.swing.DnDListModel.DragLocation; import com.mandelsoft.swing.DnDListModel.TransferSupport; /** * * @author Uwe Krueger */ public class MandelListFolderListModel extends AbstractMandelListModel<MandelListFolder> { private TreeListEventAdapter adapter; private MandelListFolderBrowserModel model; private MandelScanner scanner; public MandelListFolderListModel(MandelListFolderTreeModel model, MandelScanner scanner ) { adapter=new TreeListEventAdapter(); this.scanner=scanner; this.model=new MandelListFolderBrowserModel(model); this.model.addTreeModelListener(adapter); } @Override public void refresh(boolean soft) { getFolderTreeModel().getFolderTree().refresh(); } public MandelListFolderTreeModel getFolderTreeModel() { return model.getFolderTreeModel(); } public void setModel(MandelListFolderTreeModel model) { this.model.setFolderTreeModel(model); } public void setActiveFolder(MandelListFolder f) { model.setActiveFolder(f); } public void addPropertyChangeListener(PropertyChangeListener l) { model.addPropertyChangeListener(l); } public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { model.addPropertyChangeListener(propertyName, listener); } public void removePropertyChangeListener(PropertyChangeListener l) { model.removePropertyChangeListener(l); } public void removeTreeModelListener(TreeModelListener l) { model.removeTreeModelListener(l); } public void addTreeModelListener(TreeModelListener l) { model.addTreeModelListener(l); } public String getActivePathName() { return model.getActivePathName(); } public TreePath getActivePath() { return model.getActivePath(); } public MandelListFolder getActiveFolder() { return model.getActiveFolder(); } public static TreePath getParentPath(TreeModelEvent e, TreePath path) { return MandelListFolderBrowserModel.getParentPath(e, path); } @Override public boolean isModifiable() { return model.isPathModifiable(getActivePath()); } public void removeFolder(MandelListFolder node) { model.removeFolder(node); } public MandelListFolder insertFolder(String name, MandelListFolder parent) { return model.insertFolder(name, parent); } ///////////////////////////////////////////////////////////////////////// @Override protected MandelScanner getMandelScanner() { return scanner; } @Override protected QualifiedMandelName getQualifiedName(MandelListFolder elem) { return elem.getThumbnailName(); } @Override protected boolean usesThumbnail(QualifiedMandelName name) { return lookupElement(name)!=null; } @Override protected MandelListFolder lookupElement(QualifiedMandelName name) { for (MandelListFolder f:model.getActiveFolder().allfolders()) { QualifiedMandelName n=f.getThumbnailName(); if (n!=null && n.equals(name)) return f; } return null; } ///////////////////////////////////////////////////////////////////////// public Object getElementAt(int index) { return model.getActiveFolder().get(index); } public int getSize() { return model.getActiveFolder().size(); } //////////////////////////////////////////////////////////////// // drag'n drop support //////////////////////////////////////////////////////////////// private static boolean debug=false; public DropMode getDropMode() { return DropMode.ON_OR_INSERT; } /** * We support both copy and move actions. */ public int getSourceActions() { return TransferHandler.COPY_OR_MOVE; } public boolean canImport(TransferSupport info) { MandelFolderTransferable t; TreePath subpath; DropLocation dl=info.getDropLocation(); boolean insert=dl.isInsert(); int index =dl.getIndex(); //System.out.println("index = "+index); MandelListFolder folder=index<getSize()?(MandelListFolder)getElementAt(index) :null; if (insert) { if (!isModifiable()) return false; } else { subpath=getActivePath().pathByAddingChild(folder); if (!model.isPathModifiable(subpath)) return false; } // both drop on and in between if (info.isDataFlavorSupported(MandelFolderTransferable.folderFlavor)) { //System.out.println("support folder"); if (!insert && folder.isLeaf()) return false; try { t=(MandelFolderTransferable)info.getTransferable(). getTransferData(MandelFolderTransferable.folderFlavor); } catch (Exception e) { return false; } while (folder!=null) { for (MandelListFolder f :t.getFolders()) { if (f==folder) return false; } folder=folder.getParent(); } return true; } // drop on only if (!insert) { if (folder.getMandelList()==null) return false; if (info.isDataFlavorSupported(MandelTransferable.mandelFlavor)) { return true; } if (info.isDataFlavorSupported(DataFlavor.stringFlavor)) { try { String data=(String)info.getTransferable().getTransferData( DataFlavor.stringFlavor); if (QualifiedMandelName.create(data)!=null) return true; } catch (Exception ex) { } } } return false; } /** * Bundle up the selected items in a single list for export. * Each line is separated by a newline. */ public Transferable createTransferable(DragLocation loc) { int[] indices=loc.getSelectedRows(); TreePath[] paths=new TreePath[indices.length]; for (int i=0; i<indices.length; i++) { paths[i]=getActivePath().pathByAddingChild(getElementAt(indices[i])); } int cnt=0; for (int i=0; i<paths.length; i++) { if (model.isPathTransferable(paths[i])) cnt++; } if (cnt==0) return null; MandelListFolder[] folders=new MandelListFolder[cnt]; cnt=0; for (int i=0; i<paths.length; i++) { if (model.isPathTransferable(paths[i])) { folders[cnt++]=(MandelListFolder)paths[i].getLastPathComponent(); } } return new MandelFolderTransferable(model.getFolderTree(), folders); } /** * Perform the actual import. This demo only supports drag and drop. */ public boolean importData(TransferSupport info) { DropLocation dl=info.getDropLocation(); boolean insert=dl.isInsert(); int index =dl.getIndex(); MandelListFolder folder; if (insert) { folder=getActiveFolder(); } else { folder=(MandelListFolder)getElementAt(index); index=-1; } boolean done=true; Transferable t=info.getTransferable(); QualifiedMandelName[] data; MandelListFolder[] dropfolders; if (info.getDropAction()==TransferHandler.LINK) { info.setDropAction(TransferHandler.COPY); } // Perform the actual import. try { MandelFolderTransferable trans=(MandelFolderTransferable)t.getTransferData( MandelFolderTransferable.folderFlavor); dropfolders=trans.getFolders(); if (debug) System.out.println("import folder"); if (trans.getSource()!=model.getFolderTree()|| info.getDropAction()!=TransferHandler.MOVE) { // handle foreign folders model.insertFolders(index, dropfolders, folder); } else { // handle own folders model.moveFolders(index, dropfolders, folder); done=false; } } catch (Exception e) { check(e); try { MandelTransferable trans; trans=(MandelTransferable)t.getTransferData( MandelTransferable.mandelFlavor); if (trans.getSource()==folder.getMandelList()) { if (debug) System.out.println("self drop"); return false; } data=trans.getNames(); if (debug) System.out.println("import mandel"); model.addAll(folder, data); } catch (Exception ey) { check(ey); try { String name=(String)t.getTransferData(DataFlavor.stringFlavor); if (debug) System.out.println("import string"); QualifiedMandelName mn=QualifiedMandelName.create(name); if (mn==null) return false; model.add(folder, mn); } catch (Exception ex) { check(ex); return false; } } } return done; } private void check(Exception e) { if (!(e instanceof UnsupportedFlavorException)) { e.printStackTrace(System.out); } } /** * Remove the items moved from the list. */ public void exportDone(Transferable data, int action) { if (debug) System.out.println("action = "+action+"/"+TransferHandler.MOVE); // skip for internal move MandelFolderTransferable trans=(MandelFolderTransferable)data; MandelListFolder[] folders=trans.getFolders(); if (action==TransferHandler.MOVE && trans.getSource()!=model.getFolderTree()) { for (int i=folders.length-1; i>=0; i--) { model.removeFolder(folders[i]); } } } ///////////////////////////////////////////////////////////////////////// // List Event Adaptation ///////////////////////////////////////////////////////////////////////// private class TreeListEventAdapter implements TreeModelListener { private int getIndex(Object o) { int ix=0; for (MandelListFolder f:model.getActiveFolder().allfolders()) { if (f==o) return ix; ix++; } return -1; } public void treeNodesChanged(TreeModelEvent e) { TreePath p=e.getTreePath(); if (e.getChildren()==null) { if (p.getLastPathComponent()==model.getActiveFolder()) { fireContentsChanged(MandelListFolderListModel.this,0,Integer.MAX_VALUE); } if (p.getPathCount()>1 && p.getParentPath().getLastPathComponent()==model.getActiveFolder()) { int ix=getIndex(e.getTreePath().getLastPathComponent()); if (ix>=0) fireContentsChanged(MandelListFolderListModel.this,ix,ix); } } else { if (p.getLastPathComponent()==model.getActiveFolder()) { for (int ix:e.getChildIndices()) { fireContentsChanged(MandelListFolderListModel.this,ix,ix); } } } } public void treeNodesInserted(TreeModelEvent e) { TreePath p=e.getTreePath(); System.out.println("inserted: "+p.getLastPathComponent()); if (p.getLastPathComponent()==model.getActiveFolder()) { for (int ix:e.getChildIndices()) { fireIntervalAdded(MandelListFolderListModel.this, ix, ix); } } } public void treeStructureChanged(TreeModelEvent e) { } public void treeNodesRemoved(TreeModelEvent e) { TreePath p=e.getTreePath(); if (p.getLastPathComponent()==model.getActiveFolder()) { for (int ix:e.getChildIndices()) { fireIntervalRemoved(MandelListFolderListModel.this, ix, ix); } } } } }