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