public static void showTab(String name) {
        if (treeView != null)
            treeView.showTab(name);
        if (paletteView != null)
            paletteView.showTab(name);
    }

package org.jcryptool.core.views;

import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.Category;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.CommandManager;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.services.IServiceLocator;
import org.jcryptool.core.operations.CommandInfo;
import org.jcryptool.core.operations.IOperationsConstants;
import org.jcryptool.core.operations.OperationsPlugin;
import org.jcryptool.core.operations.algorithm.ShadowAlgorithmHandler;
import org.jcryptool.core.util.colors.ColorService;
import org.jcryptool.core.util.images.ImageService;
import org.jcryptool.core.views.content.PaletteView;
import org.jcryptool.core.views.content.TreeView;

/**
 * Displays all available algorithms in a tree or palette view.
 *
 * @author t-kern
 * @author Holger Friedrich (support for Commands)
 * @version 0.9.3
 */
public class AlgorithmView extends ViewPart implements IOperationsConstants {

    public static final String ID = "org.jcryptool.core.views.AlgorithmView";

    public static final String MENU_TEXT_ALGORITHM = Messages.AlgorithmView_menu_text_algorithms;

    public static final String MENU_TEXT_ANALYSIS = Messages.AlgorithmView_menu_text_analysis;

    public static final String MENU_TEXT_VISUALS = Messages.AlgorithmView_menu_text_visuals;

    public static final String MENU_TEXT_GAMES = Messages.AlgorithmView_menu_text_games;

    private static final int VIEW_TREE = 0x00;

    private static final int VIEW_PALETTE = 0x01;

    private static TreeView treeView;

    private static PaletteView paletteView;

    private static StackLayout layout;

    private Composite listing;

    private boolean initialSearchState = true;

    // black
    private static final Color COLOR_FILTER_USER = ColorService.BLACK;

    // gray
    private static final Color COLOR_FILTER_INITIAL = ColorService.getColor(SWT.COLOR_GRAY);

    private static ArrayList<ShadowAlgorithmHandler> algorithmTypes = new ArrayList<ShadowAlgorithmHandler>();

    public static AlgorithmView instance;

    final static String showPaletteCommandId = ViewsPlugin.PLUGIN_ID + ".commands.showPalette";

    final static String showTreeCommandId = ViewsPlugin.PLUGIN_ID + ".commands.showTree";

    private ICommandService commandService;

    private Category autogeneratedCategory;

    private IServiceLocator serviceLocator;

    AbstractHandler showPaletteHandler;

    AbstractHandler showTreeHandler;

    CommandContributionItem showPaletteContributionItem;

    CommandContributionItem showTreeContributionItem;

    public AlgorithmView() {
        PlatformUI.getPreferenceStore().setDefault("showView", VIEW_PALETTE);
        loadAlgorithms();
        AlgorithmView.instance = this;
    }

    /**
     * This is a callback that will allow us to create the org.jcryptool.core.views content and
     * initialize it.
     */
    @Override
    public void createPartControl(final Composite parent) {
        GridLayout outerLayout = new GridLayout(2, false);
        outerLayout.horizontalSpacing = 0;
        outerLayout.verticalSpacing = 0;
        outerLayout.marginHeight = 0;
        outerLayout.marginWidth = 0;
        parent.setLayout(outerLayout);
        parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        createSearchArea(parent);
        createViewArea(parent);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, ViewsPlugin.PLUGIN_ID + ".algorithmsView");
    }

    public static void showBubble(String string) {
        PaletteView viewer = paletteView;
        if (!viewer.getControl().isVisible()) {
            Control control = viewer.getControl();
            Shell shell = viewer.getControl().getShell();
            final ToolTip tip = new ToolTip(shell, SWT.BALLOON);
            tip.setMessage(string);
            tip.setVisible(true);
            tip.setLocation(control.toDisplay(control.getSize().x, 0));
            tip.setAutoHide(true);
        } else {
            viewer.getControl().addPaintListener(new PaintListener() {

                private boolean doneThis = false;

                @Override
                public void paintControl(PaintEvent e) {
                    if (doneThis) {
                        return;
                    } else {
                        doneThis = true;
                    }
                    Control control = viewer.getControl();
                    Shell shell = viewer.getControl().getShell();
                    final ToolTip tip = new ToolTip(shell, SWT.BALLOON);
                    tip.setMessage(string);
                    tip.setVisible(true);
                    tip.setLocation(control.toDisplay(control.getSize().x, 0));
                    tip.setAutoHide(true);
                }
            });
        }
    }

    private void defineCommand(final String commandId, final String name, AbstractHandler handler) {
        Command command = commandService.getCommand(commandId);
        command.define(name, null, autogeneratedCategory);
        command.setHandler(handler);
    }

    private CommandContributionItem createContributionItem(final String commandId, final ImageDescriptor icon, final String tooltip) {
        CommandContributionItemParameter param = new CommandContributionItemParameter(serviceLocator, null, commandId, SWT.PUSH);
        if (icon != null)
            param.icon = icon;
        if (tooltip != null && !tooltip.equals(""))
            param.tooltip = tooltip;
        CommandContributionItem item = new CommandContributionItem(param);
        return (item);
    }

    /**
     * creates the area containing the views
     *
     * @param parent the parent composite
     */
    private void createViewArea(Composite parent) {
        layout = new StackLayout();
        listing = new Composite(parent, SWT.NONE);
        listing.setLayout(layout);
        listing.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
        // create both views
        paletteView = new PaletteView(listing);
        treeView = new TreeView(listing);
        showTab(MENU_TEXT_ALGORITHM);
        // create the command to switch the views
        // This may be a little tricky to translate to Commands.
        // The Action seems to change its own text, tool tip and icon when it is invoked...
        // Perhaps we should create two CommandContributionItems and switch between them
        // as the view style is switched from palette to tree and vice versa.
        showPaletteHandler = new AbstractHandler() {

            @Override
            public Object execute(ExecutionEvent event) {
                layout.topControl = paletteView.getControl();
                PlatformUI.getPreferenceStore().setValue("showView", VIEW_PALETTE);
                listing.layout();
                IMenuManager manager = getViewSite().getActionBars().getMenuManager();
                manager.removeAll();
                manager.add(showTreeContributionItem);
                return (null);
            }
        };
        showTreeHandler = new AbstractHandler() {

            @Override
            public Object execute(ExecutionEvent event) {
                layout.topControl = treeView.getControl();
                PlatformUI.getPreferenceStore().setValue("showView", VIEW_TREE);
                listing.layout();
                IMenuManager manager = getViewSite().getActionBars().getMenuManager();
                manager.removeAll();
                manager.add(showPaletteContributionItem);
                return (null);
            }
        };
        serviceLocator = PlatformUI.getWorkbench();
        commandService = serviceLocator.getService(ICommandService.class);
        autogeneratedCategory = commandService.getCategory(CommandManager.AUTOGENERATED_CATEGORY_ID);
        defineCommand(showPaletteCommandId, Messages.AlgorithmView_showPalette, showPaletteHandler);
        defineCommand(showTreeCommandId, Messages.AlgorithmView_showTree, showTreeHandler);
        showPaletteContributionItem = createContributionItem(showPaletteCommandId, ImageService.getImageDescriptor(ViewsPlugin.PLUGIN_ID, "icons/switch.gif"), Messages.AlgorithmView_showPalette);
        showTreeContributionItem = createContributionItem(showTreeCommandId, ImageService.getImageDescriptor(ViewsPlugin.PLUGIN_ID, "icons/switch.gif"), Messages.AlgorithmView_showTree);
        // set the correct view to be shown and assign the corresponding action
        IMenuManager manager = getViewSite().getActionBars().getMenuManager();
        switch(PlatformUI.getPreferenceStore().getInt("showView")) {
            case VIEW_PALETTE:
                layout.topControl = paletteView.getControl();
                manager.add(showTreeContributionItem);
                break;
            default:
                layout.topControl = treeView.getControl();
                manager.add(showPaletteContributionItem);
        }
    }

    /**
     * Creates the search field. On Mac the text does contain a clear (reset) icon which resets
     * the view filter. Since Windows does not support this an additional clear (reset) icon
     * is shown next to the text.
     *
     * @param parent The parent composite
     */
    private void createSearchArea(Composite parent) {
        // search field
        final Text search = new Text(parent, SWT.SEARCH | SWT.ICON_CANCEL | SWT.ICON_SEARCH);
        if ((search.getStyle() & SWT.CANCEL) == 0) {
            // reset search button for systems that do not support the cancel icon
            Canvas canvas = new Canvas(parent, SWT.NONE);
            GridData gridData = new GridData();
            gridData.heightHint = 18;
            gridData.widthHint = 18;
            canvas.setLayoutData(gridData);
            canvas.addPaintListener(new PaintListener() {

                @Override
                public void paintControl(PaintEvent e) {
                    e.gc.drawImage(ImageService.getImage(ViewsPlugin.PLUGIN_ID, "icons/clear.gif"), 1, 1);
                }
            });
            canvas.addMouseListener(new MouseAdapter() {

                @Override
                public void mouseUp(MouseEvent e) {
                    search.setText(Messages.AlgorithmView_search_message);
                    search.setForeground(COLOR_FILTER_INITIAL);
                    initialSearchState = true;
                    treeView.setFilter("");
                    paletteView.setFilter("");
                }
            });
        }
        search.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        search.setText(Messages.AlgorithmView_search_message);
        search.setForeground(COLOR_FILTER_INITIAL);
        search.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseDown(MouseEvent e) {
                if (initialSearchState) {
                    search.setText("");
                    search.setForeground(COLOR_FILTER_USER);
                    initialSearchState = false;
                }
            }
        });
        search.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                treeView.setFilter(search.getText());
                paletteView.setFilter(search.getText());
            }
        });
        search.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                if (e.detail == SWT.CANCEL) {
                    search.setText(Messages.AlgorithmView_search_message);
                    search.setForeground(COLOR_FILTER_INITIAL);
                    initialSearchState = true;
                    treeView.setFilter("");
                    paletteView.setFilter("");
                }
            }
        });
    }

    /**
     * used to trigger actions when an algorithm is drag&dropped to an editor
     *
     * @param algorithmName the name of the algorithm whose action is to be done
     */
    public static void doAction(String algorithmName) {
        Iterator<ShadowAlgorithmHandler> it9 = algorithmTypes.iterator();
        ShadowAlgorithmHandler handler = null;
        while (it9.hasNext()) {
            handler = it9.next();
            // TODO the text property doesn't belong in the Handler but in the CommandInfo
            if (algorithmName.equals(handler.getText())) {
                // TODO maybe Command.executeWithChecks() should be called here, which also requires an ExecutionEvent
                handler.execute(null);
            }
        }
    }

    /**
     * Passing the focus request to the org.jcryptool.core.views.content's control.
     */
    @Override
    public void setFocus() {
        switch(PlatformUI.getPreferenceStore().getInt("showView")) {
            case VIEW_PALETTE:
                paletteView.getControl().setFocus();
                break;
            default:
                treeView.getControl().setFocus();
        }
    }

    /**
     * Displays messages in a MessageDialog
     *
     * @param message the message text
     */
    public static void showMessage(String message) {
        MessageDialog.openInformation(null, Messages.AlgorithmView_0, message);
    }

    /**
     * sets the viewers to display the given tab
     *
     * @param name the name of the tab to display
     */

    public static void showContextHelp(final String extensionPointId, final String name) {
        IConfigurationElement[] elements = Platform.getExtensionRegistry().getExtensionPoint(extensionPointId).getConfigurationElements();
        for (IConfigurationElement element : elements) {
            if (element.getAttribute("name").equals(name)) {
                final String contextHelpId = element.getAttribute("contextHelpId");
                if (contextHelpId != null && !"".equals(contextHelpId)) {
                    PlatformUI.getWorkbench().getHelpSystem().displayHelp(contextHelpId);
                } else {
                    PlatformUI.getWorkbench().getHelpSystem().displayHelp(ViewsPlugin.PLUGIN_ID + ".algorithmsView");
                }
                return;
            }
        }
    }

    private void loadAlgorithms() {
        CommandInfo[] commands = OperationsPlugin.getDefault().getAlgorithmsManager().getShadowAlgorithmCommands();
        for (int i = 0, length = commands.length; i < length; i++) {
            AbstractHandler handler = commands[i].getHandler();
            if (!algorithmTypes.contains((handler))) {
                algorithmTypes.add(((ShadowAlgorithmHandler) handler));
            }
        }
        // This didn't quite support the case when we have a Handler rather than an Action in the CommandOrAction.
        // I think I now added Handler support.
        // TODO Is this loadAlgorithms() method used anywhere?
    }
}


