Java tutorial
/******************************************************************************* * 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; } } }