org.cs3.pdt.console.internal.views.PrologConsoleView.java Source code

Java tutorial

Introduction

Here is the source code for org.cs3.pdt.console.internal.views.PrologConsoleView.java

Source

/*****************************************************************************
 * This file is part of the Prolog Development Tool (PDT)
 * 
 * Author: Lukas Degener (among others)
 * WWW: http://sewiki.iai.uni-bonn.de/research/pdt/start
 * Mail: pdt@lists.iai.uni-bonn.de
 * Copyright (C): 2004-2012, CS Dept. III, University of Bonn
 * 
 * All rights reserved. This program is  made available under the terms
 * of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 * 
 ****************************************************************************/

package org.cs3.pdt.console.internal.views;

import static org.cs3.prolog.common.QueryUtils.bT;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.cs3.pdt.common.PDTCommonUtil;
import org.cs3.pdt.common.search.PrologSearchPage;
import org.cs3.pdt.console.ConsoleModel;
import org.cs3.pdt.console.PDTConsole;
import org.cs3.pdt.console.PDTConsolePredicates;
import org.cs3.pdt.console.PrologConsole;
import org.cs3.pdt.console.PrologConsolePlugin;
import org.cs3.pdt.console.internal.DefaultPrologConsoleService;
import org.cs3.pdt.console.internal.ImageRepository;
import org.cs3.pdt.console.internal.loadfile.GenerateLoadFileWizard;
import org.cs3.pdt.console.internal.preferences.PreferencePageMain;
import org.cs3.pdt.console.internal.views.ConsoleViewer.SavedState;
import org.cs3.pdt.console.internal.views.completion.PrologCompletionProvider;
import org.cs3.prolog.common.Util;
import org.cs3.prolog.common.logging.Debug;
import org.cs3.prolog.connector.DefaultSubscription;
import org.cs3.prolog.connector.PrologInterfaceRegistry;
import org.cs3.prolog.connector.PrologRuntimePlugin;
import org.cs3.prolog.connector.Subscription;
import org.cs3.prolog.connector.ui.PrologContextTracker;
import org.cs3.prolog.connector.ui.PrologContextTrackerEvent;
import org.cs3.prolog.connector.ui.PrologRuntimeUI;
import org.cs3.prolog.connector.ui.PrologRuntimeUIPlugin;
import org.cs3.prolog.lifecycle.LifeCycleHook;
import org.cs3.prolog.pif.PrologInterface;
import org.cs3.prolog.pif.PrologInterfaceException;
import org.cs3.prolog.pif.service.ActivePrologInterfaceListener;
import org.cs3.prolog.session.PrologSession;
import org.cs3.prolog.ui.util.UIUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceNode;
import org.eclipse.jface.preference.IPreferencePage;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.jface.preference.PreferenceNode;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.search.ui.NewSearchUI;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;