switch(PlatformUI.getPreferenceStore().getInt("showView")) {
            case VIEW_PALETTE:
                paletteView.getControl().setFocus();
                break;
            default:
                treeView.getControl().setFocus();
        }

package org.jcryptool.core.views;

import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.Category;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.CommandManager;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.services.IServiceLocator;
import org.jcryptool.core.operations.CommandInfo;
import org.jcryptool.core.operations.IOperationsConstants;
import org.jcryptool.core.operations.OperationsPlugin;
import org.jcryptool.core.operations.algorithm.ShadowAlgorithmHandler;
import org.jcryptool.core.util.colors.ColorService;
import org.jcryptool.core.util.images.ImageService;
import org.jcryptool.core.views.content.PaletteView;
import org.jcryptool.core.views.content.TreeView;

/**
 * Displays all available algorithms in a tree or palette view.
 *
 * @author t-kern
 * @author Holger Friedrich (support for Commands)
 * @version 0.9.3
 */
public class AlgorithmView extends ViewPart implements IOperationsConstants {

    public static final String ID = "org.jcryptool.core.views.AlgorithmView";

    public static final String MENU_TEXT_ALGORITHM = Messages.AlgorithmView_menu_text_algorithms;

    public static final String MENU_TEXT_ANALYSIS = Messages.AlgorithmView_menu_text_analysis;

    public static final String MENU_TEXT_VISUALS = Messages.AlgorithmView_menu_text_visuals;

    public static final String MENU_TEXT_GAMES = Messages.AlgorithmView_menu_text_games;

    private static final int VIEW_TREE = 0x00;

    private static final int VIEW_PALETTE = 0x01;

    private static TreeView treeView;

    private static PaletteView paletteView;

    private static StackLayout layout;

    private Composite listing;

    private boolean initialSearchState = true;

    // black
    private static final Color COLOR_FILTER_USER = ColorService.BLACK;

    // gray
    private static final Color COLOR_FILTER_INITIAL = ColorService.getColor(SWT.COLOR_GRAY);

    private static ArrayList<ShadowAlgorithmHandler> algorithmTypes = new ArrayList<ShadowAlgorithmHandler>();

    public static AlgorithmView instance;

    final static String showPaletteCommandId = ViewsPlugin.PLUGIN_ID + ".commands.showPalette";

    final static String showTreeCommandId = ViewsPlugin.PLUGIN_ID + ".commands.showTree";

    private ICommandService commandService;

    private Category autogeneratedCategory;

    private IServiceLocator serviceLocator;

    AbstractHandler showPaletteHandler;

    AbstractHandler showTreeHandler;

    CommandContributionItem showPaletteContributionItem;

    CommandContributionItem showTreeContributionItem;

    public AlgorithmView() {
        PlatformUI.getPreferenceStore().setDefault("showView", VIEW_PALETTE);
        loadAlgorithms();
        AlgorithmView.instance = this;
    }

