Project: ib-ruby
// This file is part of the "IBController".
// Copyright (C) 2004 Steven M. Kearns ([email protected] ) 
// Copyright (C) 2004 - 2011 Richard L King ([email protected]) 
// For conditions of distribution and use, see copyright notice in COPYING.txt 
 
// IBController is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
 
// IBController is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more details. 
 
// You should have received a copy of the GNU General Public License 
// along with IBController.  If not, see <http://www.gnu.org/licenses/>. 
 
package ibcontroller; 
 
import javax.swing.JButton; 
import javax.swing.JCheckBox; 
import javax.swing.JCheckBoxMenuItem; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JTree; 
import javax.swing.tree.TreePath; 
 
class ConfigureApiTask implements Runnable{ 
 
    private static final SwitchLock _Running = new SwitchLock(); 
 
    private final CommandChannel mChannel; 
 
    ConfigureApiTask(final CommandChannel channel) { 
        mChannel = channel; 
    } 
 
    @Override 
    public void run() { 
        if (! _Running.set()) { 
            mChannel.writeNack("API configuration already in progress"); 
            return
        } 
 
        try { 
            waitForMainWindow(); 
            configureAPI(); 
        } catch (Exception ex) { 
            mChannel.writeNack(ex.getMessage()); 
        } finally { 
            _Running.clear(); 
        } 
    } 
 
    private void completeConfigureItViaEditMenu() { 
        Utils.logToConsole("Completing ENABLEAPI configuration"); 
        JDialog configDialog = TwsListener.getConfigDialog(); 
        if (configDialog == null) { 
            System.err.println("IBControllerServer: could not find the Global Configuration dialog"); 
            mChannel.writeNack("Global Configuration dialog not found"); 
            return
        } 
        JTree configTree = Utils.findTree(configDialog); 
        if (configTree == null) { 
            System.err.println("IBControllerServer: could not find the config tree in the Global Configuration dialog"); 
            mChannel.writeNack("config tree not found"); 
            return
        } 
        TreePath tp = new TreePath(configTree.getModel().getRoot()); 
        Object node = Utils.findChildNode(configTree.getModel(), configTree.getModel().getRoot(), "API"); 
        tp = tp.pathByAddingChild(node); 
 
        // later versions of TWS have a Settings node below the API node 
        node = Utils.findChildNode(configTree.getModel(), node, "Settings"); 
        if (!(node == null)) tp = tp.pathByAddingChild(node); 
 
        Utils.logToConsole("getExpandsSelectedPaths = " + configTree.getExpandsSelectedPaths()); 
        Utils.logToConsole("Selection path = " + tp.toString()); 
        configTree.setSelectionPath(tp); 
 
        JCheckBox cb = Utils.findCheckBox(configDialog, "Enable ActiveX and Socket Clients"); 
        if (cb == null) { 
            System.err.println("IBControllerServer: Could not find Enable ActiveX checkbox inside API menu."); 
            mChannel.writeNack("Enable ActiveX checkbox not found"); 
            return
        } 
        if (!cb.isSelected()) { 
            cb.doClick(); 
            Utils.clickButton(configDialog, "OK"); 
            Utils.logToConsole("TWS has been configured to accept API connections."); 
            mChannel.writeAck("configured"); 
        } else { 
            Utils.logToConsole("TWS is already configured to accept API connections."); 
            mChannel.writeAck("already configured"); 
        } 
 
        configDialog.setVisible(false); 
    } 
 
    private void configureAPI() { 
        GuiSynchronousExecutor.instance().execute(new Runnable(){ 
            public void run() {configureIt();} 
        }); 
    } 
 
    private void configureIt() { 
        JFrame jf = TwsListener.getMainWindow(); 
        if (jf == null) { 
            System.err.println("IBControllerServer: could not find main window to configure API"); 
             mChannel.writeNack("main window not found"); 
            return
        } 
 
        Utils.logToConsole("Attempting to configure API"); 
 
        JMenuItem jmi = Utils.findMenuItem(jf, new String[] {"Configure""API""Enable ActiveX and Socket Clients"}); 
        if (jmi != null) { 
            configureItViaConfigureMenu((JCheckBoxMenuItem)jmi); 
        } else { 
            jmi = Utils.findMenuItem(jf, new String[] {"Edit""Global Configuration..."}); 
            if (jmi != null) { 
                configureItViaEditMenu(jmi); 
            } else { 
                System.err.println("IBControllerServer: could not find Configure > API > Enable ActiveX or Edit > Global Configuration menus"); 
                mChannel.writeNack("Configure > API > Enable ActiveX or Edit > Global Configuration menus not found"); 
            } 
        } 
   } 
 
    private boolean configureItViaConfigureMenu(JCheckBoxMenuItem cmi) { 
        if (!cmi.isSelected()) { 
            cmi.doClick(); 
            Utils.logToConsole("TWS has been configured to accept API connections."); 
            mChannel.writeAck("configured"); 
        } else { 
            Utils.logToConsole("TWS is already configured to accept API connections."); 
            mChannel.writeAck("already configured"); 
        } 
        return true
    } 
 
    private void configureItViaEditMenu(JMenuItem jmi) { 
        Utils.logToConsole("Click Edit > Global Configuration..."); 
        jmi.doClick(); 
 
        GuiDeferredExecutor.instance().execute(new Runnable(){ 
            public void run() {completeConfigureItViaEditMenu();} 
        }); 
 
    } 
 
    private Boolean waitForMainWindow() { 
       if (TwsListener.getMainWindow() != null) { 
            return true
        } else { 
            // Need to wait until TWS is finished loading. 
            // Not really sure when this is, but we will wait 5 seconds 
            // after finding the main window. 
 
            int count = 0
            int maxcount = 300
            mChannel.writeInfo("Waiting for TWS to load"); 
            while (TwsListener.getMainWindow() == null) { 
                if (count++ >= maxcount) { 
                    System.err.println("IBControllerServer: IB TWS did not load successfully."); 
                    mChannel.writeNack("IBControllerServer: IB TWS did not load successfully."); 
                    return false
                } 
                if (count % 10 == 0) mChannel.writeInfo("Waiting for TWS to load"); 
                Utils.pause(1000); 
            } 
            Utils.pause(5000); 
            return true
        } 
    } 
}