public class PrologConsoleView extends ViewPart
        implements LifeCycleHook, PrologConsole, ActivePrologInterfaceListener {

    private static final String KILLABLE = "killable";

    private final class ClearAction extends Action {
        private ClearAction(String text, String tooltip, ImageDescriptor image) {
            super(text, image);
            setToolTipText(tooltip);
        }

        @Override
        public void run() {
            getViewer().clearOutput();
        }
    }

    private abstract class PasteAction extends Action {
        public PasteAction(String text, String tooltip, ImageDescriptor icon) {
            super(text, icon);

            setToolTipText(tooltip);
        }

        protected abstract String getTextToInsert();

        @Override
        public void run() {
            try {

                UIJob j = new UIJob(getToolTipText()) {

                    @Override
                    public IStatus runInUIThread(IProgressMonitor monitor) {
                        try {
                            PrologConsole c = getConsole();
                            int caretOffset = c.getCaretOffset();
                            int offsetInLineBuffer = caretOffset - c.getStartOfInput();
                            ConsoleModel model = c.getModel();
                            String lineBuffer = model.getLineBuffer();
                            if (offsetInLineBuffer < 0) {
                                offsetInLineBuffer = lineBuffer.length();
                                caretOffset = c.getStartOfInput() + lineBuffer.length();
                            }

                            String textToInsert = getTextToInsert();
                            if (textToInsert == null) {
                                return Status.OK_STATUS;
                            }
                            lineBuffer = lineBuffer.substring(0, offsetInLineBuffer) + textToInsert
                                    + lineBuffer.substring(offsetInLineBuffer);

                            model.setLineBuffer(lineBuffer);
                            c.setCaretOffset(caretOffset + textToInsert.length());

                        } catch (Throwable e) {
                            Debug.report(e);
                            return Status.CANCEL_STATUS;
                        } finally {
                            monitor.done();
                        }
                        return Status.OK_STATUS;
                    }

                    private PrologConsole getConsole() {
                        return PrologConsoleView.this;
                    }

                };

                j.schedule();
            } catch (Throwable t) {
                Debug.report(t);
            }
        }

    }

    private final class RestartAction extends Action {
        @Override
        public void run() {
            try {

                Job j = new Job("Restarting the PrologInterface") {

                    @Override
                    public IStatus run(IProgressMonitor monitor) {
                        try {
                            monitor.beginTask("initializing...", 2);

                            PrologInterface pif = getPrologInterface();
                            try {
                                if (pif != null) {
                                    pif.stop();
                                    monitor.worked(1);
                                }
                                // setPrologInterface(getEditorPrologInterface());
                            } finally {
                                if (pif != null) {
                                    if (!pif.isDown()) {
                                        pif.reset();
                                        Thread.sleep(1000);
                                    }
                                    pif.start();
                                    Display.getDefault().asyncExec(new Runnable() {
                                        @Override
                                        public void run() {
                                            getDefaultPrologConsoleService()
                                                    .fireConsoleVisibilityChanged(PrologConsoleView.this);
                                        }
                                    });
                                    writeCurrentProcessPortToFile();
                                }
                            }
                        } catch (Throwable e) {
                            Debug.report(e);
                            return Status.CANCEL_STATUS;
                        } finally {
                            monitor.done();
                        }
                        return Status.OK_STATUS;
                    }

                };
                j.schedule();
            } catch (Throwable t) {
                Debug.report(t);
            }

        }

        @Override
        public ImageDescriptor getImageDescriptor() {
            return ImageRepository.getImageDescriptor(ImageRepository.RESTART);
        }

        @Override
        public String getToolTipText() {
            return "Restart process";
        }

        @Override
        public String getText() {
            return "restart";
        }
    }

    private final class KillAction extends Action {

        @Override
        public void run() {

            boolean answer = MessageDialog.openQuestion(PrologConsoleView.this.getViewSite().getShell(),
                    "Kill process",
                    "Are you sure you want to kill the process? This will remove all breakpoints and will delete the list of consulted files");

            if (answer) {
                try {

                    Job j = new UIJob("Stopping the PrologInterface") {

                        @Override
                        public IStatus runInUIThread(IProgressMonitor monitor) {
                            try {
                                monitor.beginTask("initializing...", IProgressMonitor.UNKNOWN);

                                PrologInterfaceRegistry registry = PrologRuntimePlugin.getDefault()
                                        .getPrologInterfaceRegistry();

                                PrologInterface oldPif = getPrologInterface();
                                if (oldPif != null) {
                                    String currentKey = registry.getKey(oldPif);

                                    oldPif.clearConsultedFiles();
                                    oldPif.stop();

                                    if ("true".equals(oldPif.getAttribute(KILLABLE))) {
                                        Set<Subscription> subscriptionsForPif = registry
                                                .getSubscriptionsForPif(currentKey);
                                        for (Subscription s : subscriptionsForPif) {
                                            registry.removeSubscription(s);
                                        }
                                        registry.removePrologInterface(currentKey);
                                        getDefaultPrologConsoleService()
                                                .fireConsoleVisibilityChanged(PrologConsoleView.this);
                                        PrologRuntimeUIPlugin.getDefault().getPrologInterfaceService()
                                                .setActivePrologInterface(null);
                                    }

                                }
                            } catch (Throwable e) {
                                Debug.report(e);
                                return Status.CANCEL_STATUS;
                            } finally {
                                monitor.done();
                            }
                            return Status.OK_STATUS;
                        }

                    };
                    j.schedule();
                } catch (Throwable t) {
                    Debug.report(t);
                }
            }
        }

        @Override
        public ImageDescriptor getImageDescriptor() {
            return ImageRepository.getImageDescriptor(ImageRepository.STOP);
        }

        @Override
        public String getToolTipText() {
            return "Kill process";
        }

        @Override
        public String getText() {
            return "kill";
        }
    }

    private final class GenLoadFileAction extends Action {
        @Override
        public void run() {
            try {

                Job j = new UIJob("Generating load file") {

                    @Override
                    public IStatus runInUIThread(IProgressMonitor monitor) {
                        try {
                            monitor.beginTask("initializing...", IProgressMonitor.UNKNOWN);

                            if (getPrologInterface() != null) {
                                List<String> consultedFiles = getPrologInterface().getConsultedFiles();

                                // only create load file if there are consulted files
                                if (consultedFiles != null && consultedFiles.size() > 0) {
                                    WizardDialog dialog = new WizardDialog(getViewSite().getShell(),
                                            new GenerateLoadFileWizard(consultedFiles));
                                    dialog.open();
                                } else {
                                    MessageDialog.openWarning(PrologConsoleView.this.getViewSite().getShell(),
                                            "Generate Load File",
                                            "No need for a load file, since no files are consulted.");
                                }

                            }

                        } catch (Throwable e) {
                            Debug.report(e);
                            return Status.CANCEL_STATUS;
                        } finally {
                            monitor.done();
                        }
                        return Status.OK_STATUS;
                    }

                };
                j.schedule();
            } catch (Throwable t) {
                Debug.report(t);
            }

        }

        @Override
        public ImageDescriptor getImageDescriptor() {
            return ImageRepository.getImageDescriptor(ImageRepository.GEN_LOAD_FILE);
        }

        @Override
        public String getToolTipText() {
            return "Generate load file from consulted files";
        }

        @Override
        public String getText() {
            return "generateLoadFile";
        }
    }

    private final class CreateNamedProcessAction extends Action implements IMenuCreator {

        private Menu menu;

        private CreateNamedProcessAction() {
            setMenuCreator(this);
        }

        @Override
        public void run() {
            askForNameAndCreateProcess(PrologRuntimeUIPlugin.getDefault().getPreferenceStore()
                    .getString(PrologRuntimeUI.PREF_CONFIGURATION));
        }

        private void askForNameAndCreateProcess(final String configuration) {
            Job j = new UIJob("Creating new Prolog Process") {
                @Override
                public IStatus runInUIThread(IProgressMonitor arg0) {
                    PrologInterfaceRegistry registry = PrologRuntimePlugin.getDefault()
                            .getPrologInterfaceRegistry();

                    InputDialog dialog = createNewProcessNameDialog(registry);
                    int result = dialog.open();
                    if (result == InputDialog.CANCEL)
                        return Status.CANCEL_STATUS;
                    String pifKey = dialog.getValue();

                    PrologInterface pif = activateNewPrologProcess(registry, pifKey, configuration);
                    pif.setAttribute(KILLABLE, "true");
                    return Status.OK_STATUS;
                }

                public InputDialog createNewProcessNameDialog(PrologInterfaceRegistry registry) {
                    final Set<String> pifKeys = registry.getRegisteredKeys();
                    String defaultPifKey = getNameOfProjectOfActiveEditorInput();
                    if (pifKeys.contains(defaultPifKey))
                        defaultPifKey = null;

                    IInputValidator validator = new IInputValidator() {
                        @Override
                        public String isValid(String arg0) {
                            if ("".equals(arg0))
                                return "Process name must not be empty";
                            else if (pifKeys.contains(arg0))
                                return "Process name already used";
                            else
                                return null;
                        }
                    };
                    InputDialog dialog = new InputDialog(PrologConsoleView.this.getViewSite().getShell(),
                            "Create Prolog Process (" + configuration + ")",
                            "Enter a new name for your new Prolog process:", defaultPifKey, validator);
                    return dialog;
                }

            };
            j.schedule();
        }

        private String getNameOfProjectOfActiveEditorInput() {
            IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
            if (window != null) {
                IWorkbenchPage page = window.getActivePage();
                if (page != null) {
                    IEditorPart editor = page.getActiveEditor();
                    if (editor == null)
                        return null;

                    IEditorInput editorInput = editor.getEditorInput();
                    if (editorInput == null)
                        return null;

                    IFile file = (IFile) editorInput.getAdapter(IFile.class);
                    if (file != null) {
                        return file.getProject().getName();
                    }
                }
            }
            return null;
        }

        @Override
        public ImageDescriptor getImageDescriptor() {
            return ImageRepository.getImageDescriptor(ImageRepository.NEW_PROCESS);
        }

        @Override
        public String getToolTipText() {
            return "create process";
        }

        @Override
        public String getText() {
            return "create process";
        }

        @Override
        public void dispose() {
            if (menu != null) {
                menu.dispose();
            }
        }

        @Override
        public Menu getMenu(Control parent) {
            if (menu != null) {
                menu.dispose();
            }
            Menu newMenu = new Menu(parent);
            List<String> preferenceConfigurations = PrologRuntimeUIPlugin.getDefault()
                    .getPreferenceConfigurations();
            String defaultConfiguration = PrologRuntimeUIPlugin.getDefault().getPreferenceStore()
                    .getString(PrologRuntimeUI.PREF_CONFIGURATION);
            for (String preferenceConfiguration : preferenceConfigurations) {
                MenuItem item = new MenuItem(newMenu, SWT.NONE);
                item.setText(preferenceConfiguration.replaceAll("&", "&&"));
                if (preferenceConfiguration.equals(defaultConfiguration)) {
                    item.setImage(ImageRepository.getImage(ImageRepository.NEW_PROCESS));
                }
                final String configuration = preferenceConfiguration;
                item.addSelectionListener(new SelectionAdapter() {
                    @Override
                    public void widgetSelected(SelectionEvent e) {
                        askForNameAndCreateProcess(configuration);
                    }
                });
            }
            menu = newMenu;
            return menu;
        }

        @Override
        public Menu getMenu(Menu parent) {
            return null;
        }
    }

    private class ConsoleQueryAction extends Action {

        private String query;

        public ConsoleQueryAction(String text, ImageDescriptor icon, String query) {
            super(text, icon);
            this.query = query.endsWith(".") ? query : query + ".";
            setToolTipText(text);
        }

        protected String getQuery() {
            return query;
        }

        @Override
        public void run() {
            Job j = new Job(getToolTipText()) {
                @Override
                protected IStatus run(IProgressMonitor monitor) {
                    try {
                        PrologConsole c = getConsole();
                        ConsoleModel model = c.getModel();
                        model.setLineBuffer(" ");
                        model.commitLineBuffer();
                        model.setLineBuffer(getQuery());
                        model.commitLineBuffer();
                    } catch (Throwable e) {
                        Debug.report(e);
                        return Status.CANCEL_STATUS;
                    } finally {
                        monitor.done();
                    }
                    return Status.OK_STATUS;
                }

                private PrologConsole getConsole() {
                    return PrologConsoleView.this;
                }

            };
            j.schedule();
        }
    }

    private class PifQueryAction extends Action {

        private String query;

        public PifQueryAction(String text, ImageDescriptor icon, String query) {
            super(text, icon);
            this.query = query.endsWith(".") ? query : query + ".";
            setToolTipText(text);
        }

        protected String getQuery() {
            return query;
        }

        @Override
        public void run() {
            try {
                getPrologInterface().queryOnce(getQuery());
            } catch (PrologInterfaceException e) {
                Debug.report(e);
            }
        }
    }

    public static final String HOOK_ID = PDTConsole.CONSOLE_VIEW_ID;
    private ConsoleViewer viewer;
    private Composite partControl;
    private PrologInterface currentPif;
    private Menu contextMenu;
    private Action cutAction;
    private Action copyAction;
    private Action pasteAction;
    private Action selectAllAction;
    private ClearAction clearAction;
    private Action searchAction;
    //   private GuiTracerAction guiTracerAction;
    private PasteAction pasteFileNameAction;
    private RestartAction restartAction;
    private KillAction killAction;
    private GenLoadFileAction genLoadFileAction;
    private CreateNamedProcessAction createProcessAction;
    private HashMap<PrologInterface, PrologSocketConsoleModel> models = new HashMap<PrologInterface, PrologSocketConsoleModel>();
    private Label title;
    private HashMap<PrologInterface, SavedState> viewerStates = new HashMap<PrologInterface, SavedState>();

    private SelectContextPIFAutomatedAction automatedSelector;
    private ConsoleQueryAction activateGuiTracerAction;
    private ConsoleQueryAction deactivateGuiTracerAction;
    private ConsoleQueryAction threadMonitorAction;
    private ConsoleQueryAction debugMonitorAction;

    private PifQueryAction abortAction;
    private PifQueryAction traceAction;
    private Action helpAction;
    private Action configAction;

    @Override
    public void createPartControl(Composite parent) {

        try {
            createPartControl_impl(parent);
        } catch (Throwable t) {
            Debug.report(t);
            throw new RuntimeException(t.getLocalizedMessage(), t);
        }
    }

    private void createPartControl_impl(Composite parent) {

        this.partControl = parent;

        Listener handler = new Listener() {

            @Override
            public void handleEvent(Event event) {
                switch (event.type) {
                case SWT.Show:
                case SWT.Hide:
                    getDefaultPrologConsoleService().fireConsoleVisibilityChanged(PrologConsoleView.this);
                    break;
                case SWT.FocusOut:
                    getDefaultPrologConsoleService().fireConsoleLostFocus(PrologConsoleView.this);
                }

            }

        };
        parent.getParent().addListener(SWT.Show, handler);
        parent.getParent().addListener(SWT.Hide, handler);
        parent.getParent().addListener(SWT.FocusOut, handler);
        PrologConsolePlugin.getDefault().getPrologConsoleService().registerPrologConsole(this);
        getDefaultPrologConsoleService().fireConsoleVisibilityChanged(PrologConsoleView.this);
        PrologRuntimeUIPlugin.getDefault().getPrologInterfaceService().registerActivePrologInterfaceListener(this);
        GridLayout layout = new GridLayout(1, true);
        layout.horizontalSpacing = 0;
        layout.verticalSpacing = 0;
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        parent.setLayout(layout);
        GridData ld = new GridData(GridData.FILL_HORIZONTAL);
        title = new Label(parent, SWT.HORIZONTAL);
        title.setLayoutData(ld);
        viewer = new ConsoleViewer(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
        viewer.getControl().setEnabled(false);
        ld = new GridData(GridData.FILL_BOTH);
        viewer.getControl().setLayoutData(ld);
        createActions();
        initMenus(parent);
        initToolBars();
        getSite().setSelectionProvider(viewer);

    }

    private DefaultPrologConsoleService getDefaultPrologConsoleService() {
        return ((DefaultPrologConsoleService) PrologConsolePlugin.getDefault().getPrologConsoleService());
    }

    private void loadHistory(ConsoleHistory history) {

        try {
            FileInputStream in = new FileInputStream(getHistoryFile());
            history.loadHistory(in);
            in.close();
        } catch (IOException e) {
            Debug.report(e);
        }

    }

    private void createActions() {
        ISharedImages sharedImages = getSite().getWorkbenchWindow().getWorkbench().getSharedImages();
        cutAction = new Action() {
            @Override
            public void run() {
                viewer.cut();
            }
            //         @Override
            //         public boolean isEnabled() {
            //            return ((StyledText)viewer.getControl()).getSelectionRange().y > 0;
            //         }
        };
        cutAction.setText("Cut");
        cutAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_CUT);
        cutAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
        cutAction.setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));

        copyAction = new Action() {
            @Override
            public void run() {
                viewer.copy();
            }
            //         @Override
            //         public boolean isEnabled() {
            //            return ((StyledText)viewer.getControl()).getSelectionRange().y > 0;
            //         }
        };
        copyAction.setText("Copy");
        copyAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY);
        copyAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
        copyAction
                .setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));

        pasteAction = new Action() {
            @Override
            public void run() {
                viewer.paste();
            }
        };
        pasteAction.setText("Paste");
        pasteAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_PASTE);
        pasteAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE));

        selectAllAction = new Action() {
            @Override
            public void run() {
                viewer.selectAll();
            }
        };
        selectAllAction.setText("Select All");
        selectAllAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_SELECT_ALL);

        clearAction = new ClearAction("Clear", "Clear console output",
                ImageRepository.getImageDescriptor(ImageRepository.CLEAR));
        searchAction = new Action("Open Search Dialog") {
            @Override
            public void run() {
                NewSearchUI.openSearchDialog(getSite().getWorkbenchWindow(), PrologSearchPage.EXTENSION_POINT_ID);
            }
        };
        //      guiTracerAction = new GuiTracerAction(new String[] {"guitracer", "noguitracer"},
        //            new String[] {"activate guitracer", "deactivate guitracer"},  
        //            new String[] {"activate GUI tracer", "deactivate GUI tracer"}, 
        //            new ImageDescriptor[] {
        //            ImageRepository.getImageDescriptor(ImageRepository.GUITRACER),
        //            ImageRepository.getImageDescriptor(ImageRepository.NOGUITRACER)});
        activateGuiTracerAction = new ConsoleQueryAction("Activate GUI tracer",
                ImageRepository.getImageDescriptor(ImageRepository.GUITRACER), "guitracer");
        deactivateGuiTracerAction = new ConsoleQueryAction("Deactivate GUI tracer",
                ImageRepository.getImageDescriptor(ImageRepository.NOGUITRACER), "noguitracer");
        threadMonitorAction = new ConsoleQueryAction("Show SWI thread monitor",
                ImageRepository.getImageDescriptor(ImageRepository.THREAD_MONITOR),
                "user:prolog_ide(thread_monitor)");
        debugMonitorAction = new ConsoleQueryAction("Show SWI debug message monitor",
                ImageRepository.getImageDescriptor(ImageRepository.DEBUG_MONITOR),
                "user:prolog_ide(debug_monitor)");
        abortAction = new PifQueryAction("Abort running query",
                ImageRepository.getImageDescriptor(ImageRepository.ABORT),
                bT(PDTConsolePredicates.CONSOLE_THREAD_NAME, "ID") + ", catch(thread_signal(ID, abort),_,fail)") {
            @Override
            public void run() {
                super.run();
                if (!getModel().isConnected()) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                            }
                            try {
                                connect(currentPif);
                            } catch (PrologInterfaceException e) {
                            }
                        }
                    }).start();
                }
            }
        };
        traceAction = new PifQueryAction("Interrupt running query and start tracing",
                ImageRepository.getImageDescriptor(ImageRepository.TRACE),
                bT(PDTConsolePredicates.CONSOLE_THREAD_NAME, "ID") + ", catch(thread_signal(ID, trace),_,fail)");

        pasteFileNameAction = new PasteAction("Paste filename", "Paste the name of the current editor file",
                ImageRepository.getImageDescriptor(ImageRepository.PASTE_FILENAME)) {

            @Override
            protected String getTextToInsert() {
                String fileName = UIUtils.getFileFromActiveEditor();
                if (fileName == null) {
                    return null;
                }
                return Util.quoteAtom(Util.prologFileName(new File(fileName)));
            }

        };
        pasteFileNameAction.setActionDefinitionId(PDTConsole.COMMAND_PASTE_FILENAME);

        IKeyBindingService keyBindingService = getSite().getKeyBindingService();
        keyBindingService.setScopes(new String[] { PDTConsole.CONTEXT_USING_CONSOLE_VIEW });
        keyBindingService.registerAction(pasteFileNameAction);
        restartAction = new RestartAction();
        killAction = new KillAction();
        genLoadFileAction = new GenLoadFileAction();
        createProcessAction = new CreateNamedProcessAction();
        helpAction = new Action("SWI-Prolog Documentation",
                ImageRepository.getImageDescriptor(ImageRepository.HELP)) {
            @Override
            public void run() {
                try {
                    PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser()
                            .openURL(new URL("http://www.swi-prolog.org/pldoc/index.html"));
                } catch (Exception e) {
                }
            }

        };

        configAction = new Action("Console preferences",
                ImageRepository.getImageDescriptor(ImageRepository.PREFERENCES)) {
            @Override
            public void run() {
                PreferenceManager mgr = new PreferenceManager();

                IPreferencePage page = new PreferencePageMain();
                page.setTitle("PDT Console");

                IPreferenceNode node = new PreferenceNode("PreferencePage", page);
                mgr.addToRoot(node);

                PreferenceDialog dialog = new PreferenceDialog(getSite().getShell(), mgr);
                dialog.create();
                dialog.setMessage(page.getTitle());
                dialog.open();
            }
        };
    }

    private void initMenus(Control parent) {

        MenuManager manager = new MenuManager();
        manager.setRemoveAllWhenShown(true);
        manager.addMenuListener(new IMenuListener() {

            @Override
            public void menuAboutToShow(IMenuManager manager) {
                manager.add(new Separator("#Clipboard"));
                manager.add(selectAllAction);
                manager.add(cutAction);
                manager.add(copyAction);
                manager.add(pasteAction);
                manager.add(pasteFileNameAction);
                manager.add(clearAction);
                manager.add(new Separator("#Clipboard-end"));
                manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
                manager.add(searchAction);
                manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS + "-end"));
            }

        });
        getSite().registerContextMenu(manager, viewer);
        contextMenu = manager.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(contextMenu);
    }

    private void initToolBars() {
        IActionBars bars = this.getViewSite().getActionBars();

        bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAllAction);
        bars.setGlobalActionHandler(ActionFactory.CUT.getId(), cutAction);
        bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
        bars.setGlobalActionHandler(ActionFactory.PASTE.getId(), pasteAction);

        IToolBarManager toolBarManager = bars.getToolBarManager();

        addToolbarContributions(toolBarManager);
        addMenuContributions(bars.getMenuManager());

        //      pifSelector.init(getViewSite().getWorkbenchWindow());
        automatedSelector.init(getViewSite().getWorkbenchWindow());

    }

    private void createAutomatedSelector(IToolBarManager toolBarManager) {

        automatedSelector = new SelectContextPIFAutomatedAction() {

            @Override
            protected PrologInterface getPrologInterface() {
                return PrologConsoleView.this.getPrologInterface();
            }

            @Override
            protected void setPrologInterface(PrologInterface prologInterface) {
                PrologConsoleView.this.setPrologInterface(prologInterface);

            }

            @Override
            protected void trackerActivated(PrologContextTracker tracker) {
                setPrologInterface(automatedSelector.getCurrentPrologInterface());

            }

            @Override
            protected void trackerDeactivated(PrologContextTracker tracker) {
                setPrologInterface(automatedSelector.getCurrentPrologInterface());

            }

            @Override
            public void contextChanged(PrologContextTrackerEvent e) {
                PrologContextTracker tracker = (PrologContextTracker) e.getSource();
                Debug.info("context changed for tracker " + tracker.getLabel());
                setPrologInterface(e.getPrologInterface());

            }

        };
        toolBarManager.add(automatedSelector);

        //      pifSelector = new SelectPifAction() {
        //
        //         protected void setPrologInterface(PrologInterface prologInterface) {
        //            PrologConsoleView.this.setPrologInterface(prologInterface);
        //
        //         }
        //
        //         protected PrologInterface getPrologInterface() {
        //            return PrologConsoleView.this.getPrologInterface();
        //         }
        //
        //      };
        //      toolBarManager.add(pifSelector);

        //      contextSelector = new SelectContextsAction() {
        //
        //         public void contextChanged(PrologContextTrackerEvent e) {
        //            PrologContextTracker tracker = (PrologContextTracker) e
        //                  .getSource();
        //            Debug.info("context changed for tracker " + tracker.getLabel());
        //            setPrologInterface(e.getPrologInterface());
        //
        //         }
        //
        //         protected void trackerActivated(PrologContextTracker tracker) {
        //            setPrologInterface(contextSelector.getCurrentPrologInterface());
        //
        //         }
        //
        //         protected void trackerDeactivated(PrologContextTracker tracker) {
        //            setPrologInterface(contextSelector.getCurrentPrologInterface());
        //
        //         }
        //      };

        //      toolBarManager.add(contextSelector);
        //      setPrologInterface(contextSelector.getCurrentPrologInterface());
        setPrologInterface(PDTCommonUtil.getActivePrologInterface());
        automatedSelector.setImageDescriptor(ImageRepository.getImageDescriptor(ImageRepository.MANUAL_MODE));
    }

    public PrologInterface activateNewPrologProcess(PrologInterfaceRegistry registry, String pifKey,
            String configuration) {
        DefaultSubscription subscription = new DefaultSubscription(pifKey + "_indepent", pifKey,
                "Independent prolog process", "Prolog");
        registry.addSubscription(subscription);
        PrologInterface pif = PrologRuntimeUIPlugin.getDefault().getPrologInterface(subscription, configuration);

        if (automatedSelector.getActiveTrackers().isEmpty()) {
            setPrologInterface(pif);
            automatedSelector.setImageDescriptor(ImageRepository.getImageDescriptor(ImageRepository.MANUAL_MODE));
        }
        return pif;
    }

    private void addToolbarContributions(IToolBarManager manager) {
        manager.add(new Separator("#Console"));
        createAutomatedSelector(manager);
        manager.add(createProcessAction);
        manager.add(restartAction);
        manager.add(killAction);
        manager.add(clearAction);
        manager.add(new Separator("#Console-end"));
        manager.add(new Separator("#Query"));
        manager.add(traceAction);
        manager.add(abortAction);
        manager.add(new Separator("#Query-end"));
        manager.add(new Separator("#Toolbar-Other"));
        manager.add(genLoadFileAction);
        manager.add(configAction);
        manager.add(helpAction);
        manager.add(new Separator("#Toolbar-End"));
    }

    private void addMenuContributions(IMenuManager manager) {
        manager.add(activateGuiTracerAction);
        manager.add(deactivateGuiTracerAction);
        manager.add(threadMonitorAction);
        manager.add(debugMonitorAction);
    }

    private File getHistoryFile() {
        String value = PrologConsolePlugin.getDefault().getPreferenceValue(PDTConsole.PREF_CONSOLE_HISTORY_FILE,
                null);
        if (value == null) {
            throw new NullPointerException(
                    "Required property \"" + PDTConsole.PREF_CONSOLE_HISTORY_FILE + "\" was not specified.");
        }
        return new File(value);
    }

    @Override
    public void setFocus() {
        if (viewer == null) {
            Debug.warning("PrologConsoleView.setFocus(): View not instantiated yet.");
            return;
        }
        viewer.getControl().setFocus();
        getDefaultPrologConsoleService().fireConsoleRecievedFocus(this);
    }

    @Override
    public void dispose() {
        PrologConsolePlugin.getDefault().getPrologConsoleService().unregisterPrologConsole(this);
        PrologRuntimeUIPlugin.getDefault().getPrologInterfaceService()
                .unRegisterActivePrologInterfaceListener(this);
        for (Iterator<PrologInterface> it = models.keySet().iterator(); it.hasNext();) {
            PrologInterface pif = it.next();
            try {
                disconnect(pif);
                removeHooks(pif);
            } catch (Throwable e) {
                Debug.report(e);
            }
        }
        models.clear();
        contextMenu.dispose();
        // viewer.getControl().dispose();
        super.dispose();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.cs3.pl.prolog.LifeCycleHook#onInit(org.cs3.pl.prolog.PrologSession)
     */
    @Override
    public void onInit(PrologInterface pif, PrologSession initSession) {
        ;
    }

    private void startServer(PrologInterface pif, PrologSession session) {
        try {
            String queryString = bT(PDTConsolePredicates.PDT_START_CONSOLE_SERVER, "Port",
                    Util.quoteAtom(PrologRuntimePlugin.getDefault().getPrologInterfaceRegistry().getKey(pif)));
            Debug.info("starting console server using: " + queryString);

            Map<String, ?> result = session.queryOnce(queryString);
            if (result == null) {
                Debug.info("starting server failed, which may mean that it is actualy running already.");
                result = session.queryOnce(bT(PDTConsolePredicates.PDT_CURRENT_CONSOLE_SERVER, "Port"));
                if (result == null) {
                    throw new RuntimeException("No Server running.");
                }
            }

            int port = Integer.parseInt((String) result.get("Port"));
            Debug.debug("A server thread seems to be listinging at port " + port);
        } catch (Throwable e) {
            Debug.report(e);
            throw new RuntimeException(e);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.cs3.pl.prolog.LifeCycleHook#afterInit()
     */
    @Override
    public void afterInit(PrologInterface pif) {
        try {
            connect(pif);
        } catch (PrologInterfaceException e) {
            Debug.report(e);
        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.cs3.pl.prolog.LifeCycleHook#beforeShutdown(org.cs3.pl.prolog.PrologSession)
     */
    @Override
    public void beforeShutdown(PrologInterface pif, PrologSession session) {
        ConsoleHistory history = viewer.getHistory();
        saveHistory(history);
        disconnect(pif);
    }

    @Override
    public void onError(PrologInterface pif) {
        ConsoleHistory history = viewer.getHistory();
        saveHistory(history);
        disconnect(pif);

    }

    private void saveHistory(ConsoleHistory history) {
        if (history == null) {
            return;
        }
        try {
            FileOutputStream out = new FileOutputStream(getHistoryFile());
            history.saveHistory(out);
            out.close();
        } catch (IOException e) {
            Debug.report(e);
        }
    }

    @Override
    public ConsoleModel getModel() {
        return (getPrologInterface() == null ? null : models.get(getPrologInterface()));
    }

    @Override
    public PrologInterface getPrologInterface() {
        return currentPif;
    }

    @Override
    public void setPrologInterface(PrologInterface newPif) {
        setPrologInterface(newPif, true);
    }

    private void setPrologInterface(PrologInterface newPif, boolean updateActivePif) {
        if (currentPif == newPif) {
            return;
        }
        if (currentPif != null) {
            viewerStates.put(currentPif, viewer.saveState());
        }
        currentPif = newPif;
        if (currentPif != null) {
            addHooks(currentPif);
            try {
                connect(currentPif);
            } catch (PrologInterfaceException e) {
                Debug.report(e);
            }
            reconfigureViewer(currentPif);
            getDefaultPrologConsoleService().fireActivePrologInterfaceChanged(this);
            if (updateActivePif) {
                PrologRuntimeUIPlugin.getDefault().getPrologInterfaceService().setActivePrologInterface(currentPif);
            }

        } else {
            Debug.debug("no pif (yet).");
        }
        if (automatedSelector != null) {
            automatedSelector.update();
        }
        writeCurrentProcessPortToFile();
    }

    public void writeCurrentProcessPortToFile() {
        try {
            int port = (Integer) currentPif.getClass().getMethod("getPort").invoke(currentPif);
            File portFile = new File(
                    System.getProperty("java.io.tmpdir") + File.separator + "pdt_console_active_port.txt");
            FileWriter writer = new FileWriter(portFile, false);
            writer.write("" + port + "\n");
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void ensureConnectionForCurrentPrologInterface() {
        try {
            connect(currentPif);
        } catch (PrologInterfaceException e) {
            Debug.report(e);
        }
    }

    /*
     * note: implementation should take into account, that this method might be
     * called several times for the same pif, even during one single life cycle.
     * 
     * attach means: ensure a model exsists for this pif. ensure the model is
     * connected. console only attach to a pif that is in UP state.
     * 
     */
    synchronized private void connect(final PrologInterface pif) throws PrologInterfaceException {

        PrologSocketConsoleModel model = getConsoleModel(pif);
        ensureConnection(pif, model);
    }

    private PrologSocketConsoleModel getConsoleModel(final PrologInterface pif) {
        PrologSocketConsoleModel model = models.get(pif);
        if (model == null) {
            model = new PrologSocketConsoleModel(false);
            models.put(pif, model);
        }
        return model;
    }

    private void ensureConnection(final PrologInterface pif, PrologSocketConsoleModel model)
            throws PrologInterfaceException {
        if (model.isConnected()) {
            return;
        }

        PrologSession session = pif.getSession(PrologInterface.NONE);
        //      FileSearchPathConfigurator.configureFileSearchPath(PrologRuntimeUIPlugin.getDefault()
        //            .getLibraryManager(), session,
        //            new String[] { PDTConsole.PL_LIBRARY });

        Map<String, ?> result = null;
        try {
            //         result = session.queryOnce( "consult(lib_pdt_console_pl(loader)).");
            result = session.queryOnce(bT(PDTConsolePredicates.PDT_START_CONSOLE_SERVER, "Port",
                    Util.quoteAtom(PrologRuntimePlugin.getDefault().getPrologInterfaceRegistry().getKey(pif))));
            if (result == null) {
                startServer(pif, session);
                result = session.queryOnce(bT(PDTConsolePredicates.PDT_CURRENT_CONSOLE_SERVER, "Port"));
            }
            if (result == null) {
                throw new RuntimeException("could not install console server");
            }
        } catch (Exception e) {
            Debug.info(e.toString());
        } finally {
            if (session != null) {
                session.dispose();
            }
        }

        int port = Integer.parseInt(result.get("Port").toString());
        model.setPort(port);
        model.connect();
    }

    private void disconnect(PrologInterface pif) {
        PrologSocketConsoleModel model = models.get(pif);
        if (model == null) {
            return;
        }

        model.disconnect();

    }

    private void addHooks(PrologInterface pif) {
        pif.addLifeCycleHook(this, HOOK_ID, new String[0]);

    }

    private void removeHooks(PrologInterface pif) {

        pif.removeLifeCycleHook(HOOK_ID);

    }

    private void reconfigureViewer(final PrologInterface pif) {

        if (Display.getCurrent() != viewer.getControl().getDisplay()) {
            viewer.getControl().getDisplay().asyncExec(new Runnable() {
                @Override
                public void run() {
                    reconfigureViewer(pif);
                }
            });
            return;
        }
        if (pif == null) {

            viewer.setModel(null);
            viewer.setHistory(null);
            viewer.setCompletionProvider(null);
            title.setText("no console available(yet).");
            return;
        }

        ConsoleViewer.SavedState savedState = viewerStates.get(pif);
        if (savedState == null) {
            viewer.clearOutput();
            ConsoleHistory history = new ConsoleHistory(
                    PrologRuntimePlugin.getDefault().getPrologInterfaceRegistry().getKey(pif));
            viewer.setHistory(history);
            loadHistory(history);
            viewer.setModel(models.get(pif));
            PrologCompletionProvider completionProvider = new PrologCompletionProvider();
            completionProvider.setPrologInterface(pif);
            viewer.setCompletionProvider(completionProvider);
        } else {
            viewer.loadState(savedState);
        }
        PrologInterfaceRegistry reg = PrologRuntimePlugin.getDefault().getPrologInterfaceRegistry();
        String key = reg.getKey(pif);
        title.setText(SelectContextPIFAutomatedAction.getLabelForPif(key, reg));
        //      Object configuration = pif.getAttribute(PrologRuntimeUI.CONFIGURATION_ATTRIBUTE);
        //      if (configuration == null) {
        //         title.setText(key);
        //      } else {
        //         title.setText(key + " (" + configuration.toString().replaceAll("&", "&&") + ")");
        //      }

        viewer.setEnterSendsSemicolon(false);

    }

    @Override
    public boolean isVisible() {
        return partControl.getVisible();
    }

    public ConsoleViewer getViewer() {
        return viewer;
    }

    @Override
    public String getText() {
        return getViewer().getText();
    }

    @Override
    public int getLineAtOffset(int offset) {
        return getViewer().getLineAtOffset(offset);
    }

    @Override
    public int getOffsetAtLine(int line) {
        return getViewer().getOffsetAtLine(line);
    }

    @Override
    public int getLineCount() {
        return getViewer().getLineCount();
    }

    @Override
    public void clearOutput() {
        getViewer().clearOutput();

    }

    @Override
    public String getTextRange(int offset, int length) {
        return getViewer().getTextRange(offset, length);
    }

    @Override
    public int getCaretOffset() {
        return getViewer().getCaretOffset();
    }

    @Override
    public int getStartOfInput() {

        return getViewer().getStartOfInput();
    }

    @Override
    public void setCaretOffset(int offset) {
        getViewer().setCaretOffset(offset);

    }

    @Override
    public void setData(Object data) {
        ;
    }

    @Override
    public void lateInit(PrologInterface pif) {
        ;
    }

    @Override
    public void activePrologInterfaceChanged(final PrologInterface pif) {
        Display display = getSite().getShell().getDisplay();
        if (Display.getCurrent() != display) {
            display.asyncExec(new Runnable() {
                @Override
                public void run() {
                    activePrologInterfaceChanged(pif);
                }
            });
        } else {
            setPrologInterface(pif, false);
        }
    }

}