1 4 package org.oddjob.designer.view; 5 6 import java.awt.BorderLayout ; 7 import java.awt.Component ; 8 import java.awt.Container ; 9 import java.awt.Dimension ; 10 import java.awt.GridBagConstraints ; 11 import java.awt.GridBagLayout ; 12 import java.awt.event.ActionEvent ; 13 14 import javax.swing.AbstractAction ; 15 import javax.swing.Action ; 16 import javax.swing.JMenu ; 17 import javax.swing.JMenuItem ; 18 import javax.swing.JPanel ; 19 import javax.swing.JPopupMenu ; 20 import javax.swing.JScrollPane ; 21 import javax.swing.JSplitPane ; 22 import javax.swing.JTree ; 23 import javax.swing.event.TreeModelEvent ; 24 import javax.swing.event.TreeModelListener ; 25 import javax.swing.event.TreeSelectionEvent ; 26 import javax.swing.event.TreeSelectionListener ; 27 import javax.swing.tree.DefaultMutableTreeNode ; 28 import javax.swing.tree.DefaultTreeModel ; 29 import javax.swing.tree.TreePath ; 30 import javax.swing.tree.TreeSelectionModel ; 31 32 import org.oddjob.designer.Looks; 33 import org.oddjob.designer.model.DesignDefinition; 34 import org.oddjob.designer.model.DesignElement; 35 import org.oddjob.designer.model.DesignElementType; 36 import org.oddjob.designer.model.StandardForm; 37 import org.oddjob.designer.model.MultiTypeTree; 38 39 42 public class MultiTypeTreeView implements ViewProducer { 43 44 private final MultiTypeTree designDefinition; 45 46 private final DefaultMutableTreeNode top = new DefaultMutableTreeNode (); 47 private final DefaultTreeModel model = new DefaultTreeModel (top); 48 49 54 public MultiTypeTreeView(MultiTypeTree designDefinition) { 55 this.designDefinition = designDefinition; 56 57 top.setUserObject(designDefinition.getDesignElement()); 58 buildTree(top); 59 } 60 61 66 void buildTree(DefaultMutableTreeNode tn) { 67 DesignElementType de = (DesignElementType) tn.getUserObject(); 68 DesignElementType[] children = de.children(); 69 for (int i = 0; i < children.length; ++i) { 70 DefaultMutableTreeNode ctn = new DefaultMutableTreeNode (); 71 ctn.setUserObject(children[i]); 72 tn.add(ctn); 73 buildTree(ctn); 74 } 75 } 76 77 81 public Component dialog() { 82 return group(); 83 } 84 85 89 public Component group() { 90 ValuesPanel mainForm = new ValuesPanel(); 91 return mainForm; 92 } 93 94 97 public Component detailEdit() { 98 return ViewHelper.createDetailButton(designDefinition); 99 } 100 101 105 public Component cell() { 106 return ViewHelper.createDetailButton(designDefinition); 107 } 108 109 112 public int inline(Container container, int row, int column, 113 boolean selectionInGroup) { 114 throw new UnsupportedOperationException ("Can't imagine a tree ever being used inline!"); 115 } 116 117 120 public void setEnabled(boolean enabled) { 121 throw new UnsupportedOperationException ("Can't imagine a tree ever being used in a selection!"); 122 } 123 124 128 class ValuesPanel extends JPanel { 129 130 private JScrollPane detailScroll; 131 132 ValuesPanel() { 133 final PopupListener popupListener = new PopupListener(); 134 135 detailScroll = new JScrollPane (); 136 detailScroll.setPreferredSize(new Dimension ( 137 Looks.DETAIL_FORM_WIDTH, Looks.DESIGNER_HEIGHT)); 138 139 final JTree tree = new JTree (model); 140 tree.setShowsRootHandles(true); 141 tree.setExpandsSelectedPaths(true); 142 model.addTreeModelListener(new TreeModelListener () { 143 public void treeNodesChanged(TreeModelEvent e) { 144 } 145 public void treeNodesInserted(TreeModelEvent e) { 146 TreePath p = e.getTreePath().pathByAddingChild(e.getChildren()[0]); 147 tree.scrollPathToVisible(p); 148 } 149 public void treeNodesRemoved(TreeModelEvent e) { 150 tree.setSelectionPath(null); 151 } 152 public void treeStructureChanged(TreeModelEvent e) { 153 } 154 }); 155 156 tree.getSelectionModel().setSelectionMode 157 (TreeSelectionModel.SINGLE_TREE_SELECTION); 158 159 tree.addTreeSelectionListener(new TreeSelectionListener () { 160 public void valueChanged(TreeSelectionEvent event) { 161 JTree tree = (JTree )event.getSource(); 162 DefaultMutableTreeNode tn = (DefaultMutableTreeNode ) tree.getLastSelectedPathComponent(); 163 if (tn == null) { 164 popupListener.setPopup(null); 165 detailScroll.setViewportView(new JPanel ()); 166 } else { 167 popupListener.setPopup(generatePopup(tn)); 168 169 JPanel detailView = new JPanel (); 170 detailView.setLayout(new GridBagLayout ()); 171 GridBagConstraints c = new GridBagConstraints (); 172 c.anchor = GridBagConstraints.FIRST_LINE_START; 173 c.fill = GridBagConstraints.NONE; 174 c.gridx = 0; 175 c.gridy = 0; 176 c.weightx = 1.0; 177 c.weighty = 1.0; 178 179 DesignDefinition dd = null; 180 if (tn != top) { 181 DesignElement de = (DesignElement) tn.getUserObject(); 182 dd = de.detail(); 183 } 184 else { 185 dd = designDefinition.getDetail(); 186 } 187 if (dd != null) { 188 detailView.add(FormFactory.createForm( 189 new StandardForm(dd.getTitle()) 190 .addGroup(dd)), c); 191 detailScroll.setViewportView(detailView); 192 } 193 } 194 detailScroll.validate(); 195 detailScroll.repaint(); 196 } 197 }); 198 tree.addMouseListener(popupListener); 199 200 setLayout(new BorderLayout ()); 201 JScrollPane treeScroll = new JScrollPane (); 202 treeScroll.setPreferredSize(new Dimension ( 203 Looks.DESIGNER_TREE_WIDTH, Looks.DESIGNER_HEIGHT)); 204 205 treeScroll.setViewportView(tree); 206 207 JSplitPane split = new JSplitPane (JSplitPane.HORIZONTAL_SPLIT, 208 treeScroll, detailScroll); 209 210 add(split); 211 } 212 } 213 214 215 JPopupMenu generatePopup(DefaultMutableTreeNode tn) { 216 JMenu menu = new JMenu (); 217 DesignElementType de = (DesignElementType) tn.getUserObject(); 218 final String [] choices = de.supportedTypes(); 219 for (int i = 0; i < choices.length; ++i) { 220 menu.add(new JMenuItem (new AddAction(tn, choices[i]))); 221 } 222 if (tn != top) { 223 menu.add(new JMenuItem (new DeleteAction(tn))); 224 } 225 return menu.getPopupMenu(); 226 } 227 228 class AddAction extends AbstractAction { 229 final DefaultMutableTreeNode tn; 230 final String type; 231 AddAction(DefaultMutableTreeNode tn, String type) { 232 this.tn = tn; 233 this.type = type; 234 putValue(Action.NAME, "Add " + type); 235 } 236 public void actionPerformed(ActionEvent e) { 237 DesignElementType de = (DesignElementType) tn.getUserObject(); 238 DesignElementType nde = de.createType(type); 239 de.addChild(nde); 240 DefaultMutableTreeNode ntn= new DefaultMutableTreeNode (nde); 241 model.insertNodeInto(ntn, tn, tn.getChildCount()); 242 } 243 } 244 245 class DeleteAction extends AbstractAction { 246 final DefaultMutableTreeNode tn; 247 DeleteAction(DefaultMutableTreeNode tn) { 248 this.tn = tn; 249 putValue(Action.NAME, "Delete"); 250 } 251 public void actionPerformed(ActionEvent e) { 252 int index = tn.getParent().getIndex(tn); 253 DesignElementType parentDE = (DesignElementType) 254 ((DefaultMutableTreeNode )tn.getParent()).getUserObject(); 255 parentDE.removeChild(index); 256 model.removeNodeFromParent(tn); 257 } 258 } 259 260 } 261 | Popular Tags |