001package jmri.jmrix.openlcb.swing.networktree; 002 003import java.awt.Dimension; 004import javax.swing.JTree; 005import javax.swing.event.TreeSelectionEvent; 006import javax.swing.tree.DefaultMutableTreeNode; 007 008import jmri.*; 009import jmri.jmrix.can.CanListener; 010import jmri.jmrix.can.CanMessage; 011import jmri.jmrix.can.CanReply; 012import jmri.jmrix.can.CanSystemConnectionMemo; 013import jmri.jmrix.can.swing.CanPanelInterface; 014import jmri.jmrix.openlcb.swing.ClientActions; 015import jmri.util.JmriJFrame; 016 017import org.openlcb.Connection; 018import org.openlcb.MimicNodeStore; 019import org.openlcb.NodeID; 020import org.openlcb.OlcbInterface; 021import org.openlcb.SimpleNodeIdent; 022import org.openlcb.implementations.MemoryConfigurationService; 023import org.openlcb.swing.memconfig.MemConfigDescriptionPane; 024import org.openlcb.swing.memconfig.MemConfigReadWritePane; 025import org.openlcb.swing.networktree.NodeTreeRep; 026import org.openlcb.swing.networktree.TreePane; 027 028/** 029 * Frame displaying tree of OpenLCB nodes. 030 * 031 * @author Bob Jacobsen Copyright (C) 2009, 2010, 2012 032 */ 033public class NetworkTreePane extends jmri.util.swing.JmriPanel implements CanListener, CanPanelInterface { 034 035 public NetworkTreePane() { 036 super(); 037 } 038 039 private transient CanSystemConnectionMemo memo; 040 041 @Override 042 public void initContext(Object context) { 043 if (context instanceof CanSystemConnectionMemo) { 044 initComponents((CanSystemConnectionMemo) context); 045 } 046 } 047 048 @Override 049 public void initComponents(CanSystemConnectionMemo memo) { 050 this.memo = memo; 051 052 memo.getTrafficController().addCanListener(this); 053 054 // add GUI components 055 setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.Y_AXIS)); 056 057 treePane = new TreePane(){ 058 UserPreferencesManager pref = jmri.InstanceManager.getDefault(UserPreferencesManager.class); 059 String sortPreferenceName = NetworkTreePane.class.getName() + ".selectedSortOrder"; 060 061 @Override 062 public void initComponents(MimicNodeStore store, final Connection connection, 063 final NodeID node, final NodeTreeRep.SelectionKeyLoader loader) { 064 super.initComponents(store, connection, node, loader); 065 // finally handle sort-by JComboBox preferences WITHOUT setting preferences 066 var name = pref.getProperty(this.getClass().getName(), sortPreferenceName); 067 if (name == null) name = "BY_NAME"; 068 SortOrder order; 069 try { 070 order = SortOrder.valueOf((String)name); 071 } catch (IllegalArgumentException e) { 072 order = SortOrder.BY_NAME; 073 } 074 super.setSortOrder(order); 075 // and do it a little later to make sure the table has been shown 076 final var localOrder = order; 077 jmri.util.ThreadingUtil.runOnLayoutDelayed( () -> { 078 super.setSortOrder(localOrder); 079 }, 750 080 ); 081 } 082 083 // This overrides setOrder to preserve the order 084 @Override 085 public void setSortOrder(SortOrder order) { 086 pref.setProperty(this.getClass().getName(), sortPreferenceName, order.name()); 087 super.setSortOrder(order); 088 } 089 }; 090 treePane.setPreferredSize(new Dimension(300, 300)); 091 092 treePane.initComponents(memo.get(MimicNodeStore.class), memo.get(Connection.class), memo.get(NodeID.class), new ActionLoader(memo) 093 ); 094 add(treePane); 095 096 treePane.addTreeSelectionListener((TreeSelectionEvent e) -> { 097 JTree tree = (JTree) e.getSource(); 098 DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 099 100 if (node == null) { 101 return; 102 } 103 104 if (node.getUserObject() instanceof NodeTreeRep.SelectionKey) { 105 ((NodeTreeRep.SelectionKey) node.getUserObject()).select(node); 106 } 107 }); 108 } 109 110 TreePane treePane; 111 112 @Override 113 public String getTitle() { 114 if (memo != null) { 115 return (memo.getUserName() + " Network Tree"); 116 } 117 return "LCC / OpenLCB Network Tree"; 118 } 119 120 @Override 121 public void dispose() { 122 memo.getTrafficController().removeCanListener(this); 123 } 124 125 @Override 126 public synchronized void message(CanMessage l) { // receive a message and log it 127 } 128 129 @Override 130 public synchronized void reply(CanReply l) { // receive a reply and log it 131 } 132 133 //private final static Logger log = LoggerFactory.getLogger(NetworkTreePane.class); 134 135 /** 136 * Nested class to open specific windows when proper tree element is picked. 137 */ 138 private static class ActionLoader extends NodeTreeRep.SelectionKeyLoader { 139 140 private final ClientActions actions; 141 142 ActionLoader(CanSystemConnectionMemo memo) { 143 OlcbInterface iface = memo.get(OlcbInterface.class); 144 actions = new ClientActions(iface, memo); 145 this.store = iface.getNodeStore(); 146 this.mcs = iface.getMemoryConfigurationService(); 147 } 148 149 final MimicNodeStore store; 150 final MemoryConfigurationService mcs; 151 152 @Override 153 public NodeTreeRep.SelectionKey cdiKey(String name, NodeID node) { 154 return new NodeTreeRep.SelectionKey(name, node) { 155 @Override 156 public void select(DefaultMutableTreeNode rep) { 157 MimicNodeStore.NodeMemo memo = store.findNode(node); 158 SimpleNodeIdent ident = memo.getSimpleNodeIdent(); 159 StringBuilder description = new StringBuilder(); 160 if (ident.getUserName() != null) { 161 description.append(ident.getUserName()); 162 } 163 if (ident.getUserDesc() != null && ident.getUserDesc().length() > 0) { 164 if (description.length() > 0) { 165 description.append(" - "); 166 } 167 description.append(ident.getUserDesc()); 168 } 169 if (description.length() == 0) { 170 if (ident.getMfgName() != null && ident.getMfgName().length() > 0) { 171 description.append(ident.getMfgName()); 172 } 173 if (ident.getModelName() != null && ident.getModelName().length() > 0) { 174 if (description.length() > 0) { 175 description.append(" - "); 176 } 177 description.append(ident.getModelName()); 178 } 179 } 180 if (description.length() == 0) { 181 description.append(node.toString()); 182 } else { 183 description.append(" ("); 184 description.append(node.toString()); 185 description.append(")"); 186 } 187 openCdiPane(node, description.toString()); 188 } 189 }; 190 } 191 192 @Override 193 public NodeTreeRep.SelectionKey configurationKey(String name, NodeID node) { 194 return new NodeTreeRep.SelectionKey(name, node) { 195 @Override 196 public void select(DefaultMutableTreeNode rep) { 197 openConfigurePane(node); 198 } 199 }; 200 } 201 202 void openConfigurePane(NodeID node) { 203 { 204 JmriJFrame f = new JmriJFrame(); 205 f.setTitle("Configuration Capabilities " + node); 206 MemConfigDescriptionPane mc = new MemConfigDescriptionPane(node, store, mcs); 207 f.add(mc); 208 mc.initComponents(); 209 f.pack(); 210 f.setVisible(true); 211 } 212 { 213 JmriJFrame f = new JmriJFrame(); 214 f.setTitle("Configuration R/W Tool " + node); 215 MemConfigReadWritePane mc = new MemConfigReadWritePane(node, store, mcs); 216 f.add(mc); 217 mc.initComponents(); 218 f.pack(); 219 f.setVisible(true); 220 } 221 } 222 223 public void openCdiPane(final NodeID destNode, String description) { 224 actions.openCdiWindow(destNode, description); 225 } 226 } 227 228}