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        if (p.isHighlightCursor()) {
119            panel.setAttribute("highlightCursor", "yes");
120        }
121
122        // store layout track drawing options
123        try {
124            LayoutTrackDrawingOptions ltdo = p.getLayoutTrackDrawingOptions();
125            Element e = jmri.configurexml.ConfigXmlManager.elementFromObject(ltdo);
126            if (e != null) {
127                panel.addContent(e);
128            }
129        } catch (Exception e) {
130            log.error("Error storing contents element: ", e);
131        }
132
133        // note: moving zoom attribute into per-window user preference
134        //panel.setAttribute("zoom", Double.toString(p.getZoom()));
135        int num;
136
137        // include contents (Icons and Labels)
138        List<Positionable> contents = p.getContents();
139        for (Positionable sub : contents) {
140            if (sub != null && sub.storeItem()) {
141                try {
142                    Element e = jmri.configurexml.ConfigXmlManager.elementFromObject(sub);
143                    if (e != null) {
144                        panel.addContent(e);
145                    }
146                } catch (Exception e) {
147                    log.error("Error storing contents element: ", e);
148                }
149            } else {
150                log.warn("Null entry found when storing panel contents.");
151            }
152        }
153
154        // include LayoutTracks
155        List<LayoutTrack> layoutTracks = p.getLayoutTracks();
156        num = layoutTracks.size();
157        if (log.isDebugEnabled()) {
158            log.debug("N LayoutTrack elements: {}", num);
159        }
160
161
162
163        // Previous write order was
164        //   LayoutTurnout) && !(item instanceof LayoutSlip)
165        //   TrackSegment
166        //   PositionablePoint
167        //   LevelXing
168        //   LayoutSlip
169        //   LayoutTurntable
170
171        // write order specified for compatibility
172        for (LayoutTrackView lv : p.getLayoutTurnoutViews()) {
173            if (! (lv instanceof LayoutSlipView) )
174                storeOne(panel, lv);
175        }
176        for (LayoutTrackView lv : p.getTrackSegmentViews())         {storeOne(panel, lv); }
177        for (LayoutTrackView lv : p.getPositionablePointViews())    {storeOne(panel, lv); }
178        for (LayoutTrackView lv : p.getLevelXingViews())            {storeOne(panel, lv); }
179        for (LayoutTrackView lv : p.getLayoutSlipViews())           {storeOne(panel, lv); }
180        for (LayoutTrackView lv : p.getLayoutTurntableViews())      {storeOne(panel, lv); }
181        for (LayoutTrackView lv : p.getLayoutTraverserViews())      {storeOne(panel, lv); }
182
183        // include Layout Shapes
184        for (LayoutShape ls : p.getLayoutShapes()) {storeOne(panel, ls); }
185
186        return panel;
187    }   // store
188
189
190    private void storeOne(Element panel, Object item) {
191        try {
192            Element e = jmri.configurexml.ConfigXmlManager.elementFromObject(item);
193            if (e != null) {
194                panel.addContent(e);
195            }
196        } catch (Exception ex) {
197            log.error("Error storing layout item: {}", item, ex);
198        }
199    }
200
201    @Override
202    public void load(Element element, Object o) {
203        log.error("Invalid method called");
204    }
205
206    /**
207     * Create a LayoutEditor object, then register and fill it, then pop it in a
208     * JFrame
209     *
210     * @param shared Top level Element to unpack.
211     */
212    @Override
213    public boolean load(Element shared, Element perNode) {
214        if (java.awt.GraphicsEnvironment.isHeadless()) {
215            return true;
216        }
217
218        boolean result = true;
219        Attribute a;
220        // find coordinates
221        int x = 0;
222        int y = 0;
223        // From this version onwards separate sizes for window and panel are used
224        int windowHeight = 400;
225        int windowWidth = 300;
226        int panelHeight = 340;
227        int panelWidth = 280;
228        int sidetrackwidth = 3;
229        int mainlinetrackwidth = 3;
230        try {
231            if ((a = shared.getAttribute("x")) != null) {
232                x = a.getIntValue();
233            }
234            if ((a = shared.getAttribute("y")) != null) {
235                y = a.getIntValue();
236            }
237
238            // For compatibility with previous versions, try and
239            // see if height and width tags are contained in the file
240            if ((a = shared.getAttribute("height")) != null) {
241                windowHeight = a.getIntValue();
242                panelHeight = windowHeight - 60;
243            }
244            if ((a = shared.getAttribute("width")) != null) {
245                windowWidth = a.getIntValue();
246                panelWidth = windowWidth - 18;
247            }
248
249            // For files created by the new version,
250            // retrieve window and panel sizes
251            if ((a = shared.getAttribute("windowheight")) != null) {
252                windowHeight = a.getIntValue();
253            }
254            if ((a = shared.getAttribute("windowwidth")) != null) {
255                windowWidth = a.getIntValue();
256            }
257            if ((a = shared.getAttribute("panelheight")) != null) {
258                panelHeight = a.getIntValue();
259            }
260            if ((a = shared.getAttribute("panelwidth")) != null) {
261                panelWidth = a.getIntValue();
262            }
263
264            mainlinetrackwidth = shared.getAttribute("mainlinetrackwidth").getIntValue();
265            sidetrackwidth = shared.getAttribute("sidetrackwidth").getIntValue();
266        } catch (DataConversionException e) {
267            log.error("failed to convert LayoutEditor attribute");
268            result = false;
269        }
270
271        double xScale = 1.0;
272        double yScale = 1.0;
273        if ((a = shared.getAttribute("xscale")) != null) {
274            try {
275                xScale = (Float.parseFloat(a.getValue()));
276            } catch (NumberFormatException e) {
277                log.error("failed to convert xscale attribute to float - {}", a.getValue());
278                result = false;
279            }
280        }
281        if ((a = shared.getAttribute("yscale")) != null) {
282            try {
283                yScale = (Float.parseFloat(a.getValue()));
284            } catch (NumberFormatException e) {
285                log.error("failed to convert yscale attribute to float - {}", a.getValue());
286                result = false;
287            }
288        }
289
290        // find the name
291        String name = "";
292        if ((a = shared.getAttribute("name")) != null) {
293            name = a.getValue();
294        }
295        if (InstanceManager.getDefault(EditorManager.class).contains(name)) {
296            JFrame frame = new JFrame("DialogDemo");
297            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
298            log.warn("File contains a panel with the same name ({}) as an existing panel", name);
299            int n = JmriJOptionPane.showConfirmDialog(frame,
300                    Bundle.getMessage("DuplicatePanel", name),
301                    Bundle.getMessage("DuplicatePanelTitle"),
302                    JmriJOptionPane.YES_NO_OPTION);
303            if (n != JmriJOptionPane.YES_OPTION ) {
304                return false;
305            }
306        }
307
308        // If available, override location and size with machine dependent values
309        if (!InstanceManager.getDefault(jmri.util.gui.GuiLafPreferencesManager.class).isEditorUseOldLocSize()) {
310            jmri.UserPreferencesManager prefsMgr = InstanceManager.getNullableDefault(jmri.UserPreferencesManager.class);
311            if (prefsMgr != null) {
312                String windowFrameRef = "jmri.jmrit.display.layoutEditor.LayoutEditor:" + name;
313
314                java.awt.Point prefsWindowLocation = prefsMgr.getWindowLocation(windowFrameRef);
315                if (prefsWindowLocation != null) {
316                    x = (int) prefsWindowLocation.getX();
317                    y = (int) prefsWindowLocation.getY();
318                }
319
320                java.awt.Dimension prefsWindowSize = prefsMgr.getWindowSize(windowFrameRef);
321                if (prefsWindowSize != null && prefsWindowSize.getHeight() != 0 && prefsWindowSize.getWidth() != 0) {
322                    windowHeight = (int) prefsWindowSize.getHeight();
323                    windowWidth = (int) prefsWindowSize.getWidth();
324                }
325            }
326        }
327
328        LayoutEditor panel = new LayoutEditor(name);
329        panel.setLayoutName(name);
330        InstanceManager.getDefault(EditorManager.class).add(panel);
331
332        // create the objects
333        panel.gContext.setMainlineTrackWidth(mainlinetrackwidth);
334        panel.gContext.setSidelineTrackWidth(sidetrackwidth);
335        panel.gContext.setXScale(xScale);
336        panel.gContext.setYScale(yScale);
337
338        String color = ColorUtil.ColorDarkGray;
339        try {
340            if ((a = shared.getAttribute("defaulttrackcolor")) != null) {
341                color = a.getValue();
342            }
343            panel.setDefaultTrackColor(ColorUtil.stringToColor(color));
344        } catch (IllegalArgumentException e) {
345            panel.setDefaultTrackColor(Color.BLACK);
346            log.error("Invalid defaulttrackcolor {}; using black", color);
347        }
348
349        color = ColorUtil.ColorBlack;
350        try {
351            if ((a = shared.getAttribute("defaulttextcolor")) != null) {
352                color = a.getValue();
353            }
354            panel.setDefaultTextColor(ColorUtil.stringToColor(color));
355        } catch (IllegalArgumentException e) {
356            panel.setDefaultTextColor(Color.BLACK);
357            log.error("Invalid defaulttextcolor {}; using black", color);
358        }
359
360        color = "track";  //default to using use default track color for circle color
361        try {
362            if ((a = shared.getAttribute("turnoutcirclecolor")) != null) {
363                color = a.getValue();
364            }
365            panel.setTurnoutCircleColor(ColorUtil.stringToColor(color));
366        } catch (IllegalArgumentException e) {
367            panel.setTurnoutCircleColor(Color.BLACK);
368            log.error("Invalid color {}; using black", color);
369        }
370
371        // default to using turnout circle color just set
372        try {
373            if ((a = shared.getAttribute("turnoutcirclethrowncolor")) != null) {
374                color = a.getValue();
375            }
376            panel.setTurnoutCircleThrownColor(ColorUtil.stringToColor(color));
377        } catch (IllegalArgumentException e) {
378            panel.setTurnoutCircleThrownColor(Color.BLACK);
379            log.error("Invalid color {}; using black", color);
380        }
381
382        try {   // the "turnoutfillcontrolcircles" attribute has a default="no" value in the schema;
383            // it will always return a "no" attribute if the attribute is not present.
384            panel.setTurnoutFillControlCircles(shared.getAttribute("turnoutfillcontrolcircles").getBooleanValue());
385        } catch (DataConversionException e) {
386            log.warn("unable to convert turnoutfillcontrolcircles attribute");
387        } catch (NullPointerException e) {  // considered normal if the attribute is not present
388            log.debug("missing turnoutfillcontrolcircles attribute");
389        }
390
391        if ((a = shared.getAttribute("turnoutcirclesize")) != null) {
392            try {
393                panel.setTurnoutCircleSize(a.getIntValue());
394            } catch (DataConversionException e) {
395                log.warn("unable to convert turnoutcirclesize");
396            }
397        }
398
399        try {
400            panel.setTurnoutDrawUnselectedLeg(shared.getAttribute("turnoutdrawunselectedleg").getBooleanValue());
401        } catch (DataConversionException e) {
402            log.warn("unable to convert turnoutdrawunselectedleg attribute");
403        } catch (NullPointerException e) {  // considered normal if the attribute is not present
404            log.debug("missing turnoutdrawunselectedleg attribute");
405        }
406
407        // turnout size parameters
408        if ((a = shared.getAttribute("turnoutbx")) != null) {
409            try {
410                panel.setTurnoutBX(Float.parseFloat(a.getValue()));
411            } catch (NumberFormatException e) {
412                log.error("failed to convert turnoutbx to float - {}", a.getValue());
413                result = false;
414            }
415        }
416
417        if ((a = shared.getAttribute("turnoutcx")) != null) {
418            try {
419                panel.setTurnoutCX(Float.parseFloat(a.getValue()));
420            } catch (NumberFormatException e) {
421                log.error("failed to convert turnoutcx to float - {}", a.getValue());
422                result = false;
423            }
424        }
425
426        if ((a = shared.getAttribute("turnoutwid")) != null) {
427            try {
428                panel.setTurnoutWid(Float.parseFloat(a.getValue()));
429            } catch (NumberFormatException e) {
430                log.error("failed to convert turnoutwid to float - {}", a.getValue());
431                result = false;
432            }
433        }
434
435        if ((a = shared.getAttribute("xoverlong")) != null) {
436            try {
437                panel.setXOverLong(Float.parseFloat(a.getValue()));
438            } catch (NumberFormatException e) {
439                log.error("failed to convert xoverlong to float - {}", a.getValue());
440                result = false;
441            }
442        }
443        if ((a = shared.getAttribute("xoverhwid")) != null) {
444            try {
445                panel.setXOverHWid(Float.parseFloat(a.getValue()));
446            } catch (NumberFormatException e) {
447                log.error("failed to convert xoverhwid to float - {}", a.getValue());
448                result = false;
449            }
450        }
451        if ((a = shared.getAttribute("xovershort")) != null) {
452            try {
453                panel.setXOverShort(Float.parseFloat(a.getValue()));
454            } catch (NumberFormatException e) {
455                log.error("failed to convert xovershort to float - {}", a.getValue());
456                result = false;
457            }
458        }
459        // grid size parameter
460        if ((a = shared.getAttribute("gridSize")) != null) {
461            try {
462                panel.gContext.setGridSize(Integer.parseInt(a.getValue()));
463            } catch (NumberFormatException e) {
464                log.error("failed to convert gridSize to int - {}", a.getValue());
465                result = false;
466            }
467        }
468
469        // second grid size parameter
470        if ((a = shared.getAttribute("gridSize2nd")) != null) {
471            try {
472                panel.gContext.setGridSize2nd(Integer.parseInt(a.getValue()));
473            } catch (NumberFormatException e) {
474                log.error("failed to convert gridSize2nd to int - {}", a.getValue());
475                result = false;
476            }
477        }
478
479        try {
480            panel.setAllPositionable(shared.getAttribute("positionable").getBooleanValue());
481        } catch (DataConversionException e) {
482            log.warn("unable to convert positionable attribute");
483        } catch (NullPointerException e) {  // considered normal if the attribute is not present
484            log.debug("missing positionable attribute");
485
486        }
487
488        try {
489            panel.setAllControlling(shared.getAttribute("controlling").getBooleanValue());
490        } catch (DataConversionException e) {
491            log.warn("unable to convert controlling attribute");
492        } catch (NullPointerException e) {  // considered normal if the attribute is not present
493            log.debug("missing controlling attribute");
494        }
495
496        try {
497            panel.setTurnoutAnimation(shared.getAttribute("animating").getBooleanValue());
498        } catch (DataConversionException e) {
499            log.warn("unable to convert animating attribute");
500        } catch (NullPointerException e) {  // considered normal if the attribute is not present
501            log.debug("missing animating attribute");
502        }
503
504        try {
505            panel.setDrawGrid(shared.getAttribute("drawgrid").getBooleanValue());
506        } catch (DataConversionException e) {
507            log.warn("unable to convert drawgrid attribute");
508        } catch (NullPointerException e) {  // considered normal if the attribute is not present
509            log.debug("missing drawgrid attribute");
510        }
511
512        try {
513            panel.setSnapOnAdd(shared.getAttribute("snaponadd").getBooleanValue());
514        } catch (DataConversionException e) {
515            log.warn("unable to convert snaponadd attribute");
516        } catch (NullPointerException e) {  // considered normal if the attribute is not present
517            log.debug("missing snaponadd attribute");
518        }
519
520        try {
521            panel.setSnapOnMove(shared.getAttribute("snaponmove").getBooleanValue());
522        } catch (DataConversionException e) {
523            log.warn("unable to convert snaponmove attribute");
524        } catch (NullPointerException e) {  // considered normal if the attribute is not present
525            log.debug("missing snaponmove attribute");
526        }
527
528        try {
529            panel.setTurnoutCircles(shared.getAttribute("turnoutcircles").getBooleanValue());
530        } catch (DataConversionException e) {
531            log.warn("unable to convert turnoutcircles attribute");
532        } catch (NullPointerException e) {  // considered normal if the attribute is not present
533            log.debug("missing turnoutcircles attribute");
534        }
535
536        try {
537            panel.setTooltipsNotEdit(shared.getAttribute("tooltipsnotedit").getBooleanValue());
538        } catch (DataConversionException e) {
539            log.warn("unable to convert tooltipsnotedit attribute");
540        } catch (NullPointerException e) {  // considered normal if the attribute is not present
541            log.debug("missing tooltipsnotedit attribute");
542        }
543
544        try {
545            panel.setAutoBlockAssignment(shared.getAttribute("autoblkgenerate").getBooleanValue());
546        } catch (DataConversionException e) {
547            log.warn("unable to convert autoblkgenerate attribute");
548        } catch (NullPointerException e) {  // considered normal if the attribute is not present
549            log.debug("missing autoblkgenerate attribute");
550        }
551
552        try {
553            panel.setTooltipsInEdit(shared.getAttribute("tooltipsinedit").getBooleanValue());
554        } catch (DataConversionException e) {
555            log.warn("unable to convert tooltipsinedit attribute");
556        } catch (NullPointerException e) {  // considered normal if the attribute is not present
557            log.debug("missing tooltipsinedit attribute");
558        }
559
560        // set default track color
561        if ((a = shared.getAttribute("defaulttrackcolor")) != null) {
562            try {
563                panel.setDefaultTrackColor(ColorUtil.stringToColor(a.getValue()));
564            } catch (IllegalArgumentException e) {
565                panel.setDefaultTrackColor(Color.darkGray);
566                log.error("Invalid defaulttrackcolor {}; using 'darkGray'", a.getValue());
567            }
568        }
569        // set default occupied track color
570        if ((a = shared.getAttribute("defaultoccupiedtrackcolor")) != null) {
571            try {
572                panel.setDefaultOccupiedTrackColor(ColorUtil.stringToColor(a.getValue()));
573            } catch (IllegalArgumentException e) {
574                panel.setDefaultOccupiedTrackColor(Color.red);
575                log.error("Invalid defaultoccupiedtrackcolor {}; using 'red'", a.getValue());
576            }
577        }
578        // set default alternative track color
579        if ((a = shared.getAttribute("defaultalternativetrackcolor")) != null) {
580            try {
581                panel.setDefaultAlternativeTrackColor(ColorUtil.stringToColor(a.getValue()));
582            } catch (IllegalArgumentException e) {
583                panel.setDefaultAlternativeTrackColor(Color.white);
584                log.error("Invalid defaultalternativetrackcolor {}; using 'white'", a.getValue());
585            }
586        }
587        try {
588            int red = shared.getAttribute("redBackground").getIntValue();
589            int blue = shared.getAttribute("blueBackground").getIntValue();
590            int green = shared.getAttribute("greenBackground").getIntValue();
591            Color backgroundColor = new Color(red, green, blue);
592            panel.setDefaultBackgroundColor(backgroundColor);
593            panel.setBackgroundColor(backgroundColor);
594        } catch (DataConversionException e) {
595            log.warn("Could not parse color attributes!");
596        } catch (NullPointerException e) {  // considered normal if the attributes are not present
597            log.debug("missing background color attributes");
598        }
599
600        try {
601            panel.setDirectTurnoutControl(shared.getAttribute("useDirectTurnoutControl").getBooleanValue());
602        } catch (DataConversionException e) {
603            log.warn("unable to convert Layout Editor useDirectTurnoutControl attribute");
604        } catch (NullPointerException e) {  // considered normal if the attribute is not present
605            log.debug("missing useDirectTurnoutControl attribute");
606        }
607
608        try {
609            panel.setHighlightCursor(shared.getAttribute("highlightCursor").getBooleanValue());
610        } catch (DataConversionException e) {
611            log.warn("unable to convert highlightCursor attribute");
612        } catch (NullPointerException e) {  // considered normal if the attribute is not present
613            log.debug("missing highlightCursor attribute");
614        }
615
616
617        // Set editor's option flags, load content after
618        // this so that individual item flags are set as saved
619        panel.initView();
620
621
622        // load the contents
623        for (Element item : shared.getChildren()) {
624            // get the class, hence the adapter object to do loading
625            String adapterName = item.getAttribute("class").getValue();
626            adapterName = jmri.configurexml.ConfigXmlManager.currentClassName(adapterName);
627
628            if (log.isDebugEnabled()) {
629                String id = "<null>";
630                try {
631                    id = item.getAttribute("name").getValue();
632                    log.debug("Load {} for [{}] via {}", id, panel.getName(), adapterName);
633                } catch (NullPointerException e) {
634                    log.debug("Load layout object for [{}] via {}", panel.getName(), adapterName);
635                    log.debug("Load layout object for [{}] via {}", panel.getName(), adapterName);
636                } catch (RuntimeException e) {
637                    throw e;
638                } catch (Exception e) {
639                }
640            }
641            try {
642                // get the class name, including migrations
643                adapterName = jmri.configurexml.ConfigXmlManager.currentClassName(adapterName);
644                // get the adapter object
645                XmlAdapter adapter = (XmlAdapter) Class.forName(adapterName).getDeclaredConstructor().newInstance();
646                // and load with it
647                adapter.load(item, panel);
648                if (!panel.loadOK()) {
649                    result = false;
650                }
651            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException
652                    | jmri.configurexml.JmriConfigureXmlException
653                    | java.lang.reflect.InvocationTargetException e) {
654                log.error("Exception while loading {}", item.getName(), e);
655                result = false;
656            }
657        }
658        panel.disposeLoadData();     // dispose of url correction data
659
660        // final initialization of objects
661        panel.setConnections();
662
663        // display the results
664        try {
665            // set first since other attribute use this setting
666            panel.setAllEditable(shared.getAttribute("editable").getBooleanValue());
667        } catch (DataConversionException e) {
668            log.warn("unable to convert editable attribute");
669        } catch (NullPointerException e) {  // considered normal if the attribute is not present
670            log.debug("missing editable attribute");
671        }
672
673        try {
674            panel.setShowHelpBar(shared.getAttribute("showhelpbar").getBooleanValue());
675        } catch (DataConversionException e) {
676            log.warn("unable to convert showhelpbar attribute");
677        } catch (NullPointerException e) {  // considered normal if the attribute is not present
678            log.debug("missing showhelpbar attribute");
679        }
680
681        try {
682            panel.setAntialiasingOn(shared.getAttribute("antialiasing").getBooleanValue());
683        } catch (DataConversionException e) {
684            log.warn("unable to convert antialiasing attribute");
685        } catch (NullPointerException e) {  // considered normal if the attribute is not present
686            log.debug("missing antialiasing attribute");
687        }
688
689        // set contents state
690        String slValue = "both";
691        try {
692            boolean value = shared.getAttribute("sliders").getBooleanValue();
693            slValue = value ? "both" : "none";
694        } catch (DataConversionException e) {
695            log.warn("unable to convert sliders attribute");
696        } catch (NullPointerException e) {  // considered normal if the attribute is not present
697            log.debug("missing sliders attribute");
698        }
699        if ((a = shared.getAttribute("scrollable")) != null) {
700            slValue = a.getValue();
701        }
702        panel.setScroll(slValue);
703
704        panel.pack();
705        panel.setLayoutDimensions(windowWidth, windowHeight, x, y, panelWidth, panelHeight);
706        panel.setVisible(true);    // always show the panel
707
708        // make a pass over positionables, setting (re)setting their font style.
709        // This is to bypass a problem on Windows, where bold labels need to have
710        // this done after pack() to avoid sizing issues.
711        for (jmri.jmrit.display.Positionable label : panel.getContents()) {
712            var popup = label.getPopupUtility();
713            if (popup != null) { // encountered in some testing
714                popup.setFontStyle(popup.getFontStyle());
715            }
716        }
717        
718        panel.resetDirty();
719
720        // register the resulting panel for later configuration
721        ConfigureManager cm = InstanceManager.getNullableDefault(jmri.ConfigureManager.class);
722        if (cm != null) {
723            cm.registerUser(panel);
724        }
725        //open Dispatcher frame if any Transits are defined, and open Dispatcher flag set on
726        if (jmri.InstanceManager.getDefault(jmri.TransitManager.class).getNamedBeanSet().size() > 0) {
727            try {
728                boolean value = shared.getAttribute("openDispatcher").getBooleanValue();
729                panel.setOpenDispatcherOnLoad(value);
730                if (value) {
731                    // Create the DispatcherFrame instance.
732                    // This is a trigger for LoadXmlConfigAction to call loadAtStartup.
733                    InstanceManager.getDefault(DispatcherFrame.class);
734                }
735            } catch (DataConversionException e) {
736                log.warn("unable to convert openDispatcher attribute");
737            } catch (NullPointerException e) {  // considered normal if the attribute is not present
738                log.debug("No openDispatcher attribute");
739            }
740        }
741        return result;
742    }   // load
743
744    @Override
745    public int loadOrder() {
746        return jmri.Manager.PANELFILES;
747    }
748
749    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LayoutEditorXml.class);
750
751}