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