org.eclipse.e4.tools.event.spy.internal.ui.CapturedEventTree.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.e4.tools.event.spy.internal.ui.CapturedEventTree.java

Source

/*******************************************************************************
 * Copyright (c) 2013 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.e4.tools.event.spy.internal.ui;

import java.util.ArrayList;

import org.eclipse.core.databinding.beans.PojoObservables;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
import org.eclipse.e4.tools.event.spy.internal.model.CapturedEvent;
import org.eclipse.e4.tools.event.spy.internal.model.IEventItem;
import org.eclipse.e4.tools.event.spy.internal.model.ItemToFilter;
import org.eclipse.e4.tools.event.spy.internal.util.JDTUtils;
import org.eclipse.jface.databinding.viewers.ObservableListTreeContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.TreeStructureAdvisor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Resource;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;

public class CapturedEventTree extends TreeViewer {
    private ICapturedEventTreeListener listener;

    private WritableList capturedEvents;

    private Clipboard clipboard;

    private TreeItemCursor treeItemCursor;

    private TreeItemForeground treeItemForeground;

    private TreeItemBackground treeItemBackground;

    private TreeItemFont treeItemFont;

    private SelectedTreeItem selectedClassNameTreeItem;

    private SelectedTreeItem selectedTreeItem;

    public CapturedEventTree(Composite parent) {
        super(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);

        getTree().setHeaderVisible(true);
        getTree().setLinesVisible(true);

        TreeColumn column = new TreeColumn(getTree(), SWT.LEFT);
        column.setText(ItemToFilter.Topic.toString());
        column.setWidth(350);

        column = new TreeColumn(getTree(), SWT.LEFT);
        column.setText(ItemToFilter.Publisher.toString());
        column.setWidth(150);

        column = new TreeColumn(getTree(), SWT.LEFT);
        column.setText(ItemToFilter.ChangedElement.toString());
        column.setWidth(150);

        ObservableListTreeContentProvider contentProvider = new ObservableListTreeContentProvider(
                new CapturedEventsObservableFactory(), new CapturedEventsTreeStructureAdvisor());
        setContentProvider(contentProvider);

        IObservableMap[] attributes = PojoObservables.observeMaps(contentProvider.getKnownElements(),
                IEventItem.class, new String[] { "name", "param1", "param2" });
        setLabelProvider(new ObservableMapLabelProvider(attributes));

        capturedEvents = new WritableList(new ArrayList<CapturedEvent>(), CapturedEvent.class);
        setInput(capturedEvents);

        clipboard = new Clipboard(getTree().getDisplay());

        createTreeItemResources();

        addTreeEventListeners();
    }

    private static class CapturedEventsTreeStructureAdvisor extends TreeStructureAdvisor {
        @Override
        public Boolean hasChildren(Object element) {
            if (element instanceof CapturedEvent) {
                return !((CapturedEvent) element).getParameters().isEmpty();
            }
            return false;
        }
    }

    private static class CapturedEventsObservableFactory implements IObservableFactory {
        @Override
        public IObservable createObservable(Object target) {
            if (target instanceof IObservableList) {
                return (IObservableList) target;
            }
            if (target instanceof CapturedEvent) {
                return PojoObservables.observeList(target, "parameters");
            }
            return null;
        }
    }

    private void createTreeItemResources() {
        Display display = getTree().getDisplay();

        treeItemCursor = new TreeItemCursor(getTree().getCursor(), display.getSystemCursor(SWT.CURSOR_HAND));

        treeItemForeground = new TreeItemForeground(new Color(display, new RGB(0, 0, 120)),
                display.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT), display.getSystemColor(SWT.COLOR_BLACK));

        treeItemBackground = new TreeItemBackground(display.getSystemColor(SWT.COLOR_LIST_SELECTION),
                getTree().getBackground());

        Font currentFont = getTree().getFont();
        FontData currentFontData = currentFont.getFontData()[0];
        treeItemFont = new TreeItemFont(currentFont,
                new Font(display, currentFontData.getName(), currentFontData.getHeight(), SWT.ITALIC));

        selectedClassNameTreeItem = new SelectedTreeItem() {
            @Override
            public void clear() {
                redrawTreeItem(getTreeItem(), getColumnIndex());
                super.clear();

                Tree tree = getTree();
                if (tree.getCursor() != treeItemCursor.getDefaultCursor()) {
                    tree.setCursor(treeItemCursor.getDefaultCursor());
                }
            }
        };

        selectedTreeItem = new SelectedTreeItem() {
            @Override
            public void clear() {
                redrawTreeItem(getTreeItem(), getColumnIndex());
                super.clear();
            }
        };
    }

    private void addTreeEventListeners() {
        getTree().addDisposeListener(new DisposeListener() {
            @Override
            public void widgetDisposed(DisposeEvent e) {
                if (clipboard != null && !clipboard.isDisposed()) {
                    clipboard.dispose();
                }
                disposeResource(treeItemForeground.getParamColor());
                disposeResource(treeItemFont.getSelectedClassNameFont());
            }

            private void disposeResource(Resource resource) {
                if (resource != null && !resource.isDisposed()) {
                    resource.dispose();
                }
            }
        });

        getTree().addMouseMoveListener(new MouseMoveListener() {
            @Override
            public void mouseMove(MouseEvent e) {
                selectedClassNameTreeItem.clear();

                // we can select and finally open the class only when 'ctrl' is
                // pressed
                if ((e.stateMask & SWT.CTRL) != SWT.CTRL) {
                    return;
                }

                TreeItem item = getTree().getItem(new Point(e.x, e.y));
                int index = getSelectedColumnIndex(item, e.x, e.y);

                if (index > 0 /* we check the 2nd and 3rd column only */ && item.getParentItem() == null /*
                                                                                                         * we don't check parameters at
                                                                                                         * this moment
                                                                                                         */) {
                    String text = item.getText(index);
                    if (JDTUtils.containsClassName(text)) {
                        selectedClassNameTreeItem.setText(text);
                        selectedClassNameTreeItem.setColumnIndex(index);
                        selectedClassNameTreeItem.setTreeItem(item);
                        getTree().setCursor(treeItemCursor.getPointerCursor());
                        redrawTreeItem(item, index);
                    }
                }
            }
        });

        getTree().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDown(MouseEvent e) {
                TreeItem item = getTree().getItem(new Point(e.x, e.y));
                updateSelectedTreeItem(item, getSelectedColumnIndex(item, e.x, e.y));

                if (listener != null && (e.stateMask & SWT.CTRL) == SWT.CTRL
                        && selectedClassNameTreeItem.getText() != null) {
                    listener.treeItemWithClassNameClicked(selectedClassNameTreeItem.getText());
                }
            }
        });

        getTree().addListener(SWT.EraseItem, new Listener() {
            @Override
            public void handleEvent(Event event) {
                if ((event.detail & SWT.FOREGROUND) == SWT.FOREGROUND) {
                    event.detail &= ~SWT.FOREGROUND;
                }
                if ((event.detail & SWT.SELECTED) == SWT.SELECTED) {
                    event.detail &= ~SWT.SELECTED;
                }
            }
        });

        getTree().addListener(SWT.PaintItem, new Listener() {
            @Override
            public void handleEvent(Event event) {
                TreeItem item = (TreeItem) event.item;
                String text = item.getText(event.index);
                int xOffset = item.getParentItem() != null ? 10 : 2;
                Rectangle rec = item.getBounds(event.index);

                event.gc.setFont(getFont(item, event.index));
                event.gc.setForeground(getForeground(item, event.index));
                event.gc.setBackground(getBackground(item, event.index));
                event.gc.fillRectangle(rec.x, rec.y, rec.width, rec.height);
                event.gc.drawText(text, event.x + xOffset, event.y, true);
            }
        });

        getTree().addKeyListener(new KeyListener() {
            @Override
            public void keyPressed(KeyEvent e) {
                String text = selectedTreeItem.getText();
                if (text == null || (e.stateMask & SWT.CTRL) != SWT.CTRL) {
                    return;
                }
                if (e.keyCode == 'c' && text.trim().length() > 0) {
                    clipboard.setContents(new Object[] { text }, new Transfer[] { TextTransfer.getInstance() });
                } else if (e.keyCode == SWT.ARROW_LEFT) {
                    updateSelectedTreeItem(selectedTreeItem.getTreeItem(),
                            Math.max(0, selectedTreeItem.getColumnIndex() - 1));
                } else if (e.keyCode == SWT.ARROW_RIGHT) {
                    updateSelectedTreeItem(selectedTreeItem.getTreeItem(),
                            Math.min(getTree().getColumnCount() - 1, selectedTreeItem.getColumnIndex() + 1));
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
                selectedClassNameTreeItem.clear();
            }
        });

        getTree().addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if ((e.stateMask & SWT.BUTTON1) != SWT.BUTTON1) {
                    updateSelectedTreeItem((TreeItem) e.item,
                            selectedTreeItem.getText() != null ? selectedTreeItem.getColumnIndex() : 0);
                }
            }
        });

        getTree().addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                selectedClassNameTreeItem.clear();
            }
        });
    }

    private void updateSelectedTreeItem(TreeItem item, int columnIndex) {
        if (columnIndex > -1) {
            selectedTreeItem.clear(); // clear old selection
            selectedTreeItem.setTreeItem(item);
            selectedTreeItem.setColumnIndex(columnIndex);
            selectedTreeItem.setText(item.getText(columnIndex));
            redrawTreeItem(item, columnIndex);
        }
    }

    private Color getForeground(TreeItem item, int index) {
        if (selectedTreeItem.getTreeItem() == item && selectedTreeItem.getColumnIndex() == index) {
            return treeItemForeground.getSelectedColor();
        }
        if (item.getParentItem() != null) {
            return treeItemForeground.getParamColor();
        }
        return treeItemForeground.getDefaultColor();
    }

    private Color getBackground(TreeItem item, int index) {
        if (selectedTreeItem.getTreeItem() == item && selectedTreeItem.getColumnIndex() == index) {
            return treeItemBackground.getSelectedColor();
        }
        return treeItemBackground.getDefaultColor();
    }

    private Font getFont(TreeItem item, int columnIndex) {
        if (selectedClassNameTreeItem.getTreeItem() == item
                && selectedClassNameTreeItem.getColumnIndex() == columnIndex) {
            return treeItemFont.getSelectedClassNameFont();
        }
        return treeItemFont.getDefaultFont();
    }

    private void redrawTreeItem(TreeItem item, int columnIndex) {
        if (item != null && !item.isDisposed()) {
            Rectangle rec = item.getBounds(columnIndex);
            getTree().redraw(rec.x, rec.y, rec.width, rec.height, true);
        }
    }

    private int getSelectedColumnIndex(TreeItem item, int mouseX, int mouseY) {
        for (int i = 0; item != null && i < getTree().getColumnCount(); i++) {
            Rectangle rec = item.getBounds(i);
            if (mouseX >= rec.x && mouseX <= rec.x + rec.width) {
                return i;
            }
        }
        return -1;
    }

    public void addEvent(CapturedEvent event) {
        capturedEvents.add(event);
    }

    public void setListener(ICapturedEventTreeListener listener) {
        this.listener = listener;
    }

    public void removeAll() {
        capturedEvents.clear();
    }

    private static class TreeItemForeground {
        private final Color paramColor;

        private final Color selectedColor;

        private final Color defaultColor;

        public TreeItemForeground(Color paramColor, Color selectedColor, Color defaultColor) {
            this.paramColor = paramColor;
            this.selectedColor = selectedColor;
            this.defaultColor = defaultColor;
        }

        public Color getParamColor() {
            return paramColor;
        }

        public Color getSelectedColor() {
            return selectedColor;
        }

        public Color getDefaultColor() {
            return defaultColor;
        }
    }

    private static class TreeItemBackground {
        private final Color selectedColor;

        private final Color defaultColor;

        public TreeItemBackground(Color selectedColor, Color defaultColor) {
            this.selectedColor = selectedColor;
            this.defaultColor = defaultColor;
        }

        public Color getSelectedColor() {
            return selectedColor;
        }

        public Color getDefaultColor() {
            return defaultColor;
        }
    }

    private static class TreeItemCursor {
        private final Cursor defaultCursor;

        private final Cursor pointerCursor;

        public TreeItemCursor(Cursor defaultCursor, Cursor pointerCursor) {
            this.defaultCursor = defaultCursor;
            this.pointerCursor = pointerCursor;
        }

        public Cursor getDefaultCursor() {
            return defaultCursor;
        }

        public Cursor getPointerCursor() {
            return pointerCursor;
        }
    }

    private static class TreeItemFont {
        private final Font defaultFont;

        private final Font selectedClassNameFont;

        public TreeItemFont(Font defaultFont, Font selectedClassNameFont) {
            this.defaultFont = defaultFont;
            this.selectedClassNameFont = selectedClassNameFont;
        }

        public Font getDefaultFont() {
            return defaultFont;
        }

        public Font getSelectedClassNameFont() {
            return selectedClassNameFont;
        }
    }

    private static class SelectedTreeItem {
        private TreeItem treeItem;

        private int columnIndex;

        private String text;

        public SelectedTreeItem() {
            clear();
        }

        public void setTreeItem(TreeItem treeItem) {
            this.treeItem = treeItem;
        }

        public TreeItem getTreeItem() {
            return treeItem;
        }

        public void setColumnIndex(int columnIndex) {
            this.columnIndex = columnIndex;
        }

        public int getColumnIndex() {
            return columnIndex;
        }

        public void setText(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public void clear() {
            treeItem = null;
            columnIndex = -1;
            text = null;
        }
    }
}