001package jmri.jmrit.display.switchboardEditor.configurexml; 002 003import java.awt.Color; 004import java.awt.Dimension; 005import java.awt.Point; 006import java.util.List; 007import javax.swing.JFrame; 008import jmri.ConfigureManager; 009import jmri.InstanceManager; 010import jmri.configurexml.AbstractXmlAdapter; 011import jmri.configurexml.XmlAdapter; 012import jmri.jmrit.display.EditorManager; 013import jmri.jmrit.display.switchboardEditor.SwitchboardEditor; 014import jmri.jmrit.display.switchboardEditor.SwitchBoardLabelDisplays; 015import jmri.util.ColorUtil; 016 017import org.jdom2.Attribute; 018import org.jdom2.Element; 019import org.slf4j.Logger; 020import org.slf4j.LoggerFactory; 021 022/** 023 * Handle configuration for {@link SwitchboardEditor} panes. 024 * 025 * @author Bob Jacobsen Copyright (c) 2002 026 * @author Egbert Broerse Copyright (c) 2017, 2020 027 */ 028public class SwitchboardEditorXml extends AbstractXmlAdapter { 029 030 public SwitchboardEditorXml() { 031 } 032 033 /** 034 * Default implementation for storing the contents of a SwitchboardEditor. 035 * Storing of beanswitch properties for use on web panel 036 * {@link SwitchboardEditorXml} 037 * 038 * @param o Object to store, of type SwitchboardEditor 039 * @return Element containing the complete info 040 */ 041 @Override 042 public Element store(Object o) { 043 SwitchboardEditor p = (SwitchboardEditor) o; 044 Element panel = new Element("switchboardeditor"); 045 046 JFrame frame = p.getTargetFrame(); 047 048 panel.setAttribute("class", "jmri.jmrit.display.switchboardEditor.configurexml.SwitchboardEditorXml"); 049 panel.setAttribute("name", "" + frame.getTitle()); 050 // size and position are managed by Prefsmanager 051 panel.setAttribute("editable", "" + (p.isEditable() ? "yes" : "no")); 052 panel.setAttribute("showtooltips", "" + (p.showToolTip() ? "yes" : "no")); 053 panel.setAttribute("controlling", "" + (p.allControlling() ? "yes" : "no")); 054 panel.setAttribute("hide", p.isVisible() ? "no" : "yes"); 055 panel.setAttribute("panelmenu", p.isPanelMenuVisible() ? "yes" : "no"); 056 panel.setAttribute("scrollable", p.getScrollable()); 057 panel.setAttribute("hideunconnected", "" + (p.hideUnconnected() ? "yes" : "no")); 058 panel.setAttribute("autoitemrange", "" + (p.autoItemRange() ? "yes" : "no")); 059 panel.setAttribute("rangemin", "" + p.getPanelMenuRangeMin()); 060 panel.setAttribute("rangemax", "" + p.getPanelMenuRangeMax()); 061 panel.setAttribute("type", p.getSwitchType()); 062 panel.setAttribute("connection", p.getSwitchManu()); 063 panel.setAttribute("shape", p.getSwitchShape()); 064 panel.setAttribute("rows", "" + p.getRows()); 065 panel.setAttribute("total", "" + p.getTotal()); // total number of items displayed 066 panel.setAttribute("showusername", "" + p.showUserName()); 067 panel.setAttribute("iconscale", "" + p.getIconScale()); 068 panel.setAttribute("defaulttextcolor", p.getDefaultTextColor()); 069 panel.setAttribute("activecolor", p.getActiveSwitchColor()); // fetched directly from Editor by Servlet 070 panel.setAttribute("inactivecolor", p.getInactiveSwitchColor()); // user-settable since 4.21.3 071 if (p.getBackgroundColor() != null) { 072 panel.setAttribute("redBackground", "" + p.getBackgroundColor().getRed()); 073 panel.setAttribute("greenBackground", "" + p.getBackgroundColor().getGreen()); 074 panel.setAttribute("blueBackground", "" + p.getBackgroundColor().getBlue()); 075 } 076 077 // include contents (not used to store Switchboards on disk as 078 // all config is stored at Panel level). 079 return panel; 080 } 081 082 @Override 083 public void load(Element element, Object o) { 084 log.error("Invalid method called"); 085 } 086 087 /** 088 * Create a SwitchboardEditor object, then register and fill it, then pop it 089 * in a JFrame. 090 * 091 * @param shared Top level Element to unpack. 092 * @return true if successful 093 */ 094 @Override 095 public boolean load(Element shared, Element perNode) { 096 if (java.awt.GraphicsEnvironment.isHeadless()) { 097 return true; 098 } 099 100 boolean result = true; 101 Attribute a; 102 // find coordinates 103 int x = 0; 104 int y = 0; 105 int height = 400; 106 int width = 300; 107 int rangemin = 1; 108 int rangemax = 32; 109 int rows = 4; 110 int iconscale = 100; 111 String type; 112 String connection; 113 String shape; 114 String name; 115 116 try { 117 if ((a = shared.getAttribute("x")) != null) { 118 x = a.getIntValue(); 119 } 120 if ((a = shared.getAttribute("y")) != null) { 121 y = a.getIntValue(); 122 } 123 if ((a = shared.getAttribute("height")) != null) { 124 height = a.getIntValue(); 125 } 126 if ((a = shared.getAttribute("width")) != null) { 127 width = a.getIntValue(); 128 } 129 } catch (org.jdom2.DataConversionException e) { 130 log.error("failed to convert Switchboard's attribute"); 131 result = false; 132 } 133 // find the name 134 name = "Switchboard"; // this will be replaced by the name as stored NOI18N 135 if (shared.getAttribute("name") != null) { 136 name = shared.getAttribute("name").getValue(); 137 } 138 // confirm that panel hasn't already been loaded 139 if (InstanceManager.getDefault(EditorManager.class).contains(name)) { 140 log.warn("File contains a panel with the same name ({}) as an existing panel", name); 141 result = false; 142 } 143 144 // If available, override location and size with machine dependent values 145 if (!InstanceManager.getDefault(jmri.util.gui.GuiLafPreferencesManager.class).isEditorUseOldLocSize()) { 146 jmri.UserPreferencesManager prefsMgr = InstanceManager.getNullableDefault(jmri.UserPreferencesManager.class); 147 if (prefsMgr != null) { 148 149 Point prefsWindowLocation = prefsMgr.getWindowLocation(name); 150 if (prefsWindowLocation != null) { 151 x = (int) prefsWindowLocation.getX(); 152 y = (int) prefsWindowLocation.getY(); 153 } 154 155 Dimension prefsWindowSize = prefsMgr.getWindowSize(name); 156 if (prefsWindowSize != null && prefsWindowSize.getHeight() != 0 && prefsWindowSize.getWidth() != 0) { 157 height = (int) prefsWindowSize.getHeight(); 158 width = (int) prefsWindowSize.getWidth(); 159 } 160 } 161 } 162 163 SwitchboardEditor panel = new SwitchboardEditor(name); 164 //panel.makeFrame(name); 165 InstanceManager.getDefault(EditorManager.class).add(panel); 166 panel.getTargetFrame().setLocation(x, y); 167 panel.getTargetFrame().setSize(width, height); 168 169 panel.setTitle(); 170 171 // Load editor option flags. This has to be done before the content 172 // items are loaded, to preserve the individual item settings. 173 boolean value = true; 174 175 if ((a = shared.getAttribute("editable")) != null && a.getValue().equals("no")) { 176 value = false; 177 } 178 panel.setAllEditable(value); 179 value = (a = shared.getAttribute("showtooltips")) == null || !a.getValue().equals("no"); 180 panel.setAllShowToolTip(value); 181 value = (a = shared.getAttribute("controlling")) == null || !a.getValue().equals("no"); 182 panel.setAllControlling(value); 183 value = (a = shared.getAttribute("hide")) != null && a.getValue().equals("yes"); 184 panel.setShowHidden(value); 185 value = (a = shared.getAttribute("panelmenu")) == null || !a.getValue().equals("no"); 186 panel.setPanelMenuVisible(value); 187 188 String state = "both"; 189 if ((a = shared.getAttribute("scrollable")) != null) { 190 state = a.getValue(); 191 } 192 panel.setScroll(state); 193 value = (a = shared.getAttribute("hideunconnected")) != null && a.getValue().equals("yes"); 194 panel.setHideUnconnected(value); 195 value = (a = shared.getAttribute("autoitemrange")) == null || !a.getValue().equals("no"); 196 panel.setAutoItemRange(value); 197 198 try { 199 rangemin = shared.getAttribute("rangemin").getIntValue(); 200 rangemax = shared.getAttribute("rangemax").getIntValue(); 201 } catch (org.jdom2.DataConversionException e) { 202 log.error("failed to convert Switchboard's range"); 203 result = false; 204 } 205 panel.setPanelMenuRangeMin(rangemin); 206 panel.setPanelMenuRangeMax(rangemax); 207 208 type = shared.getAttribute("type").getValue(); 209 panel.setSwitchType(type); 210 211 connection = shared.getAttribute("connection").getValue(); 212 panel.setSwitchManu(connection); 213 log.debug("SwitchBoard connection choice set to {}", connection); 214 215 shape = shared.getAttribute("shape").getValue(); 216 panel.setSwitchShape(shape); 217 218 if (shared.getAttribute("columns") != null) { 219 try { // migration of old naming, dropped since 4.21.2 220 rows = shared.getAttribute("columns").getIntValue(); 221 } catch (org.jdom2.DataConversionException e) { 222 log.error("failed to convert Switchboard's row (formerly column) count"); 223 result = false; 224 } 225 } 226 if (shared.getAttribute("rows") != null) { 227 try { 228 rows = shared.getAttribute("rows").getIntValue(); 229 } catch (org.jdom2.DataConversionException e) { 230 log.error("failed to convert Switchboard's row count"); 231 result = false; 232 } 233 } 234 panel.setRows(rows); // if 0, autoRows is selected (handled in Editor) 235 236 a = shared.getAttribute("showusername"); 237 if (a == null || a.getValue().equals("yes")) { 238 panel.setShowUserName(SwitchBoardLabelDisplays.BOTH_NAMES); // default and migration 239 } else if (a.getValue().equals("no")) { 240 panel.setShowUserName(SwitchBoardLabelDisplays.SYSTEM_NAME); // only how system name 241 } else { 242 panel.setShowUserName(SwitchBoardLabelDisplays.USER_NAME); // display name (one, prefer user name) 243 } 244 245 if (shared.getAttribute("iconscale") != null) { 246 try { 247 iconscale = shared.getAttribute("iconscale").getIntValue(); 248 } catch (org.jdom2.DataConversionException e) { 249 log.error("failed to convert Switchboard's icon scale setting"); 250 result = false; 251 } 252 } 253 panel.setIconScale(iconscale); 254 255 Color defaultTextColor = Color.BLACK; 256 if (shared.getAttribute("defaulttextcolor") != null) { 257 String color = shared.getAttribute("defaulttextcolor").getValue(); 258 try { 259 defaultTextColor = ColorUtil.stringToColor(color); 260 } catch (IllegalArgumentException ex) { 261 log.error("Invalid defaulttextcolor {} using black", color); 262 } 263 } 264 panel.setDefaultTextColor(defaultTextColor); 265 // set color if needed 266 try { 267 int red = shared.getAttribute("redBackground").getIntValue(); 268 int blue = shared.getAttribute("blueBackground").getIntValue(); 269 int green = shared.getAttribute("greenBackground").getIntValue(); 270 panel.setDefaultBackgroundColor(new Color(red, green, blue)); 271 } catch (org.jdom2.DataConversionException e) { 272 log.warn("Could not parse color attributes!"); 273 } catch (NullPointerException e) { // considered normal if the attributes are not present 274 } 275 // activecolor 276 Color activeColor = Color.RED; 277 if (shared.getAttribute("activecolor") != null) { 278 String color = shared.getAttribute("activecolor").getValue(); 279 try { 280 activeColor = ColorUtil.stringToColor(color); 281 } catch (IllegalArgumentException ex) { 282 log.error("Invalid activecolor {}, using red", color); 283 } 284 } 285 panel.setDefaultActiveColor(activeColor); 286 // inactivecolor 287 Color inactiveColor = Color.GREEN; 288 if (shared.getAttribute("inactivecolor") != null) { 289 String color = shared.getAttribute("inactivecolor").getValue(); 290 try { 291 inactiveColor = ColorUtil.stringToColor(color); 292 } catch (IllegalArgumentException ex) { 293 log.error("Invalid inactivecolor {}, using green", color); 294 } 295 } 296 panel.setDefaultInactiveColor(inactiveColor); 297 // set the (global) editor display widgets to their flag settings 298 panel.initView(); 299 300 // load the contents with their individual option settings 301 List<Element> panelItems = shared.getChildren(); 302 for (Element item : panelItems) { 303 // get the class, hence the adapter object to do loading 304 String adapterName = item.getAttribute("class").getValue(); 305 log.debug("load via {}", adapterName); 306 try { 307 XmlAdapter adapter = (XmlAdapter) Class.forName(adapterName).getDeclaredConstructor().newInstance(); 308 // and do it 309 adapter.load(item, panel); 310 if (!panel.loadOK()) { 311 result = false; 312 } 313 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException 314 | jmri.configurexml.JmriConfigureXmlException 315 | java.lang.reflect.InvocationTargetException e) { 316 log.error("Exception while loading {}", item.getName(), e); 317 result = false; 318 } 319 } 320 panel.disposeLoadData(); // dispose of url correction data 321 322 // display the results, with the editor in back 323 panel.pack(); 324 panel.setAllEditable(panel.isEditable()); 325 326 // we don't pack the target frame here, because size was specified 327 // TODO: Work out why, when calling this method, panel size is increased 328 // vertically (at least on MS Windows) 329 panel.getTargetFrame().setVisible(true); // always show the panel 330 331 // register the resulting panel for later configuration 332 ConfigureManager cm = InstanceManager.getNullableDefault(jmri.ConfigureManager.class); 333 if (cm != null) { 334 cm.registerUser(panel); 335 } 336 337 // reset the size and position, in case the display caused it to change 338 panel.getTargetFrame().setLocation(x, y); 339 panel.getTargetFrame().setSize(width, height); 340 panel.updatePressed(); // required, picks up panel color 341 log.debug("Switchboard ready"); 342 return result; 343 } 344 345 @Override 346 public int loadOrder() { 347 return jmri.Manager.PANELFILES; 348 } 349 350 private final static Logger log = LoggerFactory.getLogger(SwitchboardEditorXml.class); 351 352}