Package org.erlide.ui.views.eval

Source Code of org.erlide.ui.views.eval.LiveExpressionsView

/*******************************************************************************
* Copyright (c) 2004 Vlad Dumitrescu and others.
* All rights reserved. This program and the accompanying materials
* are 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
*
* Contributors:
*     Vlad Dumitrescu
*******************************************************************************/
package org.erlide.ui.views.eval;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.action.Action;
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.MessageDialog;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
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.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.ViewPart;
import org.erlide.backend.debug.BackendEvalResult;
import org.erlide.backend.debug.EvalHelper;
import org.erlide.engine.util.OtpRpcFactory;
import org.erlide.runtime.api.IOtpRpc;
import org.erlide.ui.ErlideUIConstants;
import org.erlide.ui.internal.ErlideUIPlugin;
import org.erlide.ui.prefs.PreferenceConstants;
import org.erlide.ui.util.DisplayUtils;
import org.erlide.ui.views.SourceViewerInformationControl;
import org.erlide.util.erlang.OtpErlang;

/**
* @author Vlad Dumitrescu
*/
public class LiveExpressionsView extends ViewPart implements IResourceChangeListener {

    public static final String ID = "org.erlide.ui.views.eval.LiveExpressionsView";

    private Label label;
    private List<LiveExpr> exprs;
    CheckboxTableViewer viewer;
    private Action refreshAction;
    private Action fAddAction;
    Action fRemoveAction;

    private final IOtpRpc backend;

    private final class ListenerImplementation implements Listener {
        private final Table t;
        SourceViewerInformationControl info = null;

        private ListenerImplementation(final Table t) {
            this.t = t;
        }

        @Override
        public void handleEvent(final Event event) {
            switch (event.type) {
            case SWT.Dispose:
            case SWT.KeyDown:
            case SWT.MouseMove: {
                if (info == null) {
                    break;
                }
                info.dispose();
                info = null;
                break;
            }
            case SWT.MouseHover: {
                final TableItem item = t.getItem(new Point(event.x, event.y));
                if (item != null) {
                    String str = item.getText(1);
                    if (str.length() > 0) {
                        // ErlLogger.debug(str);
                        final BackendEvalResult r = EvalHelper.eval(backend,
                                "lists:flatten(io_lib:format(\"~p\", [" + item.getText(1)
                                        + "])).", null);
                        if (r.isOk()) {
                            str = OtpErlang.asString(r.getValue());
                        } else {
                            str = r.getErrorReason().toString();
                        }
                        info = new SourceViewerInformationControl(t.getShell(),
                                SWT.ON_TOP | SWT.TOOL | SWT.RESIZE, SWT.MULTI | SWT.WRAP,
                                PreferenceConstants.EDITOR_TEXT_FONT, null);
                        info.setForegroundColor(t.getDisplay().getSystemColor(
                                SWT.COLOR_INFO_FOREGROUND));
                        info.setBackgroundColor(t.getDisplay().getSystemColor(
                                SWT.COLOR_INFO_BACKGROUND));
                        info.setInformation(str);

                        final Rectangle rect = item.getBounds(1);
                        final int lw = t.getGridLineWidth();
                        final Point pt = t.toDisplay(rect.x + lw, rect.y + lw);
                        info.setLocation(pt);
                        info.setSize(rect.width + lw, t.getBounds().height - rect.y);
                        info.setVisible(true);
                    }
                }
            }
                break;
            }
        }
    }

    private static class LiveExpr {
        String fExpr;
        private String cachedValue = "";
        boolean doEval = false;
        private final IOtpRpc b;

        public LiveExpr(final IOtpRpc b, final String s) {
            fExpr = s;
            this.b = b;
        }

        public void setDoEval(final boolean eval) {
            doEval = eval;
        }

        public String getValue() {
            if (doEval) {
                cachedValue = evaluate();
            }
            return cachedValue;
        }

        private String evaluate() {
            final BackendEvalResult r = EvalHelper.eval(b, fExpr + ".", null);
            if (r.isOk()) {
                return r.getValue().toString();
            }
            return "ERR: " + r.getErrorReason().toString();
        }

        @Override
        public String toString() {
            return fExpr;
        }
    }

    /*
     * The content provider class is responsible for providing objects to the
     * view. It can wrap existing objects in adapters or simply return objects
     * as-is. These objects may be sensitive to the current input of the view,
     * or ignore it and always show the same content (like Task List, for
     * example).
     */
    static class ViewContentProvider implements IStructuredContentProvider {

        private List<LiveExpr> exprlist;

        public ViewContentProvider() {
            super();
        }

        @Override
        @SuppressWarnings("unchecked")
        public void inputChanged(final Viewer v, final Object oldInput,
                final Object newInput) {
            if (newInput instanceof List<?>) {
                exprlist = (List<LiveExpr>) newInput;
            }
        }

        @Override
        public void dispose() {
            exprlist = null;
        }

        @Override
        public Object[] getElements(final Object parent) {
            return exprlist.toArray();
        }

    }

    class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {

        @Override
        public String getColumnText(final Object obj, final int index) {
            final LiveExpr e = (LiveExpr) obj;
            if (index == 0) {
                return e.fExpr;
            }
            if (index == 1) {
                e.setDoEval(viewer.getChecked(e));
                return e.getValue();
            }
            return null;
        }

        @Override
        public Image getColumnImage(final Object obj, final int index) {
            // if (index == 0)
            // return getImage(obj);
            // else
            return null;
        }

        @Override
        public Image getImage(final Object obj) {
            return PlatformUI.getWorkbench().getSharedImages()
                    .getImage(ISharedImages.IMG_OBJ_ELEMENT);
        }
    }

    static class NameSorter extends ViewerSorter {
    }

    public LiveExpressionsView() {
        ResourcesPlugin.getWorkspace().addResourceChangeListener(this,
                IResourceChangeEvent.POST_BUILD);

        backend = OtpRpcFactory.getOtpRpc();
        // TODO make the backend configurable (as for console)
    }

    /**
     * This is a callback that will allow us to create the viewer and initialize
     * it.
     */
    @Override
    public void createPartControl(final Composite parent) {
        label = new Label(parent, SWT.NULL);
        final Table t = new Table(parent, SWT.SINGLE | SWT.V_SCROLL | SWT.FULL_SELECTION
                | SWT.CHECK);
        viewer = new CheckboxTableViewer(t);

        final GridData labelLData = new GridData();
        labelLData.verticalAlignment = GridData.BEGINNING;
        labelLData.horizontalAlignment = GridData.FILL;
        labelLData.widthHint = 300;
        labelLData.heightHint = 14;
        labelLData.horizontalIndent = 0;
        labelLData.horizontalSpan = 1;
        labelLData.verticalSpan = 1;
        labelLData.grabExcessHorizontalSpace = true;
        labelLData.grabExcessVerticalSpace = false;
        label.setLayoutData(labelLData);
        label.setSize(new org.eclipse.swt.graphics.Point(319, 14));

        final GridData viewerLData = new GridData();
        viewerLData.verticalAlignment = GridData.FILL;
        viewerLData.horizontalAlignment = GridData.FILL;
        viewerLData.widthHint = 600;
        viewerLData.heightHint = 150;
        viewerLData.horizontalIndent = 0;
        viewerLData.horizontalSpan = 1;
        viewerLData.verticalSpan = 1;
        viewerLData.grabExcessHorizontalSpace = true;
        viewerLData.grabExcessVerticalSpace = true;
        t.setLayoutData(viewerLData);
        t.setSize(new org.eclipse.swt.graphics.Point(600, 200));

        final GridLayout thisLayout = new GridLayout(1, true);
        parent.setLayout(thisLayout);
        thisLayout.marginWidth = 5;
        thisLayout.marginHeight = 5;
        thisLayout.numColumns = 1;
        thisLayout.makeColumnsEqualWidth = false;
        thisLayout.horizontalSpacing = 0;
        thisLayout.verticalSpacing = 1;

        t.setLinesVisible(true);
        t.setHeaderVisible(true);
        // t.setFont();

        final TableColumn colExpr = new TableColumn(t, SWT.LEAD, 0);
        colExpr.setText("Expression");
        colExpr.setWidth(150);

        final TableColumn colValue = new TableColumn(t, SWT.LEAD, 1);
        colValue.setText("Value");
        colValue.setWidth(t.getSize().x - 50);

        viewer.setColumnProperties(new String[] { "expr", "val" });

        viewer.setContentProvider(new ViewContentProvider());
        viewer.setLabelProvider(new ViewLabelProvider());
        // viewer.setSorter(new NameSorter());

        if (!restoreState()) {
            /* Fill LiveExpressions for first time */
            exprs = new ArrayList<LiveExpr>(10);
            addExpr(new LiveExpr(backend, "erlang:now()"));
        }
        viewer.setInput(exprs);

        final TextCellEditor e = new TextCellEditor(t);
        viewer.setCellEditors(new CellEditor[] { e, null });
        viewer.setCellModifier(new LiveExprCellModifier(this));

        makeActions();
        hookContextMenu();
        contributeToActionBars();
        hookGlobalActions();

        final Listener tableListener = new ListenerImplementation(t);
        t.addListener(SWT.Dispose, tableListener);
        t.addListener(SWT.KeyDown, tableListener);
        t.addListener(SWT.MouseMove, tableListener);
        t.addListener(SWT.MouseHover, tableListener);

        // /////////////

    }

    /* We want Live Expressions to be persistant! */
    IMemento memento; // @jve:decl-index=0:

    @Override
    public void init(final IViewSite site, final IMemento aMemento)
            throws PartInitException {
        init(site);
        memento = aMemento;
    }

    @Override
    public void saveState(final IMemento aMemento) {
        if (exprs.isEmpty()) {
            return;
        }
        final IMemento aMemento2 = aMemento.createChild("LiveExpressions");
        final Iterator<LiveExpr> iter = exprs.iterator();
        while (iter.hasNext()) {
            aMemento2.createChild("expression").putTextData(iter.next().toString());
        }
    }

    private boolean restoreState() {
        if (memento != null) {
            memento = memento.getChild("LiveExpressions");
        }
        if (memento != null) {
            final IMemento[] expressions = memento.getChildren("expression");
            if (expressions.length > 0) {
                exprs = new ArrayList<LiveExpr>(expressions.length);
                for (final IMemento element : expressions) {
                    exprs.add(new LiveExpr(backend, element.getTextData()));
                }
            }
            return true;
        }
        memento = null;
        return false;
    }

    private static class LiveExprCellModifier implements ICellModifier {

        private final LiveExpressionsView view;

        public LiveExprCellModifier(final LiveExpressionsView v) {
            view = v;
        }

        @Override
        public boolean canModify(final Object element, final String property) {
            if ("expr".equals(property)) {
                return true;
            }
            return false;
        }

        @Override
        public Object getValue(final Object element, final String property) {
            Object result = null;
            final LiveExpr el = (LiveExpr) element;
            result = el.fExpr;
            return result;
        }

        @Override
        public void modify(final Object element, final String property, final Object value) {
            LiveExpr el;
            // get around bug in TableEditorImpl
            if (element instanceof TableItem) {
                el = (LiveExpr) ((TableItem) element).getData();
            } else {
                el = (LiveExpr) element;
            }
            el.fExpr = (String) value;
            el.cachedValue = "";
            view.updateExpr(el);
        }
    }

    private void hookContextMenu() {
        final MenuManager menuMgr = new MenuManager("#PopupMenu");
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {

            @Override
            public void menuAboutToShow(final IMenuManager manager) {
                LiveExpressionsView.this.fillContextMenu(manager);
            }
        });
        final Menu menu = menuMgr.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(menu);
        getSite().registerContextMenu(menuMgr, viewer);
    }

    private void contributeToActionBars() {
        final IActionBars bars = getViewSite().getActionBars();
        fillLocalPullDown(bars.getMenuManager());
        fillLocalToolBar(bars.getToolBarManager());
    }

    private void fillLocalPullDown(final IMenuManager manager) {
        manager.add(refreshAction);
        manager.add(fAddAction);
        manager.add(fRemoveAction);
        manager.add(new Separator());
    }

    void fillContextMenu(final IMenuManager manager) {
        manager.add(refreshAction);
        manager.add(fAddAction);
        manager.add(fRemoveAction);
        // Other plug-ins can contribute there actions here
        manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
    }

    private void fillLocalToolBar(final IToolBarManager manager) {
        manager.add(refreshAction);
        manager.add(fAddAction);
        manager.add(fRemoveAction);
    }

    private void makeActions() {
        refreshAction = new Action() {

            @Override
            public void run() {
                refreshView();
            }
        };
        refreshAction.setText("Refresh");
        refreshAction.setToolTipText("Refresh expressions");
        refreshAction.setImageDescriptor(ErlideUIPlugin.getDefault().getImageDescriptor(
                ErlideUIConstants.IMG_REFRESH));

        fAddAction = new Action() {

            @Override
            public void run() {
                addExpr(new LiveExpr(backend, "expr"));
            }
        };
        fAddAction.setText("Add expression");
        fAddAction.setToolTipText("Add new expression");
        fAddAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
                .getImageDescriptor(ISharedImages.IMG_TOOL_NEW_WIZARD));

        fRemoveAction = new Action() {

            @Override
            public void run() {
                delExpr();
            }
        };
        fRemoveAction.setText("Delete expression");
        fRemoveAction.setToolTipText("Delete expression");
        fRemoveAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
                .getImageDescriptor(ISharedImages.IMG_TOOL_DELETE));

    }

    private void hookGlobalActions() {
        final IActionBars bars = getViewSite().getActionBars();
        bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), fRemoveAction);
        viewer.getControl().addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(final KeyEvent event) {
                if (event.character == SWT.DEL && event.stateMask == 0
                        && fRemoveAction.isEnabled()) {
                    fRemoveAction.run();
                }
            }
        });
    }

    void showMessage(final String message) {
        MessageDialog.openInformation(viewer.getControl().getShell(),
                "Process list view", message);
    }

    /**
     * Passing the focus request to the viewer's control.
     */
    @Override
    public void setFocus() {
        viewer.getControl().setFocus();
    }

    @Override
    public void resourceChanged(final IResourceChangeEvent event) {
        refreshView();
    }

    private void refreshView() {
        if (!viewer.getControl().isDisposed()) {
            DisplayUtils.asyncExec(new Runnable() {

                @Override
                public void run() {
                    if (viewer == null) {
                        return;
                    }
                    if (viewer.getControl().isDisposed()) {
                        return;
                    }
                    viewer.refresh();
                }
            });
        }
    }

    public void addExpr(final LiveExpr e) {
        exprs.add(e);
        refreshView();
    }

    public void updateExpr(final LiveExpr e) {
        refreshView();
    }

    public void delExpr() {
        final IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
        final Iterator<LiveExpr> iter = sel.iterator();
        while (iter.hasNext()) {
            exprs.remove(iter.next());
        }
        refreshView();
    }

}
TOP

Related Classes of org.erlide.ui.views.eval.LiveExpressionsView

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.