org.eclipse.tcf.internal.debug.ui.model.TCFDetailPane.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.tcf.internal.debug.ui.model.TCFDetailPane.java

Source

/*******************************************************************************
 * Copyright (c) 2008, 2014 Wind River Systems, Inc. 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:
 *     Wind River Systems - initial API and implementation
 *******************************************************************************/
package org.eclipse.tcf.internal.debug.ui.model;

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

import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.IDebugView;
import org.eclipse.debug.ui.IDetailPane;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextPresentationListener;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPartSite;

/**
 * This detail pane uses a source viewer to display detailed information about the current
 * selection.
 */
public class TCFDetailPane implements IDetailPane, IPropertyChangeListener {

    public static final String ID = "org.eclipse.tcf.debug.DetailPaneFactory";
    public static final String NAME = "TCF Detail Pane";
    public static final String DESC = "TCF Detail Pane";

    private static final String DETAIL_COPY_ACTION = IDebugView.COPY_ACTION + ".DetailPane"; //$NON-NLS-1$
    private static final String DETAIL_SELECT_ALL_ACTION = IDebugView.SELECT_ALL_ACTION + ".DetailPane"; //$NON-NLS-1$

    private SourceViewer source_viewer;
    private Display display;
    private int generation;
    private IWorkbenchPartSite part_site;
    private final Document document = new Document();
    private final ArrayList<StyleRange> style_ranges = new ArrayList<StyleRange>();
    private final HashMap<RGB, Color> colors = new HashMap<RGB, Color>();
    private final Map<String, IAction> action_map = new HashMap<String, IAction>();
    private final List<String> selection_actions = new ArrayList<String>();
    private StyledStringBuffer doc_buffer;
    private Font mono_font;

    private final ITextPresentationListener presentation_listener = new ITextPresentationListener() {
        public void applyTextPresentation(TextPresentation presentation) {
            for (StyleRange r : style_ranges)
                presentation.addStyleRange(r);
        }
    };

    private class DetailPaneAction extends Action {
        final int op_code;

        DetailPaneAction(String text, int op_code) {
            super(text);
            this.op_code = op_code;
        }

        void update() {
            setEnabled(source_viewer != null && source_viewer.canDoOperation(op_code));
        }

        @Override
        public void run() {
            if (!isEnabled())
                return;
            source_viewer.doOperation(op_code);
        }
    }

    private void createActions() {
        DetailPaneAction action = null;

        action = new DetailPaneAction("Select &All", ITextOperationTarget.SELECT_ALL);
        action.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_SELECT_ALL);
        action_map.put(DETAIL_SELECT_ALL_ACTION, action);

        action = new DetailPaneAction("&Copy", ITextOperationTarget.COPY);
        action.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY);
        action_map.put(DETAIL_COPY_ACTION, action);

        selection_actions.add(DETAIL_COPY_ACTION);

        updateSelectionDependentActions();
    }

    private IAction getAction(String id) {
        return action_map.get(id);
    }

    private void setGlobalAction(String id, IAction action) {
        if (part_site instanceof IViewSite) {
            ((IViewSite) part_site).getActionBars().setGlobalActionHandler(id, action);
        }
    }

    private void createDetailContextMenu(Control menuControl) {
        if (part_site == null)
            return;
        MenuManager manager = new MenuManager();
        manager.setRemoveAllWhenShown(true);
        manager.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager mgr) {
                fillDetailContextMenu(mgr);
            }
        });
        Menu menu = manager.createContextMenu(menuControl);
        menuControl.setMenu(menu);
        part_site.registerContextMenu(ID, manager, source_viewer.getSelectionProvider());
    }

    private void fillDetailContextMenu(IMenuManager menu) {
        //menu.add(new Separator(MODULES_GROUP));
        //menu.add(new Separator());
        menu.add(getAction(DETAIL_COPY_ACTION));
        menu.add(getAction(DETAIL_SELECT_ALL_ACTION));
        menu.add(new Separator());
        menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
    }

    private void updateAction(String id) {
        IAction action = getAction(id);
        if (action instanceof DetailPaneAction)
            ((DetailPaneAction) action).update();
    }

    private void updateSelectionDependentActions() {
        for (String id : selection_actions)
            updateAction(id);
    }

    public Control createControl(Composite parent) {
        assert source_viewer == null;
        source_viewer = new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL);
        source_viewer.configure(new SourceViewerConfiguration());
        source_viewer.setDocument(document);
        source_viewer.setEditable(false);
        source_viewer.addTextPresentationListener(presentation_listener);
        Control control = source_viewer.getControl();
        GridData gd = new GridData(GridData.FILL_BOTH);
        control.setLayoutData(gd);
        display = control.getDisplay();
        createActions();
        // Add the selection listener so selection dependent actions get updated.
        document.addDocumentListener(new IDocumentListener() {
            public void documentAboutToBeChanged(DocumentEvent event) {
            }

            public void documentChanged(DocumentEvent event) {
                updateSelectionDependentActions();
            }
        });
        // Add the selection listener so selection dependent actions get updated.
        source_viewer.getSelectionProvider().addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                updateSelectionDependentActions();
            }
        });
        // Add a focus listener to update actions when details area gains focus
        source_viewer.getControl().addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                if (part_site != null)
                    part_site.setSelectionProvider(source_viewer.getSelectionProvider());
                setGlobalAction(IDebugView.SELECT_ALL_ACTION, getAction(DETAIL_SELECT_ALL_ACTION));
                setGlobalAction(IDebugView.COPY_ACTION, getAction(DETAIL_COPY_ACTION));
                if (part_site instanceof IViewSite)
                    ((IViewSite) part_site).getActionBars().updateActionBars();
            }

            public void focusLost(FocusEvent e) {
                if (part_site != null)
                    part_site.setSelectionProvider(null);
                setGlobalAction(IDebugView.SELECT_ALL_ACTION, null);
                setGlobalAction(IDebugView.COPY_ACTION, null);
                if (part_site instanceof IViewSite)
                    ((IViewSite) part_site).getActionBars().updateActionBars();
            }
        });
        // Add a context menu to the detail area
        createDetailContextMenu(source_viewer.getTextWidget());
        // Add font registry listener
        JFaceResources.getFontRegistry().addListener(this);
        return control;
    }

    public void display(IStructuredSelection selection) {
        if (source_viewer == null)
            return;
        generation++;
        final int g = generation;
        final ArrayList<TCFNode> nodes = new ArrayList<TCFNode>();
        if (selection != null) {
            Iterator<?> iterator = selection.iterator();
            while (iterator.hasNext()) {
                Object next = iterator.next();
                if (next instanceof TCFNode)
                    nodes.add((TCFNode) next);
            }
        }
        Protocol.invokeLater(new Runnable() {
            public void run() {
                if (g != generation)
                    return;
                final StyledStringBuffer s = getDetailText(nodes, this);
                if (s == null)
                    return;
                display.asyncExec(new Runnable() {
                    public void run() {
                        if (g != generation)
                            return;
                        doc_buffer = s;
                        document.set(getStyleRanges(s));
                    }
                });
            }
        });
    }

    private StyledStringBuffer getDetailText(ArrayList<TCFNode> nodes, Runnable done) {
        StyledStringBuffer bf = new StyledStringBuffer();
        if (nodes.size() > 0) {
            bf.enableFullErrorReports(nodes.get(0).model.getShowFullErrorReports());
            for (TCFNode n : nodes) {
                if (n instanceof IDetailsProvider) {
                    if (!((IDetailsProvider) n).getDetailText(bf, done))
                        return null;
                }
            }
        }
        return bf;
    }

    private String getStyleRanges(StyledStringBuffer s) {
        style_ranges.clear();
        for (StyledStringBuffer.Style x : s.getStyle()) {
            StyleRange r = new StyleRange(x.pos, x.len, getColor(x.fg), getColor(x.bg), x.font);
            if ((x.font & StyledStringBuffer.MONOSPACED) != 0) {
                r.fontStyle &= ~StyledStringBuffer.MONOSPACED;
                r.font = getMonospacedFont();
            }
            style_ranges.add(r);
        }
        return s.toString();
    }

    private Color getColor(RGB rgb) {
        if (rgb == null)
            return null;
        Color c = colors.get(rgb);
        if (c == null)
            colors.put(rgb, c = new Color(display, rgb));
        return c;
    }

    private Font getMonospacedFont() {
        if (mono_font == null) {
            FontData[] fd = source_viewer.getControl().getFont().getFontData();
            FontDescriptor d = JFaceResources.getFontDescriptor(IDebugUIConstants.PREF_DETAIL_PANE_FONT);
            if (fd != null && fd.length > 0)
                d = d.setHeight(fd[0].getHeight());
            mono_font = d.createFont(display);
        }
        return mono_font;
    }

    public void propertyChange(PropertyChangeEvent event) {
        for (Color c : colors.values())
            c.dispose();
        colors.clear();
        if (mono_font != null) {
            mono_font.dispose();
            mono_font = null;
            if (doc_buffer != null) {
                document.set(getStyleRanges(doc_buffer));
            }
        }
    }

    public void dispose() {
        JFaceResources.getFontRegistry().removeListener(this);
        if (mono_font != null) {
            mono_font.dispose();
            mono_font = null;
        }
        for (Color c : colors.values())
            c.dispose();
        colors.clear();
        if (source_viewer == null)
            return;
        generation++;
        if (source_viewer.getControl() != null) {
            source_viewer.getControl().dispose();
        }
        source_viewer = null;
        selection_actions.clear();
        action_map.clear();
    }

    public String getDescription() {
        return DESC;
    }

    public String getID() {
        return ID;
    }

    public String getName() {
        return NAME;
    }

    public void init(IWorkbenchPartSite part_site) {
        this.part_site = part_site;
    }

    public boolean setFocus() {
        if (source_viewer == null)
            return false;
        source_viewer.getTextWidget().setFocus();
        return true;
    }
}