001package jmri.jmrit.throttle.preferences; 002 003import java.awt.Dimension; 004import java.beans.PropertyChangeEvent; 005import java.beans.PropertyChangeListener; 006import java.io.File; 007import java.util.ArrayList; 008 009import jmri.jmrit.XmlFile; 010import jmri.util.FileUtil; 011 012import org.jdom2.Document; 013import org.jdom2.Element; 014import org.slf4j.Logger; 015import org.slf4j.LoggerFactory; 016 017/** 018 * A class to store JMRI throttles preferences. 019 * <p> 020 * A singleton instance is provided by a call to 021 * <code>jmri.InstanceManager.getDefault(ThrottlesPreferences.class);</code> or 022 * <code>jmri.InstanceManager.getNullableDefault(ThrottlesPreferences.class)</code>; 023 * @author Lionel Jeanson - 2009-2021 024 * 025 */ 026public class ThrottlesPreferences implements jmri.InstanceManagerAutoDefault { 027 028 public static final String prefPopertyName = "ThrottlePreferences"; 029 030 private boolean _useExThrottle = true; 031 private boolean _useToolBar = true; 032 private boolean _useFunctionIcon = true; 033 private boolean _useLargeSpeedSlider = true; 034 private boolean _resizeWinImg = false; 035 private boolean _useRosterImage = true; 036 private boolean _enableRosterSearch = true; 037 private boolean _enableAutoLoad = true; 038 private boolean _hideUndefinedFunButton = false; 039 private boolean _hideSpeedStepSelector = false; 040 private boolean _ignoreThrottlePosition = true; 041 private boolean _saveThrottleOnLayoutSave = true; 042 private boolean _isAddressSelectorShowingAllRosterGroup = false; 043 private boolean _isSilentSteal = false; 044 private boolean _isSilentShare = false; 045 private String _defaultThrottleFilePath = null; 046 private ThrottlesPreferencesWindowKeyboardControls _tpwkc = new ThrottlesPreferencesWindowKeyboardControls(); 047 protected boolean dirty = false; 048 049 private Dimension _winDim = new Dimension(800, 600); 050 private String prefFile; 051 private ArrayList<PropertyChangeListener> listeners; 052 053 public ThrottlesPreferences() { 054 String dirname = FileUtil.getUserFilesPath() + "throttle" + File.separator; 055 FileUtil.createDirectory(dirname); 056 prefFile = dirname + "ThrottlesPreferences.xml"; 057 ThrottlesPrefsXml prefs = new ThrottlesPrefsXml(); 058 File file = new File(prefFile); 059 Element root; 060 try { 061 root = prefs.rootFromFile(file); 062 } catch (java.io.FileNotFoundException e2) { 063 log.info("Did not find throttle preferences file. This is normal if you haven't save the preferences before"); 064 root = null; 065 } catch (Exception e) { 066 log.error("Exception while loading throttles preferences", e); 067 root = null; 068 } 069 if (root != null) { 070 load(root.getChild("throttlesPreferences")); 071 } 072 } 073 074 public void load(org.jdom2.Element e) { 075 if (e == null) { 076 return; 077 } 078 org.jdom2.Attribute a; 079 org.jdom2.Attribute b; 080 if ((a = e.getAttribute("isUsingExThrottle")) != null) { 081 setUseExThrottle(a.getValue().compareTo("true") == 0); 082 } 083 if ((a = e.getAttribute("isUsingToolBar")) != null) { 084 setUsingToolBar(a.getValue().compareTo("true") == 0); 085 } 086 if ((a = e.getAttribute("isResizingWindow")) != null) { 087 setResizeWindow(a.getValue().compareTo("true") == 0); 088 } 089 if ((a = e.getAttribute("isUsingFunctionIcon")) != null) { 090 setUsingFunctionIcon(a.getValue().compareTo("true") == 0); 091 } 092 if (((a = e.getAttribute("windowDimensionWidth")) != null) && ((b = e.getAttribute("windowDimensionHeight")) != null)) { 093 setWindowDimension(new Dimension(Integer.parseInt(a.getValue()), Integer.parseInt(b.getValue()))); 094 } 095 if ((a = e.getAttribute("isSavingThrottleOnLayoutSave")) != null) { 096 setSaveThrottleOnLayoutSave(a.getValue().compareTo("true") == 0); 097 } 098 if ((a = e.getAttribute("isUsingRosterImage")) != null) { 099 setUseRosterImage(a.getValue().compareTo("true") == 0); 100 } 101 if ((a = e.getAttribute("isEnablingRosterSearch")) != null) { 102 setEnableRosterSearch(a.getValue().compareTo("true") == 0); 103 } 104 if ((a = e.getAttribute("isAutoLoading")) != null) { 105 setAutoLoad(a.getValue().compareTo("true") == 0); 106 } 107 if ((a = e.getAttribute("isHidingUndefinedFunctionButtons")) != null) { 108 setHideUndefinedFuncButt(a.getValue().compareTo("true") == 0); 109 } 110 if ((a = e.getAttribute("isIgnoringThrottlePosition")) != null) { 111 setIgnoreThrottlePosition(a.getValue().compareTo("true") == 0); 112 } 113 if ((a = e.getAttribute("isSilentSteal")) != null) { 114 setSilentSteal(a.getValue().compareTo("true") == 0); 115 } 116 if ((a = e.getAttribute("isSilentShare")) != null) { 117 setSilentShare(a.getValue().compareTo("true") == 0); 118 } 119 if ((a = e.getAttribute("isUsingLargeSpeedSlider")) != null) { 120 setUseLargeSpeedSlider(a.getValue().compareTo("true") == 0); 121 } 122 if ((a = e.getAttribute("isHidingSpeedStepSelector")) != null) { 123 setHideSpeedStepSelector(a.getValue().compareTo("true") == 0); 124 } 125 if ((a = e.getAttribute("isAddressSelectorShowingAllRosterGroup")) != null) { 126 setAddressSelectorShowingAllRosterGroup(a.getValue().compareTo("true") == 0); 127 } 128 if (e.getChild("throttlesControls") != null) { 129 this._tpwkc.load(e.getChild("throttlesControls")); 130 } 131 if ((a = e.getAttribute("defaultThrottleFilePath")) != null) { 132 setDefaultThrottleFilePath(a.getValue()); 133 } 134 135 this.dirty = false; 136 } 137 138 /** 139 * @return true if preferences need to be saved 140 */ 141 public boolean isDirty() { 142 return dirty; 143 } 144 145 /** 146 * An extension of the abstract XmlFile. No changes made to that class. 147 * 148 */ 149 static class ThrottlesPrefsXml extends XmlFile { 150 } 151 152 public Element store() { 153 org.jdom2.Element e = new org.jdom2.Element("throttlesPreferences"); 154 e.setAttribute("isUsingExThrottle", "" + isUsingExThrottle()); 155 e.setAttribute("isUsingToolBar", "" + isUsingToolBar()); 156 e.setAttribute("isUsingFunctionIcon", "" + isUsingFunctionIcon()); 157 e.setAttribute("isResizingWindow", "" + isResizingWindow()); 158 e.setAttribute("windowDimensionWidth", "" + (int) getWindowDimension().getWidth()); 159 e.setAttribute("windowDimensionHeight", "" + (int) getWindowDimension().getHeight()); 160 e.setAttribute("isSavingThrottleOnLayoutSave", "" + isSavingThrottleOnLayoutSave()); 161 e.setAttribute("isUsingRosterImage", "" + isUsingRosterImage()); 162 e.setAttribute("isEnablingRosterSearch", "" + isEnablingRosterSearch()); 163 e.setAttribute("isAutoLoading", "" + isAutoLoading()); 164 e.setAttribute("isHidingUndefinedFunctionButtons", "" + isHidingUndefinedFuncButt()); 165 e.setAttribute("isIgnoringThrottlePosition", "" + isIgnoringThrottlePosition()); 166 e.setAttribute("isSilentSteal", "" + isSilentSteal()); 167 e.setAttribute("isSilentShare", "" + isSilentShare()); 168 e.setAttribute("isHidingSpeedStepSelector", "" + isHidingSpeedStepSelector()); 169 e.setAttribute("isUsingLargeSpeedSlider", "" + isUsingLargeSpeedSlider()); 170 e.setAttribute("defaultThrottleFilePath", "" + getDefaultThrottleFilePath()); 171 e.setAttribute("isAddressSelectorShowingAllRosterGroup", "" + isAddressSelectorShowingAllRosterGroup()); 172 java.util.ArrayList<Element> children = new java.util.ArrayList<>(1); 173 children.add(this._tpwkc.store()); 174 e.setContent(children); 175 return e; 176 } 177 178 public void set(ThrottlesPreferences tp) { 179 setWindowDimension(tp.getWindowDimension()); 180 setUseExThrottle(tp.isUsingExThrottle()); 181 setUsingToolBar(tp.isUsingToolBar()); 182 setUsingFunctionIcon(tp.isUsingFunctionIcon()); 183 setResizeWindow(tp.isResizingWindow()); 184 setSaveThrottleOnLayoutSave(tp.isSavingThrottleOnLayoutSave()); 185 setUseRosterImage(tp.isUsingRosterImage()); 186 setEnableRosterSearch(tp.isEnablingRosterSearch()); 187 setAutoLoad(tp.isAutoLoading()); 188 setHideUndefinedFuncButt(tp.isHidingUndefinedFuncButt()); 189 setIgnoreThrottlePosition(tp.isIgnoringThrottlePosition()); 190 setSilentSteal(tp.isSilentSteal()); 191 setSilentShare(tp.isSilentShare()); 192 setUseLargeSpeedSlider(tp.isUsingLargeSpeedSlider()); 193 setThrottlesKeyboardControls(tp.getThrottlesKeyboardControls()); 194 setDefaultThrottleFilePath(tp.getDefaultThrottleFilePath()); 195 setHideSpeedStepSelector(tp.isHidingSpeedStepSelector()); 196 setAddressSelectorShowingAllRosterGroup(tp.isAddressSelectorShowingAllRosterGroup()); 197 198 if (listeners != null) { 199 for (int i = 0; i < listeners.size(); i++) { 200 PropertyChangeListener l = listeners.get(i); 201 PropertyChangeEvent e = new PropertyChangeEvent(this, prefPopertyName, null, this); 202 l.propertyChange(e); 203 } 204 } 205 } 206 207 public void save() { 208 if (prefFile == null) { 209 return; 210 } 211 XmlFile xf = new XmlFile() { 212 }; // odd syntax is due to XmlFile being abstract 213 xf.makeBackupFile(prefFile); 214 File file = new File(prefFile); 215 try { 216 //The file does not exist, create it before writing 217 File parentDir = file.getParentFile(); 218 if (!parentDir.exists()) { 219 if (!parentDir.mkdir()) // make directory, check result 220 { 221 log.error("failed to make parent directory"); 222 } 223 } 224 if (!file.createNewFile()) // create file, check result 225 { 226 log.error("createNewFile failed"); 227 } 228 } catch (Exception exp) { 229 log.error("Exception while writing the new throttles preferences file, may not be complete", exp); 230 } 231 232 try { 233 Element root = new Element("throttles-preferences"); 234 Document doc = XmlFile.newDocument(root, XmlFile.getDefaultDtdLocation() + "throttles-preferences.dtd"); 235 // add XSLT processing instruction 236 // <?xml-stylesheet type="text/xsl" href="XSLT/throttle.xsl"?> 237/*TODO (write XSLT processing instruction) java.util.Map<String,String> m = new java.util.HashMap<String,String>(); 238 m.put("type", "text/xsl"); 239 m.put("href", jmri.jmrit.XmlFile.xsltLocation+"throttles-preferences.xsl"); 240 ProcessingInstruction p = new ProcessingInstruction("xml-stylesheet", m); 241 doc.addContent(0,p);*/ 242 root.setContent(store()); 243 xf.writeXML(file, doc); 244 } catch (java.io.IOException ex) { 245 log.warn("Exception in storing throttles preferences xml", ex); 246 } 247 this.dirty = false; 248 } 249 250 public Dimension getWindowDimension() { 251 return _winDim; 252 } 253 254 public void setWindowDimension(Dimension d) { 255 _winDim = d; 256 this.dirty = true; 257 } 258 259 public boolean isUsingExThrottle() { 260 return _useExThrottle; 261 } 262 263 public void setUseExThrottle(boolean exThrottle) { 264 _useExThrottle = exThrottle; 265 this.dirty = true; 266 } 267 268 public boolean isUsingToolBar() { 269 return _useToolBar; 270 } 271 272 public void setUsingToolBar(boolean win4all) { 273 _useToolBar = win4all; 274 this.dirty = true; 275 } 276 277 /** 278 * Check if function icons are in use. 279 * 280 * @return user preference to use function icons. 281 */ 282 public boolean isUsingFunctionIcon() { 283 return _useFunctionIcon; 284 } 285 286 public void setUsingFunctionIcon(boolean useFunctionIcon) { 287 _useFunctionIcon = useFunctionIcon; 288 this.dirty = true; 289 } 290 291 public boolean isResizingWindow() { 292 return _resizeWinImg; 293 } 294 295 public void setResizeWindow(boolean winImg) { 296 _resizeWinImg = winImg; 297 this.dirty = true; 298 } 299 300 public boolean isUsingRosterImage() { 301 return _useRosterImage; 302 } 303 304 public void setUseRosterImage(boolean rosterImage) { 305 _useRosterImage = rosterImage; 306 this.dirty = true; 307 } 308 309 public boolean isEnablingRosterSearch() { 310 return _enableRosterSearch; 311 } 312 313 public void setEnableRosterSearch(boolean b) { 314 _enableRosterSearch = b; 315 this.dirty = true; 316 } 317 318 public void setAutoLoad(boolean b) { 319 _enableAutoLoad = b; 320 this.dirty = true; 321 } 322 323 public boolean isAutoLoading() { 324 return _enableAutoLoad; 325 } 326 327 public void setHideUndefinedFuncButt(boolean b) { 328 _hideUndefinedFunButton = b; 329 this.dirty = true; 330 } 331 332 public boolean isHidingUndefinedFuncButt() { 333 return _hideUndefinedFunButton; 334 } 335 336 public void setIgnoreThrottlePosition(boolean b) { 337 _ignoreThrottlePosition = b; 338 this.dirty = true; 339 } 340 341 public boolean isIgnoringThrottlePosition() { 342 return _ignoreThrottlePosition; 343 } 344 345 public void setSaveThrottleOnLayoutSave(boolean b) { 346 _saveThrottleOnLayoutSave = b; 347 this.dirty = true; 348 } 349 350 public boolean isSavingThrottleOnLayoutSave() { 351 return _saveThrottleOnLayoutSave; 352 } 353 354 public boolean isSilentSteal() { 355 return _isSilentSteal; 356 } 357 358 public boolean isSilentShare() { 359 return _isSilentShare; 360 } 361 362 public void setSilentSteal(boolean b) { 363 _isSilentSteal = b; 364 this.dirty = true; 365 } 366 367 public void setSilentShare(boolean b) { 368 _isSilentShare = b; 369 this.dirty = true; 370 } 371 372 373 public void setUseLargeSpeedSlider(boolean b) { 374 _useLargeSpeedSlider = b; 375 this.dirty = true; 376 } 377 378 public boolean isUsingLargeSpeedSlider() { 379 return _useLargeSpeedSlider; 380 } 381 382 public void setDefaultThrottleFilePath(String p) { 383 _defaultThrottleFilePath = p; 384 this.dirty = true; 385 } 386 387 public String getDefaultThrottleFilePath() { 388 return _defaultThrottleFilePath; 389 } 390 391 public boolean isHidingSpeedStepSelector() { 392 return _hideSpeedStepSelector; 393 } 394 395 public void setHideSpeedStepSelector(boolean b) { 396 _hideSpeedStepSelector = b; 397 this.dirty = true; 398 } 399 400 public boolean isAddressSelectorShowingAllRosterGroup() { 401 return _isAddressSelectorShowingAllRosterGroup; 402 } 403 404 public void setAddressSelectorShowingAllRosterGroup(boolean b) { 405 _isAddressSelectorShowingAllRosterGroup = b; 406 this.dirty = true; 407 } 408 409 /** 410 * @return the throttles keyboard controls preferences 411 */ 412 public ThrottlesPreferencesWindowKeyboardControls getThrottlesKeyboardControls() { 413 return _tpwkc; 414 } 415 416 /** 417 * Set the throttles keyboard controls preferences 418 * @param tpwkc the new keyboard preferences 419 */ 420 public void setThrottlesKeyboardControls(ThrottlesPreferencesWindowKeyboardControls tpwkc) { 421 _tpwkc = tpwkc; 422 } 423 424 /** 425 * Add a PropertyChangeListener. 426 * AddressListeners are notified when the throtlle preferences are updated 427 * @param l listener to add. 428 * 429 */ 430 public void addPropertyChangeListener(PropertyChangeListener l) { 431 if (listeners == null) { 432 listeners = new ArrayList<>(2); 433 } 434 if (!listeners.contains(l)) { 435 listeners.add(l); 436 } 437 } 438 439 /** 440 * Remove a PropertyChangeListener. 441 * @param l listener to remove. 442 */ 443 public void removePropertyChangeListener(PropertyChangeListener l) { 444 if (listeners == null) { 445 return; 446 } 447 listeners.remove(l); 448 } 449 450 private static final Logger log = LoggerFactory.getLogger(ThrottlesPreferences.class); 451}