001package jmri.jmrit.display.panelEditor.configurexml;
002
003import java.awt.Color;
004import java.awt.Dimension;
005import java.awt.Point;
006import java.util.List;
007
008import javax.swing.JFrame;
009
010import org.jdom2.Attribute;
011import org.jdom2.Element;
012import org.slf4j.Logger;
013import org.slf4j.LoggerFactory;
014
015import jmri.ConfigureManager;
016import jmri.InstanceManager;
017import jmri.configurexml.AbstractXmlAdapter;
018import jmri.configurexml.XmlAdapter;
019import jmri.jmrit.display.EditorManager;
020import jmri.jmrit.display.Positionable;
021import jmri.jmrit.display.panelEditor.PanelEditor;
022
023/**
024 * Handle configuration for {@link PanelEditor} panes.
025 *
026 * @author Bob Jacobsen Copyright: Copyright (c) 2002
027 */
028public class PanelEditorXml extends AbstractXmlAdapter {
029
030    public PanelEditorXml() {
031    }
032
033    /**
034     * Default implementation for storing the contents of a PanelEditor
035     *
036     * @param o Object to store, of type PanelEditor
037     * @return Element containing the complete info
038     */
039    @Override
040    public Element store(Object o) {
041        PanelEditor p = (PanelEditor) o;
042        Element panel = new Element("paneleditor");
043
044        JFrame frame = p.getTargetFrame();
045        Dimension size = frame.getSize();
046        Point posn = frame.getLocation();
047
048        panel.setAttribute("class", "jmri.jmrit.display.panelEditor.configurexml.PanelEditorXml");
049        panel.setAttribute("name", "" + frame.getTitle());
050        panel.setAttribute("x", "" + posn.x);
051        panel.setAttribute("y", "" + posn.y);
052        panel.setAttribute("height", "" + size.height);
053        panel.setAttribute("width", "" + size.width);
054        panel.setAttribute("editable", "" + (p.isEditable() ? "yes" : "no"));
055        panel.setAttribute("positionable", "" + (p.allPositionable() ? "yes" : "no"));
056        //panel.setAttribute("showcoordinates", ""+(p.showCoordinates()?"yes":"no"));
057        panel.setAttribute("showtooltips", "" + (p.showToolTip() ? "yes" : "no"));
058        panel.setAttribute("controlling", "" + (p.allControlling() ? "yes" : "no"));
059        panel.setAttribute("hide", p.showHidden() ? "no" : "yes");  // hide=no means showHidden enabled
060        panel.setAttribute("panelmenu", p.isPanelMenuVisible() ? "yes" : "no");
061        panel.setAttribute("scrollable", p.getScrollable());
062        if (p.getBackgroundColor() != null) {
063            panel.setAttribute("redBackground", "" + p.getBackgroundColor().getRed());
064            panel.setAttribute("greenBackground", "" + p.getBackgroundColor().getGreen());
065            panel.setAttribute("blueBackground", "" + p.getBackgroundColor().getBlue());
066        }
067
068        // include contents
069        List<Positionable> contents = p.getContents();
070        if (log.isDebugEnabled()) {
071            log.debug("N elements: {}", contents.size());
072        }
073        for (Positionable sub : contents) {
074            if (sub != null && sub.storeItem()) {
075                try {
076                    Element e = jmri.configurexml.ConfigXmlManager.elementFromObject(sub);
077                    if (e != null) {
078                        panel.addContent(e);
079                    }
080                } catch (RuntimeException e) {
081                    log.error("Error storing panel element", e);
082                }
083            }
084        }
085
086        return panel;
087    }
088
089    /**
090     * Create a PanelEditor object, then register and fill it, then pop it in a
091     * JFrame.
092     *
093     * @param shared Top level Element to unpack.
094     * @return true if successful
095     */
096    @Override
097    public boolean load(Element shared, Element perNode) {
098        if (java.awt.GraphicsEnvironment.isHeadless()) {
099            return true;
100        }
101
102        boolean result = true;
103        Attribute a;
104        // find coordinates
105        int x = 0;
106        int y = 0;
107        int height = 400;
108        int width = 300;
109        try {
110            if ((a = shared.getAttribute("x")) != null) {
111                x = a.getIntValue();
112            }
113            if ((a = shared.getAttribute("y")) != null) {
114                y = a.getIntValue();
115            }
116            if ((a = shared.getAttribute("height")) != null) {
117                height = a.getIntValue();
118            }
119            if ((a = shared.getAttribute("width")) != null) {
120                width = a.getIntValue();
121            }
122        } catch (org.jdom2.DataConversionException e) {
123            log.error("failed to convert PanelEditor's attribute");
124            result = false;
125        }
126        // find the name
127        String name = "Panel";
128        if (shared.getAttribute("name") != null) {
129            name = shared.getAttribute("name").getValue();
130        }
131        // confirm that panel hasn't already been loaded
132        if (InstanceManager.getDefault(EditorManager.class).contains(name)) {
133            log.warn("File contains a panel with the same name ({}) as an existing panel", name);
134            result = false;
135        }
136
137        // If available, override location and size with machine dependent values
138        if (!InstanceManager.getDefault(jmri.util.gui.GuiLafPreferencesManager.class).isEditorUseOldLocSize()) {
139            jmri.UserPreferencesManager prefsMgr = InstanceManager.getNullableDefault(jmri.UserPreferencesManager.class);
140            if (prefsMgr != null) {
141
142                java.awt.Point prefsWindowLocation = prefsMgr.getWindowLocation(name);
143                if (prefsWindowLocation != null) {
144                    x = (int) prefsWindowLocation.getX();
145                    y = (int) prefsWindowLocation.getY();
146                }
147
148                java.awt.Dimension prefsWindowSize = prefsMgr.getWindowSize(name);
149                if (prefsWindowSize != null && prefsWindowSize.getHeight() != 0 && prefsWindowSize.getWidth() != 0) {
150                    height = (int) prefsWindowSize.getHeight();
151                    width = (int) prefsWindowSize.getWidth();
152                }
153            }
154        }
155
156        PanelEditor panel = new PanelEditor(name);
157        panel.setTitle();
158        panel.setKeepSize(false);
159        panel.getTargetFrame().setLocation(x, y);
160        panel.getTargetFrame().setSize(width, height);
161        //Panel already added to EditorManager with new PanelEditor(name)
162//        InstanceManager.getDefault(EditorManager.class).add(panel);
163
164        // Load editor option flags. This has to be done before the content
165        // items are loaded, to preserve the individual item settings
166        panel.setAllEditable(!shared.getAttributeValue("editable","yes").equals("no"));
167        panel.setAllPositionable(!shared.getAttributeValue("positionable","yes").equals("no"));
168        //panel.setShowCoordinates(shared.getAttributeValue("showcoordinates","no").equals("yes"));
169        panel.setAllShowToolTip(!shared.getAttributeValue("showtooltips","yes").equals("no"));
170        panel.setAllControlling(!shared.getAttributeValue("controlling", "yes").equals("no"));
171        panel.setShowHidden(!shared.getAttributeValue("hide","no").equals("yes"));
172        panel.setPanelMenuVisible(!shared.getAttributeValue("panelmenu","yes").equals("no"));
173        panel.setScroll(shared.getAttributeValue("scrollable","both"));
174
175        // set color if needed
176        try {
177            int red = shared.getAttribute("redBackground").getIntValue();
178            int blue = shared.getAttribute("blueBackground").getIntValue();
179            int green = shared.getAttribute("greenBackground").getIntValue();
180            panel.setBackgroundColor(new Color(red, green, blue));
181        } catch (org.jdom2.DataConversionException e) {
182            log.warn("Could not parse color attributes!");
183        } catch (NullPointerException e) {  // considered normal if the attributes are not present
184        }
185        //set the (global) editor display widgets to their flag settings
186        panel.initView();
187
188        // load the contents with their individual option settings
189        List<Element> panelItems = shared.getChildren();
190        for (Element item : panelItems) {
191            // get the class, hence the adapter object to do loading
192            String adapterName = item.getAttribute("class").getValue();
193            log.debug("load via {}", adapterName);
194            try {
195                XmlAdapter adapter = (XmlAdapter) Class.forName(adapterName).getDeclaredConstructor().newInstance();
196                // and do it
197                adapter.load(item, panel);
198                if (!panel.loadOK()) {
199                    result = false;
200                }
201            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException
202                    | jmri.configurexml.JmriConfigureXmlException | java.lang.reflect.InvocationTargetException e) {
203                log.error("Exception while loading {}", item.getName(), e);
204                result = false;
205            }
206        }
207        panel.disposeLoadData();     // dispose of url correction data
208
209        // display the results, with the editor in back
210        panel.pack();
211        panel.setAllEditable(panel.isEditable());
212
213        // we don't pack the target frame here, because size was specified
214        // TODO: Work out why, when calling this method, panel size is increased
215        // vertically (at least on MS Windows)
216        panel.getTargetFrame().setVisible(true);    // always show the panel
217
218        // register the resulting panel for later configuration
219        ConfigureManager cm = InstanceManager.getNullableDefault(jmri.ConfigureManager.class);
220        if (cm != null) {
221            cm.registerUser(panel);
222        }
223
224        // reset the size and position, in case the display caused it to change
225        panel.getTargetFrame().setLocation(x, y);
226        panel.getTargetFrame().setSize(width, height);
227        return result;
228    }
229
230    @Override
231    public int loadOrder() {
232        return jmri.Manager.PANELFILES;
233    }
234
235    private final static Logger log = LoggerFactory.getLogger(PanelEditorXml.class);
236
237}