001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2015
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see http://www.gnu.org/licenses.
027 */
028package edu.wisc.ssec.mcidasv;
029
030import static ucar.unidata.util.GuiUtils.makeMenu;
031import static ucar.unidata.util.GuiUtils.makeMenuItem;
032import static ucar.unidata.util.MenuUtil.MENU_SEPARATOR;
033
034import java.util.ArrayList;
035import java.util.List;
036import java.util.Map;
037
038import org.python.util.PythonInterpreter;
039
040import org.slf4j.Logger;
041import org.slf4j.LoggerFactory;
042
043import edu.wisc.ssec.mcidasv.util.CollectionHelpers;
044
045import ucar.unidata.data.DataSource;
046import ucar.unidata.data.DescriptorDataSource;
047import ucar.unidata.idv.IntegratedDataViewer;
048import ucar.unidata.idv.ui.ImageGenerator;
049import ucar.unidata.idv.ui.JythonShell;
050
051/**
052 * Overrides the IDV's {@link ucar.unidata.idv.JythonManager JythonManager} to 
053 * associate a {@link JythonShell} with a given {@code JythonManager}.
054 */
055public class JythonManager extends ucar.unidata.idv.JythonManager {
056    
057//    /** Trusty logging object. */
058//    private static final Logger logger = LoggerFactory.getLogger(JythonManager.class);
059    
060    /** Associated Jython Shell. May be {@code null}. */
061    private JythonShell jythonShell;
062    
063    /**
064     * Create the manager and call initPython.
065     *
066     * @param idv The IDV.
067     */
068    public JythonManager(IntegratedDataViewer idv) {
069        super(idv);
070    }
071    
072    /**
073     * Create a Jython shell, if one doesn't already exist. This will also 
074     * bring the window {@literal "to the front"} of the rest of the McIDAS-V
075     * session.
076     * 
077     * @return JythonShell object for interactive Jython usage.
078     */
079    public JythonShell createShell() {
080        if (jythonShell == null) {
081            jythonShell = new JythonShell(getIdv());
082            
083        }
084        jythonShell.toFront();
085        return jythonShell;
086    }
087    
088    /** 
089     * Returns the Jython Shell associated with this {@code JythonManager}.
090     * 
091     * @return Jython Shell being used by this manager. May be {@code null}.
092     */
093    public JythonShell getShell() {
094        return jythonShell;
095    }
096    
097    /**
098     * Create and initialize a Jython interpreter.
099     * 
100     * @return Newly created Jython interpreter.
101     */
102    @Override public PythonInterpreter createInterpreter() {
103        PythonInterpreter interpreter = super.createInterpreter();
104        return interpreter;
105    }
106    
107    /**
108     * Removes the given interpreter from the list of active interpreters. 
109     * 
110     * <p>Also attempts to close any Jython Shell associated with the 
111     * interpreter.</p>
112     * 
113     * @param interpreter Interpreter to remove. Should not be {@code null}. 
114     */
115    @Override public void removeInterpreter(PythonInterpreter interpreter) {
116        super.removeInterpreter(interpreter);
117        if ((jythonShell != null) && !jythonShell.isShellResetting() && jythonShell.getInterpreter().equals(interpreter)) {
118            jythonShell.close();
119            jythonShell = null;
120        }
121    }
122
123    /**
124     * Overridden so that McIDAS-V can add an {@code islInterpreter} object
125     * to the interpreter's locals (before executing the contents of {@code}.
126     * 
127     * @param code Jython code to evaluate. {@code null} is probably a bad idea.
128     * @param properties {@code String->Object} pairs to insert into the 
129     * locals. Parameter may be {@code null}.
130     */
131    @SuppressWarnings("unchecked") // dealing with idv code that predates generics.
132    @Override public void evaluateTrusted(String code, Map<String, Object> properties) {
133        if (properties == null) {
134            properties = CollectionHelpers.newMap();
135        }
136        if (!properties.containsKey("islInterpreter")) {
137            properties.put("islInterpreter", new ImageGenerator(getIdv()));
138        }
139        if (!properties.containsKey("_idv")) {
140            properties.put("_idv", getIdv());
141        }
142        if (!properties.containsKey("idv")) {
143            properties.put("idv", getIdv());
144        }
145        super.evaluateTrusted(code, properties);
146    }
147    
148    /**
149     * Return the list of menu items to use when the user has clicked on a 
150     * formula {@link DataSource}.
151     * 
152     * @param dataSource The data source clicked on.
153     * 
154     * @return {@link List} of menu items.
155     */
156    @SuppressWarnings("unchecked") // dealing with idv code that predates generics.
157    @Override public List doMakeFormulaDataSourceMenuItems(DataSource dataSource) {
158        List menuItems = new ArrayList(100);
159        menuItems.add(makeMenuItem("Create Formula", this, "showFormulaDialog"));
160        List editItems;
161        if (dataSource instanceof DescriptorDataSource) {
162            editItems = doMakeEditMenuItems((DescriptorDataSource)dataSource);
163        }
164        else {
165            editItems = doMakeEditMenuItems();
166        }
167        menuItems.add(makeMenu("Edit Formulas", editItems));
168        menuItems.add(MENU_SEPARATOR);
169        menuItems.add(makeMenuItem("Jython Library", this, "showJythonEditor"));
170        menuItems.add(makeMenuItem("Jython Shell", this, "createShell"));
171        menuItems.add(MENU_SEPARATOR);
172        menuItems.add(makeMenuItem("Import", this, "importFormulas"));
173        menuItems.add(makeMenuItem("Export", this, "exportFormulas"));
174        return menuItems;
175    }
176    
177}