/* * 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.Component; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import com.mandelsoft.mand.scan.MandelScanner; import com.mandelsoft.mand.tool.ctx.ContextProvider; import com.mandelsoft.mand.tool.ctx.DeleteFolderAction; import com.mandelsoft.mand.tool.ctx.MandelListFolderContextMenuHandler; import com.mandelsoft.mand.tool.ctx.NewFolderAction; import com.mandelsoft.mand.util.FileMandelListFolderTree; import com.mandelsoft.mand.util.MandelList; import com.mandelsoft.mand.util.MandelListFolder; import com.mandelsoft.mand.util.MandelListFolderTree; import com.mandelsoft.swing.ActionPanel; import com.mandelsoft.swing.DnDJTree; import com.mandelsoft.swing.GBC; /** * * @author Uwe Krüger */ public class MandelListFolderPanel extends ActionPanel implements MandelListFolderTreeModelSource { private static final boolean debug=false; private MandelListFolderTreeModel model; private DnDJTree tree; private JScrollPane view; private boolean modifiable; private JButton add; private JButton remove; private MandelListFolder active; private ContextHandler contextHandler; public MandelListFolderPanel(MandelListFolderTree ftree, MandelScanner scanner) { this(new DefaultMandelListFolderTreeModel(ftree, scanner),scanner); } public MandelListFolderPanel(MandelListFolderTreeModel model, MandelScanner scanner) { // super(new GridLayout(1,0)); Dimension minimumSize = new Dimension(10, 10); this.model=model; modifiable=model.isModifiable(); tree = new DnDJTree(this.model); tree.setCellRenderer(new FolderTreeRenderer()); tree.setEditable(true); tree.addTreeSelectionListener(new TSL()); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); view = new JScrollPane(tree); view.setMinimumSize(minimumSize); JLabel c=new JLabel("height"); FontMetrics m=c.getFontMetrics(c.getFont()); view.setPreferredSize(new Dimension( (int)(m.charWidth('W')*10), (int)(m.getHeight()*6))); // view.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); // view.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); //Add the scroll panes to a split pane. // JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); // splitPane.setTopComponent(view); // splitPane.setBottomComponent(new JLabel("Test")); // splitPane.setMinimumSize(minimumSize); // setContentPane(new JPanel()); // addContent(view,null); // setContentPane(new JPanel()); addContent(view,new GBC(0,0).setWeight(10, 10).setFill(GBC.BOTH)); tree.setToggleClickCount(3); tree.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent event) { // check for double // click if (event.getClickCount()<2) return; TreePath p=tree.getPathForLocation(event.getX(), event.getY()); if (p!=null) { if (debug) System.out.println("click at "+DefaultMandelListFolderTreeModel.path(p)); fireActionPerformed(ActionEvent.ACTION_PERFORMED, null); } } }); tree.setContextMenuHandler(contextHandler=new ContextHandler()); add=addButton("new folder",new AddActionListener()); remove=addButton("delete folder",new DeleteActionListener()); add.setEnabled(false); remove.setEnabled(false); handleModifiable(modifiable); } @Override protected void panelBound() { super.panelBound(); ToolTipManager.sharedInstance().registerComponent(tree); } @Override protected void panelUnbound() { super.panelUnbound(); ToolTipManager.sharedInstance().unregisterComponent(tree); } public MandelListFolderTreeModel getModel() { return model; } public void setModel(MandelListFolderTreeModel model) { this.model=model; tree.setModel(model); } public void setActiveFolder(MandelListFolder folder) { if (active!=folder) { MandelListFolder old=active; active=folder; firePropertyChange("activeFolder",old,active); } } public MandelListFolder getActiveFolder() { return active; } public boolean isModifiable() { return modifiable; } public void setModifiable(boolean modifiable) { if (this.modifiable!=modifiable) { handleModifiable(this.modifiable=modifiable); firePropertyChange("modifiable",!modifiable,modifiable); } } protected void handleModifiable(boolean modifiable) { remove.setVisible(modifiable); add.setVisible(modifiable); tree.setEditable(modifiable); model.setModifiable(modifiable); } public TreePath getSelectedPath() { return tree.getSelectionPath(); } public MandelListFolder getSelectedFolder() { TreePath p=tree.getSelectionPath(); if (p==null) return null; return (MandelListFolder)p.getLastPathComponent(); } public void setRootVisible(boolean b) { tree.setRootVisible(b); } private boolean folderMetaModifiable(TreePath p) { return MandelListFolderTreeModel.Util.folderMetaModifiable(getModel(), p); } private boolean folderModifiable(TreePath p) { return MandelListFolderTreeModel.Util.folderModifiable(getModel(), p); } private boolean folderContentModifiable(TreePath p) { return MandelListFolderTreeModel.Util.folderContentModifiable(getModel(), p); } //////////////////////////////////////////////////////////////// // tree //////////////////////////////////////////////////////////////// private class TSL implements TreeSelectionListener { public void valueChanged(TreeSelectionEvent e) { boolean mod=false; MandelListFolderTreeModel m=null; TreePath p=e.getNewLeadSelectionPath(); if (p!=null) { if (debug) System.out.println("TSE: "+DefaultMandelListFolderTreeModel.path(p)); //new Throwable().printStackTrace(System.out); m=(MandelListFolderTreeModel)getModel(); mod=m.isPathModifiable(p)&& !((MandelListFolder)p.getLastPathComponent()).isLeaf(); } else { if (debug) System.out.println("TSE: remove selection"); } add.setEnabled(folderModifiable(p)); remove.setEnabled(folderModifiable(p)&&folderMetaModifiable(p)); } } private class FolderTreeRenderer extends DefaultTreeCellRenderer { private String desc; public FolderTreeRenderer() { setIcon(folderIcon); setLeafIcon(listIcon); } @Override public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { MandelListFolder f=(MandelListFolder)value; // System.out.println("render "+f.getName()+ // " active:"+(active==null?"none":active.getName())+ // " list:"+(f.getMandelList()!=null)+ // " leaf:"+f.isLeaf()+ // " tleaf:"+leaf+" sel:"+sel); desc=f.getProperty(MandelListFolder.DESCRIPTION); if (!f.isLeaf()) { if (f.getMandelList()==null) { setInfo(folderIcon,"This folder has no list."); } else { if (active==value) { setInfo(activeFolderlistIcon, "this folder has a list, which is displayed"); } else { setInfo(folderlistIcon, "this folder has a list"); } } } else { if (active==value) { //System.out.println("render active list "+f.getName()); setInfo(activeListIcon, "this is a plain list, which is displayed"); } else { //System.out.println("render inactive list "+f.getName()); setInfo(listIcon, "this is a plain list"); } } //String tt=getToolTipText(); return super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, hasFocus); // setToolTipText(tt); // return c; } private String desc(String desc, String def) { if (desc==null || desc.length()==0) return def; return desc; } private void setInfo(Icon icon, String tooltip) { setOpenIcon(icon); setClosedIcon(icon); setLeafIcon(icon); setToolTipText(desc(desc,tooltip)); } } //////////////////////////////////////////////////////////////// // actions //////////////////////////////////////////////////////////////// private ContextProvider<MandelListFolder, TreePath, MandelListFolderTreeModel> prov= new ContextProvider<MandelListFolder,TreePath,MandelListFolderTreeModel>() { public TreePath getSelectionSpec() { return null; } public MandelListFolder getSelectedItem() { return MandelListFolderPanel.this.getSelectedFolder(); } public Window getWindow() { return MandelListFolderPanel.this.getWindow(); } public MandelListFolderTreeModel getModel() { return MandelListFolderPanel.this.getModel(); } }; private class DeleteActionListener extends DeleteFolderAction { public DeleteActionListener() { super(prov); } } private class AddActionListener extends NewFolderAction { public AddActionListener() { super(prov); } } ////////////////////////////////////////////////////////////////////// // Conext menu ////////////////////////////////////////////////////////////////////// private class ContextHandler extends MandelListFolderContextMenuHandler implements DnDJTree.ContextMenuHandler { @Override public MandelList getSelectedMandelList() { return getSelectedItem().getMandelList(); } public void handleContextMenu(DnDJTree table, MouseEvent evt, TreePath path) { handleContextMenu((JComponent)table,evt,path); } } //////////////////////////////////////////////////////////////// // listener support //////////////////////////////////////////////////////////////// public void addActionListener(ActionListener l) { listenerList.add(ActionListener.class, l); } public void removeActionListener(ActionListener l) { listenerList.remove(ActionListener.class, l); } public ActionListener[] getActionListeners() { return getListeners(ActionListener.class); } protected void fireActionPerformed(int id, String cmd) { // Guaranteed to return a non-null array Object[] listeners=listenerList.getListenerList(); ActionEvent e=null; // Process the listeners last to first, notifying // those that are interested in this event for (int i=listeners.length-2; i>=0; i-=2) { if (listeners[i]==ActionListener.class) { // Lazily create the event: if (e==null) e=new ActionEvent(this, id, cmd); ((ActionListener)listeners[i+1]).actionPerformed(e); } } } ///////////////////////////////////////////////////////////// // icons ///////////////////////////////////////////////////////////// protected static ImageIcon createImageIcon(String path) { java.net.URL imgURL=MandelListFolderPanel.class.getResource(path); if (imgURL!=null) { return new ImageIcon(imgURL); } else { System.err.println("Couldn't find file: "+path); return null; } } static public final ImageIcon listIcon= createImageIcon("resc/list2.gif"); static public final ImageIcon activeListIcon= createImageIcon("resc/alist2.gif"); static public final ImageIcon folderIcon= createImageIcon("resc/folder2.gif"); static public final ImageIcon folderlistIcon= createImageIcon("resc/folderlist2.gif"); static public final ImageIcon activeFolderlistIcon= createImageIcon("resc/afolderlist2.gif"); ///////////////////////////////////////////////////////////// // test ///////////////////////////////////////////////////////////// static class TestFrame extends JFrame { TestFrame(MandelListFolderTree ftree) { MandelListFolderPanel panel=new MandelListFolderPanel( ftree, null); panel.setModifiable(true); add(panel); pack(); } } public static void main(String[] args) { File file = new File(args[0]); final FileMandelListFolderTree f=new FileMandelListFolderTree(file); f.print("",f.getRoot()); SwingUtilities.invokeLater(new Runnable() { public void run() { JFrame frame=new TestFrame(f); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }); } }