001package jmri.jmrix.loconet.sdfeditor; 002 003import java.awt.Dimension; 004import java.awt.FlowLayout; 005import java.util.List; 006import java.util.ResourceBundle; 007import javax.swing.BoxLayout; 008import javax.swing.JComponent; 009import javax.swing.JEditorPane; 010import javax.swing.JLabel; 011import javax.swing.JPanel; 012import javax.swing.JScrollPane; 013import javax.swing.JSeparator; 014import javax.swing.JSplitPane; 015import javax.swing.JTree; 016import javax.swing.event.TreeSelectionEvent; 017import javax.swing.event.TreeSelectionListener; 018import javax.swing.tree.DefaultMutableTreeNode; 019import javax.swing.tree.TreePath; 020import javax.swing.tree.TreeSelectionModel; 021import jmri.jmrix.loconet.sdf.SdfBuffer; 022import jmri.jmrix.loconet.sdf.SdfMacro; 023 024/** 025 * Pane for editing Digitrax SDF files. 026 * <p> 027 * The GUI consists of a tree of instructions on the left, and on the right an 028 * edit panel. The edit panel has a small detailed view of the instruction over 029 * a larger detailed view. 030 * 031 * @author Bob Jacobsen Copyright (C) 2007, 2008 032 */ 033public class EditorPane extends javax.swing.JPanel implements TreeSelectionListener { 034 035 // GUI member declarations 036 static ResourceBundle res = ResourceBundle.getBundle("jmri.jmrix.loconet.sdfeditor.Editor"); 037 static ResourceBundle exp = ResourceBundle.getBundle("jmri.jmrix.loconet.sdfeditor.Explanations"); 038 039 public EditorPane() { 040 // start to configure GUI 041 setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); 042 043 // install left and right parts in split pane 044 split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, newTree(), newEditPane()); 045 add(split); 046 } 047 048 JSplitPane split; 049 JTree tree; 050 DefaultMutableTreeNode topNode; 051 052 JComponent newTree() { 053 topNode = new DefaultMutableTreeNode("file"); // NOI18N 054 tree = new JTree(topNode); 055 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 056 057 // Listen for when the selection changes. 058 tree.addTreeSelectionListener(this); 059 060 // install in scroll area 061 JScrollPane treeView = new JScrollPane(tree); 062 treeView.setMinimumSize(new Dimension(250, 600)); 063 treeView.setPreferredSize(new Dimension(250, 600)); 064 return treeView; 065 } 066 067 SdfMacroEditor lastEditor = null; 068 069 /** 070 * Handle tree selection 071 */ 072 @Override 073 public void valueChanged(TreeSelectionEvent e) { 074 DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 075 076 if (node == null) { 077 return; 078 } 079 080 // get an editor 081 SdfMacroEditor nodeInfo = (SdfMacroEditor) node.getUserObject(); 082 083 // use that editor to show the instruction 084 instruction.setText(nodeInfo.oneInstructionString()); 085 086 // show the explanation text 087 explanation.setText(exp.getString(nodeInfo.getMacro().name())); 088 089 // make the correct editor visible 090 if (lastEditor != null) { 091 lastEditor.setVisible(false); 092 } 093 lastEditor = nodeInfo; 094 nodeInfo.update(); 095 nodeInfo.setVisible(true); 096 } 097 098 public void updateSummary() { 099 if (lastEditor != null) { 100 instruction.setText(lastEditor.oneInstructionString()); 101 } 102 } 103 104 JPanel newEditPane() { 105 JPanel p = new JPanel(); 106 p.setMinimumSize(new Dimension(600, 400)); 107 p.setPreferredSize(new Dimension(600, 400)); 108 p.setMaximumSize(new Dimension(600, 400)); 109 110 // layout is two vertical parts 111 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); 112 113 // upper part of right window 114 p.add(newInstructionPane()); 115 116 p.add(new JSeparator()); 117 118 p.add(explanation); 119 explanation.setEditable(false); 120 explanation.setContentType("text/html"); // NOI18N 121 explanation.setMinimumSize(new Dimension(600, 200)); 122 explanation.setPreferredSize(new Dimension(600, 200)); 123 explanation.setMaximumSize(new Dimension(600, 200)); 124 explanation.setBackground(new JLabel().getBackground()); 125 126 p.add(new JSeparator()); 127 128 // lower part of right window 129 p.add(newDetailPane()); 130 131 return p; 132 } 133 134 MonitoringLabel instruction = new MonitoringLabel(); 135 JEditorPane explanation = new JEditorPane(); 136 137 JComponent newInstructionPane() { 138 instruction.setLineWrap(true); 139 instruction.setWrapStyleWord(true); 140 instruction.setText("Select an instruction in the tree to the left"); // NOI18N 141 instruction.setEditable(false); 142 instruction.setMinimumSize(new Dimension(600, 80)); 143 instruction.setPreferredSize(new Dimension(600, 80)); 144 instruction.setMaximumSize(new Dimension(600, 80)); 145 instruction.setBackground(new JLabel().getBackground()); 146 return instruction; 147 } 148 149 JPanel detailed = new JPanel(); // panel that contains the specific editors 150 151 JPanel newDetailPane() { 152 153 detailed.setLayout(new FlowLayout()); 154 155 return detailed; 156 } 157 158 /** 159 * Add the instructions to the tree 160 * @param buff Buffer to add 161 */ 162 void addSdf(SdfBuffer buff) { 163 //DefaultMutableTreeNode newNode = null; 164 165 // make the top elements at the top 166 List<SdfMacro> ops = buff.getMacroList(); 167 for (int i = 0; i < ops.size(); i++) { 168 nestNodes(topNode, ops.get(i)); 169 } 170 171 // don't show the top (single) node, 172 // do show all the ones right under that. 173 tree.expandPath(new TreePath(topNode)); 174 tree.setRootVisible(false); 175 176 } 177 178 void nestNodes(DefaultMutableTreeNode parent, SdfMacro macro) { 179 // put in the new topmost node 180 SdfMacroEditor e = SdfMacroEditor.attachEditor(macro); 181 detailed.add(e); 182 e.setVisible(false); 183 DefaultMutableTreeNode newNode 184 = new DefaultMutableTreeNode(e); 185 e.setNotify(newNode, this); 186 parent.add(newNode); 187 188 // recurse for kids 189 List<SdfMacro> children = macro.getChildren(); 190 if (children == null) { 191 return; 192 } 193 for (int i = 0; i < children.size(); i++) { 194 nestNodes(newNode, children.get(i)); 195 } 196 } 197 198 /** 199 * Get rid of held resources 200 */ 201 void dispose() { 202 } 203 204}