001package jmri.jmrit.display.controlPanelEditor.configurexml;
002
003import java.awt.Color;
004import java.awt.Dimension;
005import java.awt.Point;
006import java.util.List;
007import javax.swing.JFrame;
008import jmri.ConfigureManager;
009import jmri.InstanceManager;
010import jmri.configurexml.AbstractXmlAdapter;
011import jmri.configurexml.XmlAdapter;
012import jmri.jmrit.catalog.NamedIcon;
013import jmri.jmrit.display.Editor;
014import jmri.jmrit.display.EditorManager;
015import jmri.jmrit.display.Positionable;
016import jmri.jmrit.display.controlPanelEditor.ControlPanelEditor;
017import org.jdom2.Attribute;
018import org.jdom2.Element;
019import org.slf4j.Logger;
020import org.slf4j.LoggerFactory;
021
022/**
023 * Handle configuration for {@link ControlPanelEditor} panes.
024 *
025 * @author Bob Jacobsen Copyright: Copyright (c) 2002
026 */
027public class ControlPanelEditorXml extends AbstractXmlAdapter {
028
029    public ControlPanelEditorXml() {
030    }
031
032    /**
033     * Default implementation for storing the contents of a ControlPanelEditor.
034     *
035     * @param o Object to store, of type ControlPanelEditor
036     * @return Element containing the complete info
037     */
038    @Override
039    public Element store(Object o) {
040        ControlPanelEditor p = (ControlPanelEditor) o;
041        Element panel = new Element("paneleditor");
042
043        JFrame frame = p.getTargetFrame();
044        Dimension size = frame.getSize();
045        Point posn = frame.getLocation();
046
047        panel.setAttribute("class", "jmri.jmrit.display.controlPanelEditor.configurexml.ControlPanelEditorXml");
048        panel.setAttribute("name", "" + frame.getName());
049        panel.setAttribute("x", "" + posn.x);
050        panel.setAttribute("y", "" + posn.y);
051        panel.setAttribute("height", "" + size.height);
052        panel.setAttribute("width", "" + size.width);
053        panel.setAttribute("editable", "" + (p.isEditable() ? "yes" : "no"));
054        panel.setAttribute("positionable", "" + (p.allPositionable() ? "yes" : "no"));
055        //panel.setAttribute("showcoordinates", ""+(p.showCoordinates()?"yes":"no"));
056        panel.setAttribute("showtooltips", "" + (p.showToolTip() ? "yes" : "no"));
057        panel.setAttribute("controlling", "" + (p.allControlling() ? "yes" : "no"));
058        panel.setAttribute("hide", p.showHidden() ? "no" : "yes");  // hide=no means showHidden enabled
059        panel.setAttribute("panelmenu", p.isPanelMenuVisible() ? "yes" : "no");
060        panel.setAttribute("scrollable", p.getScrollable());
061        if (p.getBackgroundColor() != null) {
062            panel.setAttribute("redBackground", "" + p.getBackgroundColor().getRed());
063            panel.setAttribute("greenBackground", "" + p.getBackgroundColor().getGreen());
064            panel.setAttribute("blueBackground", "" + p.getBackgroundColor().getBlue());
065        }
066        panel.setAttribute("state", "" + p.getExtendedState());
067        panel.setAttribute("shapeSelect", "" + (p.getShapeSelect() ? "yes" : "no"));
068
069        String family = p.getPortalIconFamily();
070        if (family != null && !family.equals("Standard")) { // don't store the default map name
071        Element elem = new Element("icons");
072            elem.setAttribute("portalFamily", family);
073            panel.addContent(elem);
074        }
075
076        // include contents
077        List<Positionable> contents = p.getContents();
078        log.debug("N elements: {}", contents.size());
079        for (Positionable sub : contents) {
080            if (sub != null && sub.storeItem()) {
081                try {
082                    Element e = jmri.configurexml.ConfigXmlManager.elementFromObject(sub);
083                    if (e != null) {
084                        panel.addContent(e);
085                    }
086                } catch (RuntimeException e) {
087                    log.error("Error storing panel element", e);
088                }
089            }
090        }
091        return panel;
092    }
093
094    public Element storeIcon(String elemName, NamedIcon icon) {
095        if (icon == null) {
096            return null;
097        }
098        Element element = new Element(elemName);
099        element.addContent(new Element("url").addContent(icon.getURL()));
100        return element;
101    }
102
103    /**
104     * Create a ControlPanelEditor object, then register and fill it, then pop
105     * it in a JFrame
106     *
107     * @param shared Top level Element to unpack.
108     * @return true if successful
109     */
110    @Override
111    public boolean load(Element shared, Element perNode) {
112        if (java.awt.GraphicsEnvironment.isHeadless()) {
113            return true;
114        }
115
116        boolean result = true;
117        Attribute a;
118        // find coordinates
119        int x = 0;
120        int y = 0;
121        int height = 400;
122        int width = 300;
123        try {
124            if ((a = shared.getAttribute("x")) != null) {
125                x = a.getIntValue();
126            }
127            if ((a = shared.getAttribute("y")) != null) {
128                y = a.getIntValue();
129            }
130            if ((a = shared.getAttribute("height")) != null) {
131                height = a.getIntValue();
132            }
133            if ((a = shared.getAttribute("width")) != null) {
134                width = a.getIntValue();
135            }
136        } catch (org.jdom2.DataConversionException e) {
137            log.error("failed to convert ControlPanelEditor's attribute");
138            result = false;
139        }
140        // find the name
141        String name = "Control Panel";
142        if (shared.getAttribute("name") != null) {
143            name = shared.getAttribute("name").getValue();
144        }
145        // confirm that panel hasn't already been loaded
146        if (InstanceManager.getDefault(EditorManager.class).contains(name)) {
147            log.warn("File contains a panel with the same name ({}) as an existing panel", name);
148            result = false;
149        }
150
151        // If available, override location and size with machine dependent values
152        if (!InstanceManager.getDefault(jmri.util.gui.GuiLafPreferencesManager.class).isEditorUseOldLocSize()) {
153            jmri.UserPreferencesManager prefsMgr = InstanceManager.getNullableDefault(jmri.UserPreferencesManager.class);
154            if (prefsMgr != null) {
155                String windowFrameRef = "jmri.jmrit.display.controlPanelEditor.ControlPanelEditor:" + name;
156
157                java.awt.Point prefsWindowLocation = prefsMgr.getWindowLocation(windowFrameRef);
158                if (prefsWindowLocation != null) {
159                    x = (int) prefsWindowLocation.getX();
160                    y = (int) prefsWindowLocation.getY();
161                }
162
163                java.awt.Dimension prefsWindowSize = prefsMgr.getWindowSize(windowFrameRef);
164                if (prefsWindowSize != null && prefsWindowSize.getHeight() != 0 && prefsWindowSize.getWidth() != 0) {
165                    height = (int) prefsWindowSize.getHeight();
166                    width = (int) prefsWindowSize.getWidth();
167                }
168            }
169        }
170
171        ControlPanelEditor panel = new ControlPanelEditor(name);
172        panel.getTargetFrame().setVisible(false);   // save painting until last
173        InstanceManager.getDefault(EditorManager.class).add(panel);
174
175        // Load editor option flags. This has to be done before the content
176        // items are loaded, to preserve the individual item settings
177        boolean value = true;
178        if ((a = shared.getAttribute("editable")) != null && a.getValue().equals("no")) {
179            value = false;
180        }
181        panel.setAllEditable(value);
182
183        value = true;
184        if ((a = shared.getAttribute("positionable")) != null && a.getValue().equals("no")) {
185            value = false;
186        }
187        panel.setAllPositionable(value);
188
189        /*
190         value = false;
191         if ((a = element.getAttribute("showcoordinates"))!=null && a.getValue().equals("yes"))
192         value = true;
193         panel.setShowCoordinates(value);
194         */
195        value = true;
196        if ((a = shared.getAttribute("showtooltips")) != null && a.getValue().equals("no")) {
197            value = false;
198        }
199        panel.setAllShowToolTip(value);
200
201        value = true;
202        if ((a = shared.getAttribute("controlling")) != null && a.getValue().equals("no")) {
203            value = false;
204        }
205        panel.setAllControlling(value);
206
207        value = true;
208        if ((a = shared.getAttribute("hide")) != null && a.getValue().equals("yes")) {
209            value = false;
210        }
211        panel.setShowHidden(value);
212
213        value = true;
214        if ((a = shared.getAttribute("panelmenu")) != null && a.getValue().equals("no")) {
215            value = false;
216        }
217        panel.setPanelMenuVisible(value);
218
219        value = true;
220        if ((a = shared.getAttribute("shapeSelect")) != null && a.getValue().equals("no")) {
221            value = false;
222        }
223        panel.setShapeSelect(value);
224
225        if ((a = shared.getAttribute("state")) != null) {
226            try {
227                int xState = a.getIntValue();
228                panel.setExtendedState(xState);
229            } catch (org.jdom2.DataConversionException e) {
230                log.error("failed to convert ControlPanelEditor's extended State");
231                result = false;
232            }
233        }
234
235        Element elem = shared.getChild("icons");
236        if (elem != null) {
237            Attribute attr = elem.getAttribute("portalFamily");
238            if (attr != null) {
239                panel.setPortalIconFamily(attr.getValue());
240            }
241        }
242
243        String state = "both";
244        if ((a = shared.getAttribute("scrollable")) != null) {
245            state = a.getValue();
246        }
247        panel.setScroll(state);
248        try {
249            int red = shared.getAttribute("redBackground").getIntValue();
250            int blue = shared.getAttribute("blueBackground").getIntValue();
251            int green = shared.getAttribute("greenBackground").getIntValue();
252            panel.setBackgroundColor(new Color(red, green, blue));
253        } catch (org.jdom2.DataConversionException e) {
254            log.warn("Could not parse color attributes!");
255        } catch (NullPointerException e) {  // considered normal if the attributes are not present
256        }
257
258        shared.removeChild("icons");
259
260        //set the (global) editor display widgets to their flag settings
261        panel.initView();
262
263        // load the contents
264        List<Element> items = shared.getChildren();
265        for (Element panelItem : items) {
266            String adapterName = panelItem.getAttribute("class").getValue();
267            log.debug("load via {}", adapterName);
268            try {
269                XmlAdapter adapter = (XmlAdapter) Class.forName(adapterName).getDeclaredConstructor().newInstance();
270                // and do it
271                adapter.load(panelItem, panel);
272                if (!panel.loadOK()) {
273                    result = false;
274                }
275            } catch (ClassNotFoundException | InstantiationException
276                    | jmri.configurexml.JmriConfigureXmlException | IllegalAccessException
277                    | NoSuchMethodException | java.lang.reflect.InvocationTargetException e) {
278                log.error("Exception while loading {}", panelItem.getName(), e);
279                result = false;
280            }
281        }
282        panel.disposeLoadData();     // dispose of url correction data
283
284        // display the results, with the editor in back
285        panel.pack();
286        panel.setAllEditable(panel.isEditable());
287
288        // register the resulting panel for later configuration
289        ConfigureManager cm = InstanceManager.getNullableDefault(jmri.ConfigureManager.class);
290        if (cm != null) {
291            cm.registerUser(panel);
292        }
293
294        // reset the size and position, in case the display caused it to change
295        panel.getTargetFrame().setLocation(x, y);
296        panel.getTargetFrame().setSize(width, height);
297        panel.setTitle();
298        panel.getTargetFrame().setVisible(true);    // always show the panel
299        // do last to set putItem override - unused.
300        panel.loadComplete();
301
302        return result;
303    }
304
305    public NamedIcon loadIcon(String key, Element element, Editor ed) {
306        Element elem = element.getChild(key);
307        NamedIcon icon = null;
308        if (elem != null) {
309            Element e = elem.getChild("url");
310            String iconName = e.getText();
311            icon = NamedIcon.getIconByName(iconName);
312            if (icon == null) {
313                icon = ed.loadFailed(key, iconName);
314                if (icon == null) {
315                    log.info("{} removed for url= {}", key, iconName);
316                }
317            }
318        }
319        return icon;
320    }
321
322    @Override
323    public int loadOrder() {
324        return jmri.Manager.PANELFILES;
325    }
326
327    private static final Logger log = LoggerFactory.getLogger(ControlPanelEditorXml.class);
328
329}