001package jmri.jmrit.display.layoutEditor.configurexml;
002
003import java.awt.Color;
004import java.util.List;
005
006import javax.swing.JFrame;
007
008import jmri.ConfigureManager;
009import jmri.InstanceManager;
010import jmri.configurexml.AbstractXmlAdapter;
011import jmri.configurexml.XmlAdapter;
012import jmri.jmrit.dispatcher.DispatcherFrame;
013import jmri.jmrit.display.EditorManager;
014import jmri.jmrit.display.Positionable;
015import jmri.jmrit.display.layoutEditor.*;
016import jmri.util.ColorUtil;
017import jmri.util.swing.JmriJOptionPane;
018
019import org.jdom2.*;
020
021/**
022 * Handle configuration for LayoutEditor panes.
023 * <p>
024 * Based in part on PanelEditorXml.java
025 *
026 * @author Dave Duchamp Copyright (c) 2007
027 * @author George Warner Copyright (c) 2017-2018
028 */
029public class LayoutEditorXml extends AbstractXmlAdapter {
030
031    public LayoutEditorXml() {
032    }
033
034    /**
035     * Default implementation for storing the contents of a LayoutEditor.
036     *
037     * @param o Object to store, of type LayoutEditor
038     * @return Element containing the complete info
039     */
040    @Override
041    public Element store(Object o) {
042        LayoutEditor p = (LayoutEditor) o;
043
044        Element panel = new Element("LayoutEditor");
045
046        panel.setAttribute("class", getClass().getName());
047        panel.setAttribute("name", p.getLayoutName());
048        if (InstanceManager.getDefault(jmri.util.gui.GuiLafPreferencesManager.class).isEditorUseOldLocSize()) {
049            panel.setAttribute("x", "" + p.gContext.getUpperLeftX());
050            panel.setAttribute("y", "" + p.gContext.getUpperLeftY());
051            panel.setAttribute("windowheight", "" + p.gContext.getWindowHeight());
052            panel.setAttribute("windowwidth", "" + p.gContext.getWindowWidth());
053        } else {
054            // Use real location and size
055            java.awt.Point loc = p.getLocation();
056            panel.setAttribute("x", "" + loc.x);
057            panel.setAttribute("y", "" + loc.y);
058
059            java.awt.Dimension size = p.getSize();
060            panel.setAttribute("windowheight", "" + size.height);
061            panel.setAttribute("windowwidth", "" + size.width);
062        }
063        panel.setAttribute("panelheight", "" + p.gContext.getLayoutHeight());
064        panel.setAttribute("panelwidth", "" + p.gContext.getLayoutWidth());
065        panel.setAttribute("sliders", "" + (p.getScroll() ? "yes" : "no")); // deprecated
066        panel.setAttribute("scrollable", "" + p.getScrollable());
067        panel.setAttribute("editable", "" + (p.isEditable() ? "yes" : "no"));
068        panel.setAttribute("positionable", "" + (p.allPositionable() ? "yes" : "no"));
069        panel.setAttribute("controlling", "" + (p.allControlling() ? "yes" : "no"));
070        panel.setAttribute("animating", "" + (p.isAnimating() ? "yes" : "no"));
071        panel.setAttribute("showhelpbar", "" + (p.getShowHelpBar() ? "yes" : "no"));
072        panel.setAttribute("drawgrid", "" + (p.getDrawGrid() ? "yes" : "no"));
073        panel.setAttribute("snaponadd", "" + (p.getSnapOnAdd() ? "yes" : "no"));
074        panel.setAttribute("snaponmove", "" + (p.getSnapOnMove() ? "yes" : "no"));
075        panel.setAttribute("antialiasing", "" + (p.getAntialiasingOn() ? "yes" : "no"));
076        panel.setAttribute("turnoutcircles", "" + (p.getTurnoutCircles() ? "yes" : "no"));
077        panel.setAttribute("tooltipsnotedit", "" + (p.getTooltipsNotEdit() ? "yes" : "no"));
078        panel.setAttribute("tooltipsinedit", "" + (p.getTooltipsInEdit() ? "yes" : "no"));
079        panel.setAttribute("mainlinetrackwidth", "" + p.gContext.getMainlineBlockWidth());  //saves wrong value for backwards compatability with pre-LayoutTrackDrawingOptions
080        panel.setAttribute("xscale", Float.toString((float) p.gContext.getXScale()));
081        panel.setAttribute("yscale", Float.toString((float) p.gContext.getYScale()));
082        panel.setAttribute("sidetrackwidth", "" + p.gContext.getSidelineBlockWidth());  //saves wrong value for backwards compatability with pre-LayoutTrackDrawingOptions
083        panel.setAttribute("defaulttrackcolor", p.getDefaultTrackColor());
084        panel.setAttribute("defaultoccupiedtrackcolor", p.getDefaultOccupiedTrackColor());
085        panel.setAttribute("defaultalternativetrackcolor", p.getDefaultAlternativeTrackColor());
086        panel.setAttribute("defaulttextcolor", p.getDefaultTextColor());
087        String turnoutCircleColor = p.getTurnoutCircleColor();
088        panel.setAttribute("turnoutcirclecolor", turnoutCircleColor);
089        String turnoutCircleThrownColor = p.getTurnoutCircleThrownColor();
090        // optional attributes
091        if (!turnoutCircleColor.equals(turnoutCircleThrownColor)) {
092            panel.setAttribute("turnoutcirclethrowncolor", turnoutCircleThrownColor);
093        }
094        if (p.isTurnoutFillControlCircles()) {
095            panel.setAttribute("turnoutfillcontrolcircles", "yes");
096        }
097
098        panel.setAttribute("turnoutcirclesize", "" + p.getTurnoutCircleSize());
099        panel.setAttribute("turnoutdrawunselectedleg", (p.isTurnoutDrawUnselectedLeg() ? "yes" : "no"));
100        panel.setAttribute("turnoutbx", Float.toString((float) p.getTurnoutBX()));
101        panel.setAttribute("turnoutcx", Float.toString((float) p.getTurnoutCX()));
102        panel.setAttribute("turnoutwid", Float.toString((float) p.getTurnoutWid()));
103        panel.setAttribute("xoverlong", Float.toString((float) p.getXOverLong()));
104        panel.setAttribute("xoverhwid", Float.toString((float) p.getXOverHWid()));
105        panel.setAttribute("xovershort", Float.toString((float) p.getXOverShort()));
106        panel.setAttribute("autoblkgenerate", "" + (p.getAutoBlockAssignment() ? "yes" : "no"));
107        if (p.getBackgroundColor() != null) {
108            panel.setAttribute("redBackground", "" + p.getBackgroundColor().getRed());
109            panel.setAttribute("greenBackground", "" + p.getBackgroundColor().getGreen());
110            panel.setAttribute("blueBackground", "" + p.getBackgroundColor().getBlue());
111        }
112        panel.setAttribute("gridSize", "" + p.gContext.getGridSize());
113        panel.setAttribute("gridSize2nd", "" + p.gContext.getGridSize2nd());
114
115        p.resetDirty();
116        panel.setAttribute("openDispatcher", p.getOpenDispatcherOnLoad() ? "yes" : "no");
117        panel.setAttribute("useDirectTurnoutControl", p.getDirectTurnoutControl() ? "yes" : "no");
118
119        // store layout track drawing options
120        try {
121            LayoutTrackDrawingOptions ltdo = p.getLayoutTrackDrawingOptions();
122            Element e = jmri.configurexml.ConfigXmlManager.elementFromObject(ltdo);
123            if (e != null) {
124                panel.addContent(e);
125            }
126        } catch (Exception e) {
127            log.error("Error storing contents element: ", e);
128        }
129
130        // note: moving zoom attribute into per-window user preference
131        //panel.setAttribute("zoom", Double.toString(p.getZoom()));
132        int num;
133
134        // include contents (Icons and Labels)
135        List<Positionable> contents = p.getContents();
136        for (Positionable sub : contents) {
137            if (sub != null && sub.storeItem()) {
138                try {
139                    Element e = jmri.configurexml.ConfigXmlManager.elementFromObject(sub);
140                    if (e != null) {
141                        panel.addContent(e);
142                    }
143                } catch (Exception e) {
144                    log.error("Error storing contents element: ", e);
145                }
146            } else {
147                log.warn("Null entry found when storing panel contents.");
148            }
149        }
150
151        // include LayoutTracks
152        List<LayoutTrack> layoutTracks = p.getLayoutTracks();
153        num = layoutTracks.size();
154        if (log.isDebugEnabled()) {
155            log.debug("N LayoutTrack elements: {}", num);
156        }
157
158
159
160        // Previous write order was
161        //   LayoutTurnout) && !(item instanceof LayoutSlip)
162        //   TrackSegment
163        //   PositionablePoint
164        //   LevelXing
165        //   LayoutSlip
166        //   LayoutTurntable
167
168        // write order specified for compatibility
169        for (LayoutTrackView lv : p.getLayoutTurnoutViews()) {
170            if (! (lv instanceof LayoutSlipView) )
171                storeOne(panel, lv);
172        }
173        for (LayoutTrackView lv : p.getTrackSegmentViews())         {storeOne(panel, lv); }
174        for (LayoutTrackView lv : p.getPositionablePointViews())    {storeOne(panel, lv); }
175        for (LayoutTrackView lv : p.getLevelXingViews())            {storeOne(panel, lv); }
176        for (LayoutTrackView lv : p.getLayoutSlipViews())           {storeOne(panel, lv); }
177        for (LayoutTrackView lv : p.getLayoutTurntableViews())      {storeOne(panel, lv); }
178
179        // include Layout Shapes
180        for (LayoutShape ls : p.getLayoutShapes()) {storeOne(panel, ls); }
181
182        return panel;
183    }   // store
184
185
186    private void storeOne(Element panel, Object item) {
187        try {
188            Element e = jmri.configurexml.ConfigXmlManager.elementFromObject(item);
189            if (e != null) {
190                panel.addContent(e);
191            }
192        } catch (Exception ex) {
193            log.error("Error storing layout item: {}", item, ex);
194        }
195    }
196
197    @Override
198    public void load(Element element, Object o) {
199        log.error("Invalid method called");
200    }
201
202    /**
203     * Create a LayoutEditor object, then register and fill it, then pop it in a
204     * JFrame
205     *
206     * @param shared Top level Element to unpack.
207     */
208    @Override
209    public boolean load(Element shared, Element perNode) {
210        if (java.awt.GraphicsEnvironment.isHeadless()) {
211            return true;
212        }
213
214        boolean result = true;
215        Attribute a;
216        // find coordinates
217        int x = 0;
218        int y = 0;
219        // From this version onwards separate sizes for window and panel are used
220        int windowHeight = 400;
221        int windowWidth = 300;
222        int panelHeight = 340;
223        int panelWidth = 280;
224        int sidetrackwidth = 3;
225        int mainlinetrackwidth = 3;
226        try {
227            if ((a = shared.getAttribute("x")) != null) {
228                x = a.getIntValue();
229            }
230            if ((a = shared.getAttribute("y")) != null) {
231                y = a.getIntValue();
232            }
233
234            // For compatibility with previous versions, try and
235            // see if height and width tags are contained in the file
236            if ((a = shared.getAttribute("height")) != null) {
237                windowHeight = a.getIntValue();
238                panelHeight = windowHeight - 60;
239            }
240            if ((a = shared.getAttribute("width")) != null) {
241                windowWidth = a.getIntValue();
242                panelWidth = windowWidth - 18;
243            }
244
245            // For files created by the new version,
246            // retrieve window and panel sizes
247            if ((a = shared.getAttribute("windowheight")) != null) {
248                windowHeight = a.getIntValue();
249            }
250            if ((a = shared.getAttribute("windowwidth")) != null) {
251                windowWidth = a.getIntValue();
252            }
253            if ((a = shared.getAttribute("panelheight")) != null) {
254                panelHeight = a.getIntValue();
255            }
256            if ((a = shared.getAttribute("panelwidth")) != null) {
257                panelWidth = a.getIntValue();
258            }
259
260            mainlinetrackwidth = shared.getAttribute("mainlinetrackwidth").getIntValue();
261            sidetrackwidth = shared.getAttribute("sidetrackwidth").getIntValue();
262        } catch (DataConversionException e) {
263            log.error("failed to convert LayoutEditor attribute");
264            result = false;
265        }
266
267        double xScale = 1.0;
268        double yScale = 1.0;
269        if ((a = shared.getAttribute("xscale")) != null) {
270            try {
271                xScale = (Float.parseFloat(a.getValue()));
272            } catch (NumberFormatException e) {
273                log.error("failed to convert xscale attribute to float - {}", a.getValue());
274                result = false;
275            }
276        }
277        if ((a = shared.getAttribute("yscale")) != null) {
278            try {
279                yScale = (Float.parseFloat(a.getValue()));
280            } catch (NumberFormatException e) {
281                log.error("failed to convert yscale attribute to float - {}", a.getValue());
282                result = false;
283            }
284        }
285
286        // find the name
287        String name = "";
288        if ((a = shared.getAttribute("name")) != null) {
289            name = a.getValue();
290        }
291        if (InstanceManager.getDefault(EditorManager.class).contains(name)) {
292            JFrame frame = new JFrame("DialogDemo");
293            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
294            log.warn("File contains a panel with the same name ({}) as an existing panel", name);
295            int n = JmriJOptionPane.showConfirmDialog(frame,
296                    Bundle.getMessage("DuplicatePanel", name),
297                    Bundle.getMessage("DuplicatePanelTitle"),
298                    JmriJOptionPane.YES_NO_OPTION);
299            if (n != JmriJOptionPane.YES_OPTION ) {
300                return false;
301            }
302        }
303
304        // If available, override location and size with machine dependent values
305        if (!InstanceManager.getDefault(jmri.util.gui.GuiLafPreferencesManager.class).isEditorUseOldLocSize()) {
306            jmri.UserPreferencesManager prefsMgr = InstanceManager.getNullableDefault(jmri.UserPreferencesManager.class);
307            if (prefsMgr != null) {
308                String windowFrameRef = "jmri.jmrit.display.layoutEditor.LayoutEditor:" + name;
309
310                java.awt.Point prefsWindowLocation = prefsMgr.getWindowLocation(windowFrameRef);
311                if (prefsWindowLocation != null) {
312                    x = (int) prefsWindowLocation.getX();
313                    y = (int) prefsWindowLocation.getY();
314                }
315
316                java.awt.Dimension prefsWindowSize = prefsMgr.getWindowSize(windowFrameRef);
317                if (prefsWindowSize != null && prefsWindowSize.getHeight() != 0 && prefsWindowSize.getWidth() != 0) {
318                    windowHeight = (int) prefsWindowSize.getHeight();
319                    windowWidth = (int) prefsWindowSize.getWidth();
320                }
321            }
322        }
323
324        LayoutEditor panel = new LayoutEditor(name);
325        panel.setLayoutName(name);
326        InstanceManager.getDefault(EditorManager.class).add(panel);
327
328        // create the objects
329        panel.gContext.setMainlineTrackWidth(mainlinetrackwidth);
330        panel.gContext.setSidelineTrackWidth(sidetrackwidth);
331        panel.gContext.setXScale(xScale);
332        panel.gContext.setYScale(yScale);
333
334        String color = ColorUtil.ColorDarkGray;
335        try {
336            if ((a = shared.getAttribute("defaulttrackcolor")) != null) {
337                color = a.getValue();
338            }
339            panel.setDefaultTrackColor(ColorUtil.stringToColor(color));
340        } catch (IllegalArgumentException e) {
341            panel.setDefaultTrackColor(Color.BLACK);
342            log.error("Invalid defaulttrackcolor {}; using black", color);
343        }
344
345        color = ColorUtil.ColorBlack;
346        try {
347            if ((a = shared.getAttribute("defaulttextcolor")) != null) {
348                color = a.getValue();
349            }
350            panel.setDefaultTextColor(ColorUtil.stringToColor(color));
351        } catch (IllegalArgumentException e) {
352            panel.setDefaultTextColor(Color.BLACK);
353            log.error("Invalid defaulttextcolor {}; using black", color);
354        }
355
356        color = "track";  //default to using use default track color for circle color
357        try {
358            if ((a = shared.getAttribute("turnoutcirclecolor")) != null) {
359                color = a.getValue();
360            }
361            panel.setTurnoutCircleColor(ColorUtil.stringToColor(color));
362        } catch (IllegalArgumentException e) {
363            panel.setTurnoutCircleColor(Color.BLACK);
364            log.error("Invalid color {}; using black", color);
365        }
366
367        // default to using turnout circle color just set
368        try {
369            if ((a = shared.getAttribute("turnoutcirclethrowncolor")) != null) {
370                color = a.getValue();
371            }
372            panel.setTurnoutCircleThrownColor(ColorUtil.stringToColor(color));
373        } catch (IllegalArgumentException e) {
374            panel.setTurnoutCircleThrownColor(Color.BLACK);
375            log.error("Invalid color {}; using black", color);
376        }
377
378        try {   // the "turnoutfillcontrolcircles" attribute has a default="no" value in the schema;
379            // it will always return a "no" attribute if the attribute is not present.
380            panel.setTurnoutFillControlCircles(shared.getAttribute("turnoutfillcontrolcircles").getBooleanValue());
381        } catch (DataConversionException e) {
382            log.warn("unable to convert turnoutfillcontrolcircles attribute");
383        } catch (NullPointerException e) {  // considered normal if the attribute is not present
384            log.debug("missing turnoutfillcontrolcircles attribute");
385        }
386
387        if ((a = shared.getAttribute("turnoutcirclesize")) != null) {
388            try {
389                panel.setTurnoutCircleSize(a.getIntValue());
390            } catch (DataConversionException e) {
391                log.warn("unable to convert turnoutcirclesize");
392            }
393        }
394
395        try {
396            panel.setTurnoutDrawUnselectedLeg(shared.getAttribute("turnoutdrawunselectedleg").getBooleanValue());
397        } catch (DataConversionException e) {
398            log.warn("unable to convert turnoutdrawunselectedleg attribute");
399        } catch (NullPointerException e) {  // considered normal if the attribute is not present
400            log.debug("missing turnoutdrawunselectedleg attribute");
401        }
402
403        // turnout size parameters
404        if ((a = shared.getAttribute("turnoutbx")) != null) {
405            try {
406                panel.setTurnoutBX(Float.parseFloat(a.getValue()));
407            } catch (NumberFormatException e) {
408                log.error("failed to convert turnoutbx to float - {}", a.getValue());
409                result = false;
410            }
411        }
412
413        if ((a = shared.getAttribute("turnoutcx")) != null) {
414            try {
415                panel.setTurnoutCX(Float.parseFloat(a.getValue()));
416            } catch (NumberFormatException e) {
417                log.error("failed to convert turnoutcx to float - {}", a.getValue());
418                result = false;
419            }
420        }
421
422        if ((a = shared.getAttribute("turnoutwid")) != null) {
423            try {
424                panel.setTurnoutWid(Float.parseFloat(a.getValue()));
425            } catch (NumberFormatException e) {
426                log.error("failed to convert turnoutwid to float - {}", a.getValue());
427                result = false;
428            }
429        }
430
431        if ((a = shared.getAttribute("xoverlong")) != null) {
432            try {
433                panel.setXOverLong(Float.parseFloat(a.getValue()));
434            } catch (NumberFormatException e) {
435                log.error("failed to convert xoverlong to float - {}", a.getValue());
436                result = false;
437            }
438        }
439        if ((a = shared.getAttribute("xoverhwid")) != null) {
440            try {
441                panel.setXOverHWid(Float.parseFloat(a.getValue()));
442            } catch (NumberFormatException e) {
443                log.error("failed to convert xoverhwid to float - {}", a.getValue());
444                result = false;
445            }
446        }
447        if ((a = shared.getAttribute("xovershort")) != null) {
448            try {
449                panel.setXOverShort(Float.parseFloat(a.getValue()));
450            } catch (NumberFormatException e) {
451                log.error("failed to convert xovershort to float - {}", a.getValue());
452                result = false;
453            }
454        }
455        // grid size parameter
456        if ((a = shared.getAttribute("gridSize")) != null) {
457            try {
458                panel.gContext.setGridSize(Integer.parseInt(a.getValue()));
459            } catch (NumberFormatException e) {
460                log.error("failed to convert gridSize to int - {}", a.getValue());
461                result = false;
462            }
463        }
464
465        // second grid size parameter
466        if ((a = shared.getAttribute("gridSize2nd")) != null) {
467            try {
468                panel.gContext.setGridSize2nd(Integer.parseInt(a.getValue()));
469            } catch (NumberFormatException e) {
470                log.error("failed to convert gridSize2nd to int - {}", a.getValue());
471                result = false;
472            }
473        }
474
475        try {
476            panel.setAllPositionable(shared.getAttribute("positionable").getBooleanValue());
477        } catch (DataConversionException e) {
478            log.warn("unable to convert positionable attribute");
479        } catch (NullPointerException e) {  // considered normal if the attribute is not present
480            log.debug("missing positionable attribute");
481
482        }
483
484        try {
485            panel.setAllControlling(shared.getAttribute("controlling").getBooleanValue());
486        } catch (DataConversionException e) {
487            log.warn("unable to convert controlling attribute");
488        } catch (NullPointerException e) {  // considered normal if the attribute is not present
489            log.debug("missing controlling attribute");
490        }
491
492        try {
493            panel.setTurnoutAnimation(shared.getAttribute("animating").getBooleanValue());
494        } catch (DataConversionException e) {
495            log.warn("unable to convert animating attribute");
496        } catch (NullPointerException e) {  // considered normal if the attribute is not present
497            log.debug("missing animating attribute");
498        }
499
500        try {
501            panel.setDrawGrid(shared.getAttribute("drawgrid").getBooleanValue());
502        } catch (DataConversionException e) {
503            log.warn("unable to convert drawgrid attribute");
504        } catch (NullPointerException e) {  // considered normal if the attribute is not present
505            log.debug("missing drawgrid attribute");
506        }
507
508        try {
509            panel.setSnapOnAdd(shared.getAttribute("snaponadd").getBooleanValue());
510        } catch (DataConversionException e) {
511            log.warn("unable to convert snaponadd attribute");
512        } catch (NullPointerException e) {  // considered normal if the attribute is not present
513            log.debug("missing snaponadd attribute");
514        }
515
516        try {
517            panel.setSnapOnMove(shared.getAttribute("snaponmove").getBooleanValue());
518        } catch (DataConversionException e) {
519            log.warn("unable to convert snaponmove attribute");
520        } catch (NullPointerException e) {  // considered normal if the attribute is not present
521            log.debug("missing snaponmove attribute");
522        }
523
524        try {
525            panel.setTurnoutCircles(shared.getAttribute("turnoutcircles").getBooleanValue());
526        } catch (DataConversionException e) {
527            log.warn("unable to convert turnoutcircles attribute");
528        } catch (NullPointerException e) {  // considered normal if the attribute is not present
529            log.debug("missing turnoutcircles attribute");
530        }
531
532        try {
533            panel.setTooltipsNotEdit(shared.getAttribute("tooltipsnotedit").getBooleanValue());
534        } catch (DataConversionException e) {
535            log.warn("unable to convert tooltipsnotedit attribute");
536        } catch (NullPointerException e) {  // considered normal if the attribute is not present
537            log.debug("missing tooltipsnotedit attribute");
538        }
539
540        try {
541            panel.setAutoBlockAssignment(shared.getAttribute("autoblkgenerate").getBooleanValue());
542        } catch (DataConversionException e) {
543            log.warn("unable to convert autoblkgenerate attribute");
544        } catch (NullPointerException e) {  // considered normal if the attribute is not present
545            log.debug("missing autoblkgenerate attribute");
546        }
547
548        try {
549            panel.setTooltipsInEdit(shared.getAttribute("tooltipsinedit").getBooleanValue());
550        } catch (DataConversionException e) {
551            log.warn("unable to convert tooltipsinedit attribute");
552        } catch (NullPointerException e) {  // considered normal if the attribute is not present
553            log.debug("missing tooltipsinedit attribute");
554        }
555
556        // set default track color
557        if ((a = shared.getAttribute("defaulttrackcolor")) != null) {
558            try {
559                panel.setDefaultTrackColor(ColorUtil.stringToColor(a.getValue()));
560            } catch (IllegalArgumentException e) {
561                panel.setDefaultTrackColor(Color.darkGray);
562                log.error("Invalid defaulttrackcolor {}; using 'darkGray'", a.getValue());
563            }
564        }
565        // set default occupied track color
566        if ((a = shared.getAttribute("defaultoccupiedtrackcolor")) != null) {
567            try {
568                panel.setDefaultOccupiedTrackColor(ColorUtil.stringToColor(a.getValue()));
569            } catch (IllegalArgumentException e) {
570                panel.setDefaultOccupiedTrackColor(Color.red);
571                log.error("Invalid defaultoccupiedtrackcolor {}; using 'red'", a.getValue());
572            }
573        }
574        // set default alternative track color
575        if ((a = shared.getAttribute("defaultalternativetrackcolor")) != null) {
576            try {
577                panel.setDefaultAlternativeTrackColor(ColorUtil.stringToColor(a.getValue()));
578            } catch (IllegalArgumentException e) {
579                panel.setDefaultAlternativeTrackColor(Color.white);
580                log.error("Invalid defaultalternativetrackcolor {}; using 'white'", a.getValue());
581            }
582        }
583        try {
584            int red = shared.getAttribute("redBackground").getIntValue();
585            int blue = shared.getAttribute("blueBackground").getIntValue();
586            int green = shared.getAttribute("greenBackground").getIntValue();
587            Color backgroundColor = new Color(red, green, blue);
588            panel.setDefaultBackgroundColor(backgroundColor);
589            panel.setBackgroundColor(backgroundColor);
590        } catch (DataConversionException e) {
591            log.warn("Could not parse color attributes!");
592        } catch (NullPointerException e) {  // considered normal if the attributes are not present
593            log.debug("missing backbround color attributes");
594        }
595
596        try {
597            panel.setDirectTurnoutControl(shared.getAttribute("useDirectTurnoutControl").getBooleanValue());
598        } catch (DataConversionException e) {
599            log.warn("unable to convert Layout Editor useDirectTurnoutControl attribute");
600        } catch (NullPointerException e) {  // considered normal if the attribute is not present
601            log.debug("missing useDirectTurnoutControl attribute");
602        }
603
604        // Set editor's option flags, load content after
605        // this so that individual item flags are set as saved
606        panel.initView();
607
608        // load the contents
609        for (Element item : shared.getChildren()) {
610            // get the class, hence the adapter object to do loading
611            String adapterName = item.getAttribute("class").getValue();
612            adapterName = jmri.configurexml.ConfigXmlManager.currentClassName(adapterName);
613
614            if (log.isDebugEnabled()) {
615                String id = "<null>";
616                try {
617                    id = item.getAttribute("name").getValue();
618                    log.debug("Load {} for [{}] via {}", id, panel.getName(), adapterName);
619                } catch (NullPointerException e) {
620                    log.debug("Load layout object for [{}] via {}", panel.getName(), adapterName);
621                    log.debug("Load layout object for [{}] via {}", panel.getName(), adapterName);
622                } catch (RuntimeException e) {
623                    throw e;
624                } catch (Exception e) {
625                }
626            }
627            try {
628                // get the class name, including migrations
629                adapterName = jmri.configurexml.ConfigXmlManager.currentClassName(adapterName);
630                // get the adapter object
631                XmlAdapter adapter = (XmlAdapter) Class.forName(adapterName).getDeclaredConstructor().newInstance();
632                // and load with it
633                adapter.load(item, panel);
634                if (!panel.loadOK()) {
635                    result = false;
636                }
637            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException
638                    | jmri.configurexml.JmriConfigureXmlException
639                    | java.lang.reflect.InvocationTargetException e) {
640                log.error("Exception while loading {}", item.getName(), e);
641                result = false;
642            }
643        }
644        panel.disposeLoadData();     // dispose of url correction data
645
646        // final initialization of objects
647        panel.setConnections();
648
649        // display the results
650        try {
651            // set first since other attribute use this setting
652            panel.setAllEditable(shared.getAttribute("editable").getBooleanValue());
653        } catch (DataConversionException e) {
654            log.warn("unable to convert editable attribute");
655        } catch (NullPointerException e) {  // considered normal if the attribute is not present
656            log.debug("missing editable attribute");
657        }
658
659        try {
660            panel.setShowHelpBar(shared.getAttribute("showhelpbar").getBooleanValue());
661        } catch (DataConversionException e) {
662            log.warn("unable to convert showhelpbar attribute");
663        } catch (NullPointerException e) {  // considered normal if the attribute is not present
664            log.debug("missing showhelpbar attribute");
665        }
666
667        try {
668            panel.setAntialiasingOn(shared.getAttribute("antialiasing").getBooleanValue());
669        } catch (DataConversionException e) {
670            log.warn("unable to convert antialiasing attribute");
671        } catch (NullPointerException e) {  // considered normal if the attribute is not present
672            log.debug("missing antialiasing attribute");
673        }
674
675        // set contents state
676        String slValue = "both";
677        try {
678            boolean value = shared.getAttribute("sliders").getBooleanValue();
679            slValue = value ? "both" : "none";
680        } catch (DataConversionException e) {
681            log.warn("unable to convert sliders attribute");
682        } catch (NullPointerException e) {  // considered normal if the attribute is not present
683            log.debug("missing sliders attribute");
684        }
685        if ((a = shared.getAttribute("scrollable")) != null) {
686            slValue = a.getValue();
687        }
688        panel.setScroll(slValue);
689
690        panel.pack();
691        panel.setLayoutDimensions(windowWidth, windowHeight, x, y, panelWidth, panelHeight);
692        panel.setVisible(true);    // always show the panel
693        panel.resetDirty();
694
695        // register the resulting panel for later configuration
696        ConfigureManager cm = InstanceManager.getNullableDefault(jmri.ConfigureManager.class);
697        if (cm != null) {
698            cm.registerUser(panel);
699        }
700        //open Dispatcher frame if any Transits are defined, and open Dispatcher flag set on
701        if (jmri.InstanceManager.getDefault(jmri.TransitManager.class).getNamedBeanSet().size() > 0) {
702            try {
703                boolean value = shared.getAttribute("openDispatcher").getBooleanValue();
704                panel.setOpenDispatcherOnLoad(value);
705                if (value) {
706                    DispatcherFrame df = InstanceManager.getDefault(DispatcherFrame.class);
707                    df.loadAtStartup();
708                }
709            } catch (DataConversionException e) {
710                log.warn("unable to convert openDispatcher attribute");
711            } catch (NullPointerException e) {  // considered normal if the attribute is not present
712                log.debug("missing openDispatcher attribute");
713            }
714        }
715        return result;
716    }   // load
717
718    @Override
719    public int loadOrder() {
720        return jmri.Manager.PANELFILES;
721    }
722
723    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LayoutEditorXml.class);
724
725}