    /**
     * This is a callback that will allow us to create the org.jcryptool.core.views content and
     * initialize it.
     */
    @Override
    public void createPartControl(final Composite parent) {
        GridLayout outerLayout = new GridLayout(2, false);
        outerLayout.horizontalSpacing = 0;
        outerLayout.verticalSpacing = 0;
        outerLayout.marginHeight = 0;
        outerLayout.marginWidth = 0;
        parent.setLayout(outerLayout);
        parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        createSearchArea(parent);
        createViewArea(parent);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, ViewsPlugin.PLUGIN_ID + ".algorithmsView");
    }

    public static void showBubble(String string) {
        PaletteView viewer = paletteView;
        if (!viewer.getControl().isVisible()) {
            Control control = viewer.getControl();
            Shell shell = viewer.getControl().getShell();
            final ToolTip tip = new ToolTip(shell, SWT.BALLOON);
            tip.setMessage(string);
            tip.setVisible(true);
            tip.setLocation(control.toDisplay(control.getSize().x, 0));
            tip.setAutoHide(true);
        } else {
            viewer.getControl().addPaintListener(new PaintListener() {

                private boolean doneThis = false;

                @Override
                public void paintControl(PaintEvent e) {
                    if (doneThis) {
                        return;
                    } else {
                        doneThis = true;
                    }
                    Control control = viewer.getControl();
                    Shell shell = viewer.getControl().getShell();
                    final ToolTip tip = new ToolTip(shell, SWT.BALLOON);
                    tip.setMessage(string);
                    tip.setVisible(true);
                    tip.setLocation(control.toDisplay(control.getSize().x, 0));
                    tip.setAutoHide(true);
                }
            });
        }
    }

    private void defineCommand(final String commandId, final String name, AbstractHandler handler) {
        Command command = commandService.getCommand(commandId);
        command.define(name, null, autogeneratedCategory);
        command.setHandler(handler);
    }

    private CommandContributionItem createContributionItem(final String commandId, final ImageDescriptor icon, final String tooltip) {
        CommandContributionItemParameter param = new CommandContributionItemParameter(serviceLocator, null, commandId, SWT.PUSH);
        if (icon != null)
            param.icon = icon;
        if (tooltip != null && !tooltip.equals(""))
            param.tooltip = tooltip;
        CommandContributionItem item = new CommandContributionItem(param);
        return (item);
    }

    /**
     * creates the area containing the views
     *
     * @param parent the parent composite
     */
    private void createViewArea(Composite parent) {
        layout = new StackLayout();
        listing = new Composite(parent, SWT.NONE);
        listing.setLayout(layout);
        listing.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
        // create both views
        paletteView = new PaletteView(listing);
        treeView = new TreeView(listing);
        showTab(MENU_TEXT_ALGORITHM);
        // create the command to switch the views
        // This may be a little tricky to translate to Commands.
        // The Action seems to change its own text, tool tip and icon when it is invoked...
        // Perhaps we should create two CommandContributionItems and switch between them
        // as the view style is switched from palette to tree and vice versa.
        showPaletteHandler = new AbstractHandler() {

            @Override
            public Object execute(ExecutionEvent event) {
                layout.topControl = paletteView.getControl();
                PlatformUI.getPreferenceStore().setValue("showView", VIEW_PALETTE);
                listing.layout();
                IMenuManager manager = getViewSite().getActionBars().getMenuManager();
                manager.removeAll();
                manager.add(showTreeContributionItem);
                return (null);
            }
        };
        showTreeHandler = new AbstractHandler() {

            @Override
            public Object execute(ExecutionEvent event) {
                layout.topControl = treeView.getControl();
                PlatformUI.getPreferenceStore().setValue("showView", VIEW_TREE);
                listing.layout();
                IMenuManager manager = getViewSite().getActionBars().getMenuManager();
                manager.removeAll();
                manager.add(showPaletteContributionItem);
                return (null);
            }
        };
        serviceLocator = PlatformUI.getWorkbench();
        commandService = serviceLocator.getService(ICommandService.class);
        autogeneratedCategory = commandService.getCategory(CommandManager.AUTOGENERATED_CATEGORY_ID);
        defineCommand(showPaletteCommandId, Messages.AlgorithmView_showPalette, showPaletteHandler);
        defineCommand(showTreeCommandId, Messages.AlgorithmView_showTree, showTreeHandler);
        showPaletteContributionItem = createContributionItem(showPaletteCommandId, ImageService.getImageDescriptor(ViewsPlugin.PLUGIN_ID, "icons/switch.gif"), Messages.AlgorithmView_showPalette);
        showTreeContributionItem = createContributionItem(showTreeCommandId, ImageService.getImageDescriptor(ViewsPlugin.PLUGIN_ID, "icons/switch.gif"), Messages.AlgorithmView_showTree);
        // set the correct view to be shown and assign the corresponding action
        IMenuManager manager = getViewSite().getActionBars().getMenuManager();
        switch(PlatformUI.getPreferenceStore().getInt("showView")) {
            case VIEW_PALETTE:
                layout.topControl = paletteView.getControl();
                manager.add(showTreeContributionItem);
                break;
            default:
                layout.topControl = treeView.getControl();
                manager.add(showPaletteContributionItem);
        }
    }

    /**
     * Creates the search field. On Mac the text does contain a clear (reset) icon which resets
     * the view filter. Since Windows does not support this an additional clear (reset) icon
     * is shown next to the text.
     *
     * @param parent The parent composite
     */
    private void createSearchArea(Composite parent) {
        // search field
        final Text search = new Text(parent, SWT.SEARCH | SWT.ICON_CANCEL | SWT.ICON_SEARCH);
        if ((search.getStyle() & SWT.CANCEL) == 0) {
            // reset search button for systems that do not support the cancel icon
            Canvas canvas = new Canvas(parent, SWT.NONE);
            GridData gridData = new GridData();
            gridData.heightHint = 18;
            gridData.widthHint = 18;
            canvas.setLayoutData(gridData);
            canvas.addPaintListener(new PaintListener() {

                @Override
                public void paintControl(PaintEvent e) {
                    e.gc.drawImage(ImageService.getImage(ViewsPlugin.PLUGIN_ID, "icons/clear.gif"), 1, 1);
                }
            });
            canvas.addMouseListener(new MouseAdapter() {

                @Override
                public void mouseUp(MouseEvent e) {
                    search.setText(Messages.AlgorithmView_search_message);
                    search.setForeground(COLOR_FILTER_INITIAL);
                    initialSearchState = true;
                    treeView.setFilter("");
                    paletteView.setFilter("");
                }
            });
        }
        search.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        search.setText(Messages.AlgorithmView_search_message);
        search.setForeground(COLOR_FILTER_INITIAL);
        search.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseDown(MouseEvent e) {
                if (initialSearchState) {
                    search.setText("");
                    search.setForeground(COLOR_FILTER_USER);
                    initialSearchState = false;
                }
            }
        });
        search.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                treeView.setFilter(search.getText());
                paletteView.setFilter(search.getText());
            }
        });
        search.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                if (e.detail == SWT.CANCEL) {
                    search.setText(Messages.AlgorithmView_search_message);
                    search.setForeground(COLOR_FILTER_INITIAL);
                    initialSearchState = true;
                    treeView.setFilter("");
                    paletteView.setFilter("");
                }
            }
        });
    }

    /**
     * used to trigger actions when an algorithm is drag&dropped to an editor
     *
     * @param algorithmName the name of the algorithm whose action is to be done
     */
    public static void doAction(String algorithmName) {
        Iterator<ShadowAlgorithmHandler> it9 = algorithmTypes.iterator();
        ShadowAlgorithmHandler handler = null;
        while (it9.hasNext()) {
            handler = it9.next();
            // TODO the text property doesn't belong in the Handler but in the CommandInfo
            if (algorithmName.equals(handler.getText())) {
                // TODO maybe Command.executeWithChecks() should be called here, which also requires an ExecutionEvent
                handler.execute(null);
            }
        }
    }

    /**
     * Passing the focus request to the org.jcryptool.core.views.content's control.
     */
    @Override
    public void setFocus() {

    }

    /**
     * Displays messages in a MessageDialog
     *
     * @param message the message text
     */
    public static void showMessage(String message) {
        MessageDialog.openInformation(null, Messages.AlgorithmView_0, message);
    }

    /**
     * sets the viewers to display the given tab
     *
     * @param name the name of the tab to display
     */
    public static void showTab(String name) {
        if (treeView != null)
            treeView.showTab(name);
        if (paletteView != null)
            paletteView.showTab(name);
    }

    public static void showContextHelp(final String extensionPointId, final String name) {
        IConfigurationElement[] elements = Platform.getExtensionRegistry().getExtensionPoint(extensionPointId).getConfigurationElements();
        for (IConfigurationElement element : elements) {
            if (element.getAttribute("name").equals(name)) {
                final String contextHelpId = element.getAttribute("contextHelpId");
                if (contextHelpId != null && !"".equals(contextHelpId)) {
                    PlatformUI.getWorkbench().getHelpSystem().displayHelp(contextHelpId);
                } else {
                    PlatformUI.getWorkbench().getHelpSystem().displayHelp(ViewsPlugin.PLUGIN_ID + ".algorithmsView");
                }
                return;
            }
        }
    }

    private void loadAlgorithms() {
        CommandInfo[] commands = OperationsPlugin.getDefault().getAlgorithmsManager().getShadowAlgorithmCommands();
        for (int i = 0, length = commands.length; i < length; i++) {
            AbstractHandler handler = commands[i].getHandler();
            if (!algorithmTypes.contains((handler))) {
                algorithmTypes.add(((ShadowAlgorithmHandler) handler));
            }
        }
        // This didn't quite support the case when we have a Handler rather than an Action in the CommandOrAction.
        // I think I now added Handler support.
        // TODO Is this loadAlgorithms() method used anywhere?
    }
}


for (int i = 0, length = commands.length; i < length; i++) {
            AbstractHandler handler = commands[i].getHandler();
            if (!algorithmTypes.contains((handler))) {
                algorithmTypes.add(((ShadowAlgorithmHandler) handler));
            }
        }

package org.jcryptool.core.views;

import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.Category;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.CommandManager;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.services.IServiceLocator;
import org.jcryptool.core.operations.CommandInfo;
import org.jcryptool.core.operations.IOperationsConstants;
import org.jcryptool.core.operations.OperationsPlugin;
import org.jcryptool.core.operations.algorithm.ShadowAlgorithmHandler;
import org.jcryptool.core.util.colors.ColorService;
import org.jcryptool.core.util.images.ImageService;
import org.jcryptool.core.views.content.PaletteView;
import org.jcryptool.core.views.content.TreeView;

/**
 * Displays all available algorithms in a tree or palette view.
 *
 * @author t-kern
 * @author Holger Friedrich (support for Commands)
 * @version 0.9.3
 */
public class AlgorithmView extends ViewPart implements IOperationsConstants {

    public static final String ID = "org.jcryptool.core.views.AlgorithmView";

    public static final String MENU_TEXT_ALGORITHM = Messages.AlgorithmView_menu_text_algorithms;

    public static final String MENU_TEXT_ANALYSIS = Messages.AlgorithmView_menu_text_analysis;

    public static final String MENU_TEXT_VISUALS = Messages.AlgorithmView_menu_text_visuals;

    public static final String MENU_TEXT_GAMES = Messages.AlgorithmView_menu_text_games;

    private static final int VIEW_TREE = 0x00;

    private static final int VIEW_PALETTE = 0x01;

    private static TreeView treeView;

    private static PaletteView paletteView;

    private static StackLayout layout;

    private Composite listing;

    private boolean initialSearchState = true;

    // black
    private static final Color COLOR_FILTER_USER = ColorService.BLACK;

    // gray
    private static final Color COLOR_FILTER_INITIAL = ColorService.getColor(SWT.COLOR_GRAY);

    private static ArrayList<ShadowAlgorithmHandler> algorithmTypes = new ArrayList<ShadowAlgorithmHandler>();

    public static AlgorithmView instance;

    final static String showPaletteCommandId = ViewsPlugin.PLUGIN_ID + ".commands.showPalette";

    final static String showTreeCommandId = ViewsPlugin.PLUGIN_ID + ".commands.showTree";

    private ICommandService commandService;

    private Category autogeneratedCategory;

    private IServiceLocator serviceLocator;

    AbstractHandler showPaletteHandler;

    AbstractHandler showTreeHandler;

    CommandContributionItem showPaletteContributionItem;

    CommandContributionItem showTreeContributionItem;

    public AlgorithmView() {
        PlatformUI.getPreferenceStore().setDefault("showView", VIEW_PALETTE);
        loadAlgorithms();
        AlgorithmView.instance = this;
    }

    /**
     * This is a callback that will allow us to create the org.jcryptool.core.views content and
     * initialize it.
     */
    @Override
    public void createPartControl(final Composite parent) {
        GridLayout outerLayout = new GridLayout(2, false);
        outerLayout.horizontalSpacing = 0;
        outerLayout.verticalSpacing = 0;
        outerLayout.marginHeight = 0;
        outerLayout.marginWidth = 0;
        parent.setLayout(outerLayout);
        parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        createSearchArea(parent);
        createViewArea(parent);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, ViewsPlugin.PLUGIN_ID + ".algorithmsView");
    }

    public static void showBubble(String string) {
        PaletteView viewer = paletteView;
        if (!viewer.getControl().isVisible()) {
            Control control = viewer.getControl();
            Shell shell = viewer.getControl().getShell();
            final ToolTip tip = new ToolTip(shell, SWT.BALLOON);
            tip.setMessage(string);
            tip.setVisible(true);
            tip.setLocation(control.toDisplay(control.getSize().x, 0));
            tip.setAutoHide(true);
        } else {
            viewer.getControl().addPaintListener(new PaintListener() {

                private boolean doneThis = false;

                @Override
                public void paintControl(PaintEvent e) {
                    if (doneThis) {
                        return;
                    } else {
                        doneThis = true;
                    }
                    Control control = viewer.getControl();
                    Shell shell = viewer.getControl().getShell();
                    final ToolTip tip = new ToolTip(shell, SWT.BALLOON);
                    tip.setMessage(string);
                    tip.setVisible(true);
                    tip.setLocation(control.toDisplay(control.getSize().x, 0));
                    tip.setAutoHide(true);
                }
            });
        }
    }

    private void defineCommand(final String commandId, final String name, AbstractHandler handler) {
        Command command = commandService.getCommand(commandId);
        command.define(name, null, autogeneratedCategory);
        command.setHandler(handler);
    }

    private CommandContributionItem createContributionItem(final String commandId, final ImageDescriptor icon, final String tooltip) {
        CommandContributionItemParameter param = new CommandContributionItemParameter(serviceLocator, null, commandId, SWT.PUSH);
        if (icon != null)
            param.icon = icon;
        if (tooltip != null && !tooltip.equals(""))
            param.tooltip = tooltip;
        CommandContributionItem item = new CommandContributionItem(param);
        return (item);
    }

    /**
     * creates the area containing the views
     *
     * @param parent the parent composite
     */
    private void createViewArea(Composite parent) {
        layout = new StackLayout();
        listing = new Composite(parent, SWT.NONE);
        listing.setLayout(layout);
        listing.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
        // create both views
        paletteView = new PaletteView(listing);
        treeView = new TreeView(listing);
        showTab(MENU_TEXT_ALGORITHM);
        // create the command to switch the views
        // This may be a little tricky to translate to Commands.
        // The Action seems to change its own text, tool tip and icon when it is invoked...
        // Perhaps we should create two CommandContributionItems and switch between them
        // as the view style is switched from palette to tree and vice versa.
        showPaletteHandler = new AbstractHandler() {

            @Override
            public Object execute(ExecutionEvent event) {
                layout.topControl = paletteView.getControl();
                PlatformUI.getPreferenceStore().setValue("showView", VIEW_PALETTE);
                listing.layout();
                IMenuManager manager = getViewSite().getActionBars().getMenuManager();
                manager.removeAll();
                manager.add(showTreeContributionItem);
                return (null);
            }
        };
        showTreeHandler = new AbstractHandler() {

            @Override
            public Object execute(ExecutionEvent event) {
                layout.topControl = treeView.getControl();
                PlatformUI.getPreferenceStore().setValue("showView", VIEW_TREE);
                listing.layout();
                IMenuManager manager = getViewSite().getActionBars().getMenuManager();
                manager.removeAll();
                manager.add(showPaletteContributionItem);
                return (null);
            }
        };
        serviceLocator = PlatformUI.getWorkbench();
        commandService = serviceLocator.getService(ICommandService.class);
        autogeneratedCategory = commandService.getCategory(CommandManager.AUTOGENERATED_CATEGORY_ID);
        defineCommand(showPaletteCommandId, Messages.AlgorithmView_showPalette, showPaletteHandler);
        defineCommand(showTreeCommandId, Messages.AlgorithmView_showTree, showTreeHandler);
        showPaletteContributionItem = createContributionItem(showPaletteCommandId, ImageService.getImageDescriptor(ViewsPlugin.PLUGIN_ID, "icons/switch.gif"), Messages.AlgorithmView_showPalette);
        showTreeContributionItem = createContributionItem(showTreeCommandId, ImageService.getImageDescriptor(ViewsPlugin.PLUGIN_ID, "icons/switch.gif"), Messages.AlgorithmView_showTree);
        // set the correct view to be shown and assign the corresponding action
        IMenuManager manager = getViewSite().getActionBars().getMenuManager();
        switch(PlatformUI.getPreferenceStore().getInt("showView")) {
            case VIEW_PALETTE:
                layout.topControl = paletteView.getControl();
                manager.add(showTreeContributionItem);
                break;
            default:
                layout.topControl = treeView.getControl();
                manager.add(showPaletteContributionItem);
        }
    }

    /**
     * Creates the search field. On Mac the text does contain a clear (reset) icon which resets
     * the view filter. Since Windows does not support this an additional clear (reset) icon
     * is shown next to the text.
     *
     * @param parent The parent composite
     */
    private void createSearchArea(Composite parent) {
        // search field
        final Text search = new Text(parent, SWT.SEARCH | SWT.ICON_CANCEL | SWT.ICON_SEARCH);
        if ((search.getStyle() & SWT.CANCEL) == 0) {
            // reset search button for systems that do not support the cancel icon
            Canvas canvas = new Canvas(parent, SWT.NONE);
            GridData gridData = new GridData();
            gridData.heightHint = 18;
            gridData.widthHint = 18;
            canvas.setLayoutData(gridData);
            canvas.addPaintListener(new PaintListener() {

                @Override
                public void paintControl(PaintEvent e) {
                    e.gc.drawImage(ImageService.getImage(ViewsPlugin.PLUGIN_ID, "icons/clear.gif"), 1, 1);
                }
            });
            canvas.addMouseListener(new MouseAdapter() {

                @Override
                public void mouseUp(MouseEvent e) {
                    search.setText(Messages.AlgorithmView_search_message);
                    search.setForeground(COLOR_FILTER_INITIAL);
                    initialSearchState = true;
                    treeView.setFilter("");
                    paletteView.setFilter("");
                }
            });
        }
        search.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        search.setText(Messages.AlgorithmView_search_message);
        search.setForeground(COLOR_FILTER_INITIAL);
        search.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseDown(MouseEvent e) {
                if (initialSearchState) {
                    search.setText("");
                    search.setForeground(COLOR_FILTER_USER);
                    initialSearchState = false;
                }
            }
        });
        search.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                treeView.setFilter(search.getText());
                paletteView.setFilter(search.getText());
            }
        });
        search.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                if (e.detail == SWT.CANCEL) {
                    search.setText(Messages.AlgorithmView_search_message);
                    search.setForeground(COLOR_FILTER_INITIAL);
                    initialSearchState = true;
                    treeView.setFilter("");
                    paletteView.setFilter("");
                }
            }
        });
    }

    /**
     * used to trigger actions when an algorithm is drag&dropped to an editor
     *
     * @param algorithmName the name of the algorithm whose action is to be done
     */
    public static void doAction(String algorithmName) {
        Iterator<ShadowAlgorithmHandler> it9 = algorithmTypes.iterator();
        ShadowAlgorithmHandler handler = null;
        while (it9.hasNext()) {
            handler = it9.next();
            // TODO the text property doesn't belong in the Handler but in the CommandInfo
            if (algorithmName.equals(handler.getText())) {
                // TODO maybe Command.executeWithChecks() should be called here, which also requires an ExecutionEvent
                handler.execute(null);
            }
        }
    }

    /**
     * Passing the focus request to the org.jcryptool.core.views.content's control.
     */
    @Override
    public void setFocus() {
        switch(PlatformUI.getPreferenceStore().getInt("showView")) {
            case VIEW_PALETTE:
                paletteView.getControl().setFocus();
                break;
            default:
                treeView.getControl().setFocus();
        }
    }

    /**
     * Displays messages in a MessageDialog
     *
     * @param message the message text
     */
    public static void showMessage(String message) {
        MessageDialog.openInformation(null, Messages.AlgorithmView_0, message);
    }

    /**
     * sets the viewers to display the given tab
     *
     * @param name the name of the tab to display
     */
    public static void showTab(String name) {
        if (treeView != null)
            treeView.showTab(name);
        if (paletteView != null)
            paletteView.showTab(name);
    }

    public static void showContextHelp(final String extensionPointId, final String name) {
        IConfigurationElement[] elements = Platform.getExtensionRegistry().getExtensionPoint(extensionPointId).getConfigurationElements();
        for (IConfigurationElement element : elements) {
            if (element.getAttribute("name").equals(name)) {
                final String contextHelpId = element.getAttribute("contextHelpId");
                if (contextHelpId != null && !"".equals(contextHelpId)) {
                    PlatformUI.getWorkbench().getHelpSystem().displayHelp(contextHelpId);
                } else {
                    PlatformUI.getWorkbench().getHelpSystem().displayHelp(ViewsPlugin.PLUGIN_ID + ".algorithmsView");
                }
                return;
            }
        }
    }

    private void loadAlgorithms() {
        CommandInfo[] commands = OperationsPlugin.getDefault().getAlgorithmsManager().getShadowAlgorithmCommands();

        // This didn't quite support the case when we have a Handler rather than an Action in the CommandOrAction.
        // I think I now added Handler support.
        // TODO Is this loadAlgorithms() method used anywhere?
    }
}


while (it9.hasNext()) {
            handler = it9.next();
            // TODO the text property doesn't belong in the Handler but in the CommandInfo
            if (algorithmName.equals(handler.getText())) {
                // TODO maybe Command.executeWithChecks() should be called here, which also requires an ExecutionEvent
                handler.execute(null);
            }
        }

package org.jcryptool.core.views;

import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.Category;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.CommandManager;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.services.IServiceLocator;
import org.jcryptool.core.operations.CommandInfo;
import org.jcryptool.core.operations.IOperationsConstants;
import org.jcryptool.core.operations.OperationsPlugin;
import org.jcryptool.core.operations.algorithm.ShadowAlgorithmHandler;
import org.jcryptool.core.util.colors.ColorService;
import org.jcryptool.core.util.images.ImageService;
import org.jcryptool.core.views.content.PaletteView;
import org.jcryptool.core.views.content.TreeView;

/**
 * Displays all available algorithms in a tree or palette view.
 *
 * @author t-kern
 * @author Holger Friedrich (support for Commands)
 * @version 0.9.3
 */
public class AlgorithmView extends ViewPart implements IOperationsConstants {

    public static final String ID = "org.jcryptool.core.views.AlgorithmView";

    public static final String MENU_TEXT_ALGORITHM = Messages.AlgorithmView_menu_text_algorithms;

    public static final String MENU_TEXT_ANALYSIS = Messages.AlgorithmView_menu_text_analysis;

    public static final String MENU_TEXT_VISUALS = Messages.AlgorithmView_menu_text_visuals;

    public static final String MENU_TEXT_GAMES = Messages.AlgorithmView_menu_text_games;

    private static final int VIEW_TREE = 0x00;

    private static final int VIEW_PALETTE = 0x01;

    private static TreeView treeView;

    private static PaletteView paletteView;

    private static StackLayout layout;

    private Composite listing;

    private boolean initialSearchState = true;

    // black
    private static final Color COLOR_FILTER_USER = ColorService.BLACK;

    // gray
    private static final Color COLOR_FILTER_INITIAL = ColorService.getColor(SWT.COLOR_GRAY);

    private static ArrayList<ShadowAlgorithmHandler> algorithmTypes = new ArrayList<ShadowAlgorithmHandler>();

    public static AlgorithmView instance;

    final static String showPaletteCommandId = ViewsPlugin.PLUGIN_ID + ".commands.showPalette";

    final static String showTreeCommandId = ViewsPlugin.PLUGIN_ID + ".commands.showTree";

    private ICommandService commandService;

    private Category autogeneratedCategory;

    private IServiceLocator serviceLocator;

    AbstractHandler showPaletteHandler;

    AbstractHandler showTreeHandler;

    CommandContributionItem showPaletteContributionItem;

    CommandContributionItem showTreeContributionItem;

    public AlgorithmView() {
        PlatformUI.getPreferenceStore().setDefault("showView", VIEW_PALETTE);
        loadAlgorithms();
        AlgorithmView.instance = this;
    }

    /**
     * This is a callback that will allow us to create the org.jcryptool.core.views content and
     * initialize it.
     */
    @Override
    public void createPartControl(final Composite parent) {
        GridLayout outerLayout = new GridLayout(2, false);
        outerLayout.horizontalSpacing = 0;
        outerLayout.verticalSpacing = 0;
        outerLayout.marginHeight = 0;
        outerLayout.marginWidth = 0;
        parent.setLayout(outerLayout);
        parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        createSearchArea(parent);
        createViewArea(parent);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, ViewsPlugin.PLUGIN_ID + ".algorithmsView");
    }

    public static void showBubble(String string) {
        PaletteView viewer = paletteView;
        if (!viewer.getControl().isVisible()) {
            Control control = viewer.getControl();
            Shell shell = viewer.getControl().getShell();
            final ToolTip tip = new ToolTip(shell, SWT.BALLOON);
            tip.setMessage(string);
            tip.setVisible(true);
            tip.setLocation(control.toDisplay(control.getSize().x, 0));
            tip.setAutoHide(true);
        } else {
            viewer.getControl().addPaintListener(new PaintListener() {

                private boolean doneThis = false;

                @Override
                public void paintControl(PaintEvent e) {
                    if (doneThis) {
                        return;
                    } else {
                        doneThis = true;
                    }
                    Control control = viewer.getControl();
                    Shell shell = viewer.getControl().getShell();
                    final ToolTip tip = new ToolTip(shell, SWT.BALLOON);
                    tip.setMessage(string);
                    tip.setVisible(true);
                    tip.setLocation(control.toDisplay(control.getSize().x, 0));
                    tip.setAutoHide(true);
                }
            });
        }
    }

    private void defineCommand(final String commandId, final String name, AbstractHandler handler) {
        Command command = commandService.getCommand(commandId);
        command.define(name, null, autogeneratedCategory);
        command.setHandler(handler);
    }

    private CommandContributionItem createContributionItem(final String commandId, final ImageDescriptor icon, final String tooltip) {
        CommandContributionItemParameter param = new CommandContributionItemParameter(serviceLocator, null, commandId, SWT.PUSH);
        if (icon != null)
            param.icon = icon;
        if (tooltip != null && !tooltip.equals(""))
            param.tooltip = tooltip;
        CommandContributionItem item = new CommandContributionItem(param);
        return (item);
    }

    /**
     * creates the area containing the views
     *
     * @param parent the parent composite
     */
    private void createViewArea(Composite parent) {
        layout = new StackLayout();
        listing = new Composite(parent, SWT.NONE);
        listing.setLayout(layout);
        listing.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
        // create both views
        paletteView = new PaletteView(listing);
        treeView = new TreeView(listing);
        showTab(MENU_TEXT_ALGORITHM);
        // create the command to switch the views
        // This may be a little tricky to translate to Commands.
        // The Action seems to change its own text, tool tip and icon when it is invoked...
        // Perhaps we should create two CommandContributionItems and switch between them
        // as the view style is switched from palette to tree and vice versa.
        showPaletteHandler = new AbstractHandler() {

            @Override
            public Object execute(ExecutionEvent event) {
                layout.topControl = paletteView.getControl();
                PlatformUI.getPreferenceStore().setValue("showView", VIEW_PALETTE);
                listing.layout();
                IMenuManager manager = getViewSite().getActionBars().getMenuManager();
                manager.removeAll();
                manager.add(showTreeContributionItem);
                return (null);
            }
        };
        showTreeHandler = new AbstractHandler() {

            @Override
            public Object execute(ExecutionEvent event) {
                layout.topControl = treeView.getControl();
                PlatformUI.getPreferenceStore().setValue("showView", VIEW_TREE);
                listing.layout();
                IMenuManager manager = getViewSite().getActionBars().getMenuManager();
                manager.removeAll();
                manager.add(showPaletteContributionItem);
                return (null);
            }
        };
        serviceLocator = PlatformUI.getWorkbench();
        commandService = serviceLocator.getService(ICommandService.class);
        autogeneratedCategory = commandService.getCategory(CommandManager.AUTOGENERATED_CATEGORY_ID);
        defineCommand(showPaletteCommandId, Messages.AlgorithmView_showPalette, showPaletteHandler);
        defineCommand(showTreeCommandId, Messages.AlgorithmView_showTree, showTreeHandler);
        showPaletteContributionItem = createContributionItem(showPaletteCommandId, ImageService.getImageDescriptor(ViewsPlugin.PLUGIN_ID, "icons/switch.gif"), Messages.AlgorithmView_showPalette);
        showTreeContributionItem = createContributionItem(showTreeCommandId, ImageService.getImageDescriptor(ViewsPlugin.PLUGIN_ID, "icons/switch.gif"), Messages.AlgorithmView_showTree);
        // set the correct view to be shown and assign the corresponding action
        IMenuManager manager = getViewSite().getActionBars().getMenuManager();
        switch(PlatformUI.getPreferenceStore().getInt("showView")) {
            case VIEW_PALETTE:
                layout.topControl = paletteView.getControl();
                manager.add(showTreeContributionItem);
                break;
            default:
                layout.topControl = treeView.getControl();
                manager.add(showPaletteContributionItem);
        }
    }

    /**
     * Creates the search field. On Mac the text does contain a clear (reset) icon which resets
     * the view filter. Since Windows does not support this an additional clear (reset) icon
     * is shown next to the text.
     *
     * @param parent The parent composite
     */
    private void createSearchArea(Composite parent) {
        // search field
        final Text search = new Text(parent, SWT.SEARCH | SWT.ICON_CANCEL | SWT.ICON_SEARCH);
        if ((search.getStyle() & SWT.CANCEL) == 0) {
            // reset search button for systems that do not support the cancel icon
            Canvas canvas = new Canvas(parent, SWT.NONE);
            GridData gridData = new GridData();
            gridData.heightHint = 18;
            gridData.widthHint = 18;
            canvas.setLayoutData(gridData);
            canvas.addPaintListener(new PaintListener() {

                @Override
                public void paintControl(PaintEvent e) {
                    e.gc.drawImage(ImageService.getImage(ViewsPlugin.PLUGIN_ID, "icons/clear.gif"), 1, 1);
                }
            });
            canvas.addMouseListener(new MouseAdapter() {

                @Override
                public void mouseUp(MouseEvent e) {
                    search.setText(Messages.AlgorithmView_search_message);
                    search.setForeground(COLOR_FILTER_INITIAL);
                    initialSearchState = true;
                    treeView.setFilter("");
                    paletteView.setFilter("");
                }
            });
        }
        search.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        search.setText(Messages.AlgorithmView_search_message);
        search.setForeground(COLOR_FILTER_INITIAL);
        search.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseDown(MouseEvent e) {
                if (initialSearchState) {
                    search.setText("");
                    search.setForeground(COLOR_FILTER_USER);
                    initialSearchState = false;
                }
            }
        });
        search.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                treeView.setFilter(search.getText());
                paletteView.setFilter(search.getText());
            }
        });
        search.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                if (e.detail == SWT.CANCEL) {
                    search.setText(Messages.AlgorithmView_search_message);
                    search.setForeground(COLOR_FILTER_INITIAL);
                    initialSearchState = true;
                    treeView.setFilter("");
                    paletteView.setFilter("");
                }
            }
        });
    }

    /**
     * used to trigger actions when an algorithm is drag&dropped to an editor
     *
     * @param algorithmName the name of the algorithm whose action is to be done
     */
    public static void doAction(String algorithmName) {
        Iterator<ShadowAlgorithmHandler> it9 = algorithmTypes.iterator();
        ShadowAlgorithmHandler handler = null;

    }

    /**
     * Passing the focus request to the org.jcryptool.core.views.content's control.
     */
    @Override
    public void setFocus() {
        switch(PlatformUI.getPreferenceStore().getInt("showView")) {
            case VIEW_PALETTE:
                paletteView.getControl().setFocus();
                break;
            default:
                treeView.getControl().setFocus();
        }
    }

    /**
     * Displays messages in a MessageDialog
     *
     * @param message the message text
     */
    public static void showMessage(String message) {
        MessageDialog.openInformation(null, Messages.AlgorithmView_0, message);
    }

    /**
     * sets the viewers to display the given tab
     *
     * @param name the name of the tab to display
     */
    public static void showTab(String name) {
        if (treeView != null)
            treeView.showTab(name);
        if (paletteView != null)
            paletteView.showTab(name);
    }

    public static void showContextHelp(final String extensionPointId, final String name) {
        IConfigurationElement[] elements = Platform.getExtensionRegistry().getExtensionPoint(extensionPointId).getConfigurationElements();
        for (IConfigurationElement element : elements) {
            if (element.getAttribute("name").equals(name)) {
                final String contextHelpId = element.getAttribute("contextHelpId");
                if (contextHelpId != null && !"".equals(contextHelpId)) {
                    PlatformUI.getWorkbench().getHelpSystem().displayHelp(contextHelpId);
                } else {
                    PlatformUI.getWorkbench().getHelpSystem().displayHelp(ViewsPlugin.PLUGIN_ID + ".algorithmsView");
                }
                return;
            }
        }
    }

    private void loadAlgorithms() {
        CommandInfo[] commands = OperationsPlugin.getDefault().getAlgorithmsManager().getShadowAlgorithmCommands();
        for (int i = 0, length = commands.length; i < length; i++) {
            AbstractHandler handler = commands[i].getHandler();
            if (!algorithmTypes.contains((handler))) {
                algorithmTypes.add(((ShadowAlgorithmHandler) handler));
            }
        }
        // This didn't quite support the case when we have a Handler rather than an Action in the CommandOrAction.
        // I think I now added Handler support.
        // TODO Is this loadAlgorithms() method used anywhere?
    }
}


for (int i = 0; i < columns.length; i++) {
                if (columns[i] == -1) {
                    columns[i] = per;
                    index = i;
                }
            }

package org.eclipse.birt.report.engine.emitter.excel.layout;

import java.util.logging.Logger;
import org.eclipse.birt.report.engine.content.IContent;
import org.eclipse.birt.report.engine.content.IForeignContent;
import org.eclipse.birt.report.engine.content.IListContent;
import org.eclipse.birt.report.engine.content.ITableContent;
import org.eclipse.birt.report.engine.emitter.EmitterUtil;
import org.eclipse.birt.report.engine.emitter.excel.ExcelUtil;
import org.eclipse.birt.report.engine.ir.DimensionType;
import org.eclipse.birt.report.engine.ir.ExtendedItemDesign;

public class LayoutUtil {

    private static final int DEFAULT_WIDTH = 40000;

    private static final int MIN_WIDTH = 128;

    private static final Logger log = Logger.getLogger(LayoutUtil.class.getName());

    public static ColumnsInfo createTable(int col, int width) {
        return new ColumnsInfo(col, width);
    }

    public static ColumnsInfo createTable(IListContent list, int width, int dpi) {
        width = getElementWidth(list, width, dpi);
        int[] column = new int[] { width };
        return new ColumnsInfo(column);
    }

    public static ColumnsInfo createChart(IForeignContent content, int width, int dpi) {
        ExtendedItemDesign design = (ExtendedItemDesign) content.getGenerateBy();
        DimensionType value = design.getWidth();
        if (value != null) {
            width = getElementWidth(value, width, dpi);
        }
        int[] column = new int[] { width };
        return new ColumnsInfo(column);
    }

    public static ColumnsInfo createImage(int width) {
        int[] column = new int[] { width };
        return new ColumnsInfo(column);
    }

    public static ColumnsInfo createImage(int width, int parentWidth, boolean isCenterAligned) {
        if (!isCenterAligned || parentWidth < width) {
            return createImage(width);
        }
        int[] column = new int[] { (parentWidth - width) / 2, width, (parentWidth - width) / 2 };
        return new ColumnsInfo(column);
    }

    public static int getImageWidth(DimensionType value, int parentWidth, int imageInfoWidth, int dpi) {
        if (value == null) {
            return imageInfoWidth;
        } else {
            return getElementWidth(value, parentWidth, dpi);
        }
    }

    public static int getImageHeight(DimensionType value, int imageInfoHeight, int dpi) {
        return ExcelUtil.convertDimensionType(value, imageInfoHeight, dpi);
    }

    public static int getElementWidth(IContent content, int width, int dpi) {
        DimensionType value = content.getWidth();
        if (value != null) {
            return getElementWidth(value, width, dpi);
        }
        return width;
    }

    private static int getElementWidth(DimensionType contentWidth, int width, int dpi) {
        try {
            width = Math.min(ExcelUtil.convertDimensionType(contentWidth, width, dpi), width);
        } catch (Exception e) {
        }
        return width;
    }

    public static int[] createFixedTable(ITableContent table, int tableWidth, int dpi) {
        int columnCount = table.getColumnCount();
        int[] columns = new int[columnCount];
        int unassignedCount = 0;
        int totalAssigned = 0;
        for (int i = 0; i < columnCount; i++) {
            DimensionType value = table.getColumn(i).getWidth();
            if (value == null) {
                columns[i] = -1;
                unassignedCount++;
            } else {
                columns[i] = ExcelUtil.convertDimensionType(value, tableWidth, dpi);
                totalAssigned += columns[i];
            }
        }
        if (table.getWidth() == null && unassignedCount == 0) {
            return columns;
        }
        columns = EmitterUtil.resizeTableColumn(tableWidth, columns, unassignedCount, totalAssigned);
        for (int i = 0; i < columns.length; i++) {
            if (columns[i] == 0) {
                columns[i] = MIN_WIDTH;
            }
        }
        return columns;
    }

    public static ColumnsInfo createTable(ITableContent table, int width, int dpi, boolean autoExtend) {
        int tableWidth = getElementWidth(table, width, dpi);
        int columnCount = table.getColumnCount();
        if (columnCount == 0) {
            return null;
        }
        int[] columns = new int[columnCount];
        int unassignedCount = 0;
        int totalAssigned = 0;
        for (int i = 0; i < columnCount; i++) {
            DimensionType value = table.getColumn(i).getWidth();
            if (value == null) {
                columns[i] = -1;
                unassignedCount++;
            } else {
                columns[i] = ExcelUtil.convertDimensionType(value, tableWidth, dpi);
                totalAssigned += columns[i];
            }
        }
        int leftWidth = tableWidth - totalAssigned;
        // If autoExtend, don't adjust column width when the total column width
        // exceed the width of parent table.
        if ((leftWidth > 0 || !autoExtend && leftWidth < 0) && unassignedCount == 0 && table.getWidth() != null) {
            int totalResized = 0;
            for (int i = 0; i < columnCount - 1; i++) {
                columns[i] = resize(columns[i], totalAssigned, leftWidth);
                totalResized += columns[i];
            }
            columns[columnCount - 1] = tableWidth - totalResized;
        } else if (leftWidth < 0 && unassignedCount > 0) {
            int totalResized = 0;
            int lastAssignedIndex = 0;
            for (int i = 0; i < columnCount; i++) {
                if (columns[i] == -1) {
                    columns[i] = 0;
                } else if (!autoExtend) {
                    columns[i] = resize(columns[i], totalAssigned, leftWidth);
                    lastAssignedIndex = i;
                    totalResized += columns[i];
                }
            }
            if (!autoExtend) {
                columns[lastAssignedIndex] += tableWidth - totalResized;
            }
        } else if (leftWidth >= 0 && unassignedCount > 0) {
            int per = (int) leftWidth / unassignedCount;
            int index = 0;

            columns[index] = leftWidth - per * (unassignedCount - 1);
        }
        for (int i = 0; i < columns.length; i++) {
            if (columns[i] == 0) {
                if (autoExtend) {
                    columns[i] = DEFAULT_WIDTH;
                } else {
                    columns[i] = MIN_WIDTH;
                }
            }
        }
        return new ColumnsInfo(columns);
    }

    private static int resize(int width, int total, int left) {
        return Math.round(width + (float) width / (float) total * left);
    }
}


try {
            width = Math.min(ExcelUtil.convertDimensionType(contentWidth, width, dpi), width);
        } catch (Exception e) {
        }

package org.eclipse.birt.report.engine.emitter.excel.layout;

import java.util.logging.Logger;
import org.eclipse.birt.report.engine.content.IContent;
import org.eclipse.birt.report.engine.content.IForeignContent;
import org.eclipse.birt.report.engine.content.IListContent;
import org.eclipse.birt.report.engine.content.ITableContent;
import org.eclipse.birt.report.engine.emitter.EmitterUtil;
import org.eclipse.birt.report.engine.emitter.excel.ExcelUtil;
import org.eclipse.birt.report.engine.ir.DimensionType;
import org.eclipse.birt.report.engine.ir.ExtendedItemDesign;

public class LayoutUtil {

    private static final int DEFAULT_WIDTH = 40000;

    private static final int MIN_WIDTH = 128;

    private static final Logger log = Logger.getLogger(LayoutUtil.class.getName());

    public static ColumnsInfo createTable(int col, int width) {
        return new ColumnsInfo(col, width);
    }

    public static ColumnsInfo createTable(IListContent list, int width, int dpi) {
        width = getElementWidth(list, width, dpi);
        int[] column = new int[] { width };
        return new ColumnsInfo(column);
    }

    public static ColumnsInfo createChart(IForeignContent content, int width, int dpi) {
        ExtendedItemDesign design = (ExtendedItemDesign) content.getGenerateBy();
        DimensionType value = design.getWidth();
        if (value != null) {
            width = getElementWidth(value, width, dpi);
        }
        int[] column = new int[] { width };
        return new ColumnsInfo(column);
    }

    public static ColumnsInfo createImage(int width) {
        int[] column = new int[] { width };
        return new ColumnsInfo(column);
    }

    public static ColumnsInfo createImage(int width, int parentWidth, boolean isCenterAligned) {
        if (!isCenterAligned || parentWidth < width) {
            return createImage(width);
        }
        int[] column = new int[] { (parentWidth - width) / 2, width, (parentWidth - width) / 2 };
        return new ColumnsInfo(column);
    }

    public static int getImageWidth(DimensionType value, int parentWidth, int imageInfoWidth, int dpi) {
        if (value == null) {
            return imageInfoWidth;
        } else {
            return getElementWidth(value, parentWidth, dpi);
        }
    }

    public static int getImageHeight(DimensionType value, int imageInfoHeight, int dpi) {
        return ExcelUtil.convertDimensionType(value, imageInfoHeight, dpi);
    }

    public static int getElementWidth(IContent content, int width, int dpi) {
        DimensionType value = content.getWidth();
        if (value != null) {
            return getElementWidth(value, width, dpi);
        }
        return width;
    }

    private static int getElementWidth(DimensionType contentWidth, int width, int dpi) {

        return width;
    }

    public static int[] createFixedTable(ITableContent table, int tableWidth, int dpi) {
        int columnCount = table.getColumnCount();
        int[] columns = new int[columnCount];
        int unassignedCount = 0;
        int totalAssigned = 0;
        for (int i = 0; i < columnCount; i++) {
            DimensionType value = table.getColumn(i).getWidth();
            if (value == null) {
                columns[i] = -1;
                unassignedCount++;
            } else {
                columns[i] = ExcelUtil.convertDimensionType(value, tableWidth, dpi);
                totalAssigned += columns[i];
            }
        }
        if (table.getWidth() == null && unassignedCount == 0) {
            return columns;
        }
        columns = EmitterUtil.resizeTableColumn(tableWidth, columns, unassignedCount, totalAssigned);
        for (int i = 0; i < columns.length; i++) {
            if (columns[i] == 0) {
                columns[i] = MIN_WIDTH;
            }
        }
        return columns;
    }

    public static ColumnsInfo createTable(ITableContent table, int width, int dpi, boolean autoExtend) {
        int tableWidth = getElementWidth(table, width, dpi);
        int columnCount = table.getColumnCount();
        if (columnCount == 0) {
            return null;
        }
        int[] columns = new int[columnCount];
        int unassignedCount = 0;
        int totalAssigned = 0;
        for (int i = 0; i < columnCount; i++) {
            DimensionType value = table.getColumn(i).getWidth();
            if (value == null) {
                columns[i] = -1;
                unassignedCount++;
            } else {
                columns[i] = ExcelUtil.convertDimensionType(value, tableWidth, dpi);
                totalAssigned += columns[i];
            }
        }
        int leftWidth = tableWidth - totalAssigned;
        // If autoExtend, don't adjust column width when the total column width
        // exceed the width of parent table.
        if ((leftWidth > 0 || !autoExtend && leftWidth < 0) && unassignedCount == 0 && table.getWidth() != null) {
            int totalResized = 0;
            for (int i = 0; i < columnCount - 1; i++) {
                columns[i] = resize(columns[i], totalAssigned, leftWidth);
                totalResized += columns[i];
            }
            columns[columnCount - 1] = tableWidth - totalResized;
        } else if (leftWidth < 0 && unassignedCount > 0) {
            int totalResized = 0;
            int lastAssignedIndex = 0;
            for (int i = 0; i < columnCount; i++) {
                if (columns[i] == -1) {
                    columns[i] = 0;
                } else if (!autoExtend) {
                    columns[i] = resize(columns[i], totalAssigned, leftWidth);
                    lastAssignedIndex = i;
                    totalResized += columns[i];
                }
            }
            if (!autoExtend) {
                columns[lastAssignedIndex] += tableWidth - totalResized;
            }
        } else if (leftWidth >= 0 && unassignedCount > 0) {
            int per = (int) leftWidth / unassignedCount;
            int index = 0;
            for (int i = 0; i < columns.length; i++) {
                if (columns[i] == -1) {
                    columns[i] = per;
                    index = i;
                }
            }
            columns[index] = leftWidth - per * (unassignedCount - 1);
        }
        for (int i = 0; i < columns.length; i++) {
            if (columns[i] == 0) {
                if (autoExtend) {
                    columns[i] = DEFAULT_WIDTH;
                } else {
                    columns[i] = MIN_WIDTH;
                }
            }
        }
        return new ColumnsInfo(columns);
    }

    private static int resize(int width, int total, int left) {
        return Math.round(width + (float) width / (float) total * left);
    }
}


public static void inlineSites(List<List<Host>> sites) {
        inlineSites(sites, Collections.emptyMap());
    }

package soot.jimple.toolkits.invoke;

/*-
 * #%L
 * Soot - a J*va Optimization Framework
 * %%
 * %%
 * #L%
 */
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import soot.Body;
import soot.Local;
import soot.PhaseOptions;
import soot.RefType;
import soot.Scene;
import soot.SootClass;
import soot.SootMethod;
import soot.Trap;
import soot.TrapManager;
import soot.Unit;
import soot.UnitBox;
import soot.Value;
import soot.ValueBox;
import soot.jimple.AssignStmt;
import soot.jimple.CaughtExceptionRef;
import soot.jimple.IdentityRef;
import soot.jimple.IdentityStmt;
import soot.jimple.IfStmt;
import soot.jimple.InstanceInvokeExpr;
import soot.jimple.InvokeExpr;
import soot.jimple.InvokeStmt;
import soot.jimple.Jimple;
import soot.jimple.NullConstant;
import soot.jimple.ParameterRef;
import soot.jimple.ReturnStmt;
import soot.jimple.ReturnVoidStmt;
import soot.jimple.Stmt;
import soot.jimple.ThisRef;
import soot.jimple.toolkits.scalar.LocalNameStandardizer;
import soot.tagkit.Host;
import soot.util.Chain;

/**
 * Provides methods to inline a given invoke site.
 */
public class SiteInliner {

    public String getDefaultOptions() {
        return "insert-null-checks insert-redundant-casts";
    }

    /**
     * Iterates over a list of sites, inlining them in order. Each site is given as a 3-element list (inlinee, toInline,
     * container).
     */

/**
     * Iterates over a list of sites, inlining them in order. Each site is given as a 3-element list (inlinee, toInline,
     * container).
     */
    public static void inlineSites(List<List<Host>> sites, Map<String, String> options) {
        for (List<Host> l : sites) {
            assert (l.size() == 3);
            SootMethod inlinee = (SootMethod) l.get(0);
            Stmt toInline = (Stmt) l.get(1);
            SootMethod container = (SootMethod) l.get(2);
            inlineSite(inlinee, toInline, container, options);
        }
    }

    /**
     * Inlines the method inlinee into the container at the point toInline.
     */
    public static List<Unit> inlineSite(SootMethod inlinee, Stmt toInline, SootMethod container) {
        return inlineSite(inlinee, toInline, container, Collections.emptyMap());
    }

    /**
     * Inlines the given site. Note that this method does not actually check if it's safe (with respect to access modifiers and
     * special invokes) for it to be inlined. That functionality is handled by the InlinerSafetyManager.
     */
    public static List<Unit> inlineSite(SootMethod inlinee, Stmt toInline, SootMethod container, Map<String, String> options) {
        final SootClass declaringClass = inlinee.getDeclaringClass();
        if (!declaringClass.isApplicationClass() && !declaringClass.isLibraryClass()) {
            return null;
        }
        final Body containerB = container.getActiveBody();
        final Chain<Unit> containerUnits = containerB.getUnits();
        assert (containerUnits.contains(toInline)) : toInline + " is not in body " + containerB;
        final InvokeExpr ie = toInline.getInvokeExpr();
        Value thisToAdd = (ie instanceof InstanceInvokeExpr) ? ((InstanceInvokeExpr) ie).getBase() : null;
        if (ie instanceof InstanceInvokeExpr) {
            // Insert casts to please the verifier.
            if (PhaseOptions.getBoolean(options, "insert-redundant-casts")) {
                // The verifier will complain if the argument passed to the method is not the correct type.
                // For instance, Bottle.price_static takes a cost.
                // Cost is an interface implemented by Bottle.
                Value base = ((InstanceInvokeExpr) ie).getBase();
                SootClass localType = ((RefType) base.getType()).getSootClass();
                if (localType.isInterface() || Scene.v().getActiveHierarchy().isClassSuperclassOf(localType, declaringClass)) {
                    final Jimple jimp = Jimple.v();
                    RefType type = declaringClass.getType();
                    Local castee = jimp.newLocal("__castee", type);
                    containerB.getLocals().add(castee);
                    containerUnits.insertBefore(jimp.newAssignStmt(castee, jimp.newCastExpr(base, type)), toInline);
                    thisToAdd = castee;
                }
            }
            // (If enabled), add a null pointer check.
            if (PhaseOptions.getBoolean(options, "insert-null-checks")) {
                final Jimple jimp = Jimple.v();
                /* Ah ha. Caught again! */
                if (TrapManager.isExceptionCaughtAt(Scene.v().getSootClass("java.lang.NullPointerException"), toInline, containerB)) {
                    // In this case, we don't use throwPoint. Instead, put the code right there.
                    IfStmt insertee = jimp.newIfStmt(jimp.newNeExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), toInline);
                    containerUnits.insertBefore(insertee, toInline);
                    // This sucks (but less than before).
                    insertee.setTarget(toInline);
                    ThrowManager.addThrowAfter(containerB.getLocals(), containerUnits, insertee);
                } else {
                    containerUnits.insertBefore(jimp.newIfStmt(jimp.newEqExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), ThrowManager.getNullPointerExceptionThrower(containerB)), toInline);
                }
            }
        }
        // Add synchronizing stuff.
        if (inlinee.isSynchronized()) {
            // Need to get the class object if ie is a static invoke.
            if (ie instanceof InstanceInvokeExpr) {
                Local base = (Local) ((InstanceInvokeExpr) ie).getBase();
                SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, base);
            } else if (!container.getDeclaringClass().isInterface()) {
                // If we're in an interface, we must be in a <clinit> method,
                // which surely needs no synchronization.
                final SynchronizerManager mgr = SynchronizerManager.v();
                mgr.synchronizeStmtOn(toInline, containerB, mgr.addStmtsToFetchClassBefore(containerB, toInline));
            }
        }
        final Body inlineeB = inlinee.getActiveBody();
        final Chain<Unit> inlineeUnits = inlineeB.getUnits();
        final Unit exitPoint = containerUnits.getSuccOf(toInline);
        // First, clone all of the inlinee's units & locals.
        HashMap<Local, Local> oldLocalsToNew = new HashMap<Local, Local>();
        HashMap<Unit, Unit> oldUnitsToNew = new HashMap<Unit, Unit>();
        {
            Unit cursor = toInline;
            for (Unit u : inlineeUnits) {
                Unit currPrime = (Unit) u.clone();
                if (currPrime == null) {
                    throw new RuntimeException("getting null from clone!");
                }
                currPrime.addAllTagsOf(u);
                containerUnits.insertAfter(currPrime, cursor);
                oldUnitsToNew.put(u, currPrime);
                cursor = currPrime;
            }
            for (Local l : inlineeB.getLocals()) {
                Local lPrime = (Local) l.clone();
                if (lPrime == null) {
                    throw new RuntimeException("getting null from local clone!");
                }
                containerB.getLocals().add(lPrime);
                oldLocalsToNew.put(l, lPrime);
            }
        }
        // Backpatch the newly-inserted units using newly-constructed maps.
        for (Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint)); it.hasNext(); ) {
            Unit patchee = it.next();
            for (ValueBox box : patchee.getUseAndDefBoxes()) {
                Value value = box.getValue();
                if (value instanceof Local) {
                    Local lPrime = oldLocalsToNew.get((Local) value);
                    if (lPrime == null) {
                        throw new RuntimeException("local has no clone!");
                    }
                    box.setValue(lPrime);
                }
            }
            for (UnitBox box : patchee.getUnitBoxes()) {
                Unit uPrime = oldUnitsToNew.get(box.getUnit());
                if (uPrime == null) {
                    throw new RuntimeException("inlined stmt has no clone!");
                }
                box.setUnit(uPrime);
            }
        }
        // Copy & backpatch the traps; preserve their same order.
        {
            final Chain<Trap> traps = containerB.getTraps();
            Trap prevTrap = null;
            for (Trap t : inlineeB.getTraps()) {
                Unit newBegin = oldUnitsToNew.get(t.getBeginUnit());
                Unit newEnd = oldUnitsToNew.get(t.getEndUnit());
                Unit newHandler = oldUnitsToNew.get(t.getHandlerUnit());
                if (newBegin == null || newEnd == null || newHandler == null) {
                    throw new RuntimeException("couldn't map trap!");
                }
                Trap trap = Jimple.v().newTrap(t.getException(), newBegin, newEnd, newHandler);
                if (prevTrap == null) {
                    traps.addFirst(trap);
                } else {
                    traps.insertAfter(trap, prevTrap);
                }
                prevTrap = trap;
            }
        }
        // Handle identity stmt's and returns.
        {
            ArrayList<Unit> cuCopy = new ArrayList<Unit>();
            for (Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint)); it.hasNext(); ) {
                cuCopy.add(it.next());
            }
            for (Unit u : cuCopy) {
                if (u instanceof IdentityStmt) {
                    IdentityStmt idStmt = (IdentityStmt) u;
                    IdentityRef rhs = (IdentityRef) idStmt.getRightOp();
                    if (rhs instanceof CaughtExceptionRef) {
                        continue;
                    } else if (rhs instanceof ThisRef) {
                        if (!(ie instanceof InstanceInvokeExpr)) {
                            throw new RuntimeException("thisref with no receiver!");
                        }
                        containerUnits.swapWith(u, Jimple.v().newAssignStmt(idStmt.getLeftOp(), thisToAdd));
                    } else if (rhs instanceof ParameterRef) {
                        ParameterRef pref = (ParameterRef) rhs;
                        containerUnits.swapWith(u, Jimple.v().newAssignStmt(idStmt.getLeftOp(), ie.getArg(pref.getIndex())));
                    }
                } else if (u instanceof ReturnStmt) {
                    if (toInline instanceof InvokeStmt) {
                        containerUnits.swapWith(u, Jimple.v().newGotoStmt(exitPoint));
                    } else if (toInline instanceof AssignStmt) {
                        final Jimple jimp = Jimple.v();
                        AssignStmt as = jimp.newAssignStmt(((AssignStmt) toInline).getLeftOp(), ((ReturnStmt) u).getOp());
                        containerUnits.insertBefore(as, u);
                        containerUnits.swapWith(u, jimp.newGotoStmt(exitPoint));
                    } else {
                        throw new RuntimeException("invoking stmt neither InvokeStmt nor AssignStmt!??!?!");
                    }
                } else if (u instanceof ReturnVoidStmt) {
                    containerUnits.swapWith(u, Jimple.v().newGotoStmt(exitPoint));
                }
            }
        }
        List<Unit> newStmts = new ArrayList<Unit>();
        for (Iterator<Unit> i = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint)); i.hasNext(); ) {
            newStmts.add(i.next());
        }
        // Remove the original statement toInline.
        containerUnits.remove(toInline);
        // Resolve name collisions.
        LocalNameStandardizer.v().transform(containerB, "ji.lns");
        return newStmts;
    }
}