package com.yoursway.introspection.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
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.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
public abstract class AbstractModelMonitoringView extends ViewPart {
public class AbstractChange {
private final int ordinal;
private final long timeMillis;
public AbstractChange() {
this.ordinal = nextChangeOrdinal++;
this.timeMillis = System.currentTimeMillis();
}
public int getOrdinal() {
return ordinal;
}
public long getTimeMillis() {
return timeMillis;
}
}
public abstract class BaseLabelProvider extends LabelProvider implements IFontProvider {
public Font getFont(Object element) {
if (elementsChangedLastTime.contains(element))
return boldFont;
return null;
}
}
protected static final Object[] NO_CHILDREN = new Object[0];
private TreeViewer viewer;
private DrillDownAdapter drillDownAdapter;
private Action action1;
private Action doubleClickAction;
private final List<AbstractChange> recentChanges = new ArrayList<AbstractChange>();
private final Set<Object> elementsChangedLastTime = new HashSet<Object>();
private int nextChangeOrdinal = 1;
private Font boldFont;
protected Object theInput;
public void addElementChangedEvent(final AbstractChange change) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
addElementChangedEvent2(change);
}
});
}
/**
* This is a callback that will allow us to create the viewer and initialize
* it.
*/
@Override
public void createPartControl(Composite parent) {
theInput = new Object();
connectToModel();
viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
drillDownAdapter = new DrillDownAdapter(viewer);
setupTreeViewer(viewer);
// viewer.setSorter(new NameSorter());
viewer.setInput(theInput);
makeActions();
hookContextMenu();
hookDoubleClickAction();
contributeToActionBars();
Font font = viewer.getTree().getFont();
FontData[] fontData = font.getFontData();
fontData[0].setStyle(SWT.BOLD);
boldFont = new Font(null, fontData[0]);
}
@Override
public void dispose() {
super.dispose();
boldFont.dispose();
}
/**
* Passing the focus request to the viewer's control.
*/
@Override
public void setFocus() {
viewer.getControl().setFocus();
}
private void addElementChangedEvent2(AbstractChange change) {
while (recentChanges.size() > 4) {
Object old = recentChanges.remove(recentChanges.size() - 1);
viewer.remove(old);
}
recentChanges.add(0, change);
elementsChangedLastTime.clear();
findChangedItems(change);
viewer.refresh(getModelRoot());
for (Iterator<Object> iterator = elementsChangedLastTime.iterator(); iterator.hasNext();) {
Object el = iterator.next();
viewer.expandToLevel(el, 0);
}
viewer.insert(theInput, change, 0);
if (recentChanges.size() > 2) {
int size = recentChanges.size();
for (int i = 2; i < size; i++)
viewer.collapseToLevel(recentChanges.get(i), TreeViewer.ALL_LEVELS);
}
viewer.expandToLevel(change, TreeViewer.ALL_LEVELS);
}
private void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
private void fillContextMenu(IMenuManager manager) {
manager.add(action1);
manager.add(new Separator());
drillDownAdapter.addNavigationActions(manager);
// Other plug-ins can contribute there actions here
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
private void fillLocalPullDown(IMenuManager manager) {
manager.add(action1);
}
private void fillLocalToolBar(IToolBarManager manager) {
manager.add(action1);
manager.add(new Separator());
drillDownAdapter.addNavigationActions(manager);
}
private void hookContextMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, viewer);
}
private void hookDoubleClickAction() {
viewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
doubleClickAction.run();
}
});
}
private void makeActions() {
action1 = new Action() {
@Override
public void run() {
refreshModel();
viewer.refresh(getModelRoot());
}
};
action1.setText("Refresh");
action1.setToolTipText("Rebuilds the model, if possible");
action1.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
ISharedImages.IMG_OBJS_INFO_TSK));
doubleClickAction = new Action() {
@Override
public void run() {
IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
if (selection != null) {
Object firstElement = selection.getFirstElement();
handleDoubleClick(firstElement);
}
}
};
}
protected void addRecentChangesTo(Collection<Object> result) {
result.addAll(recentChanges);
}
protected abstract void connectToModel();
protected abstract void findChangedItems(AbstractChange change);
protected abstract Object getModelRoot();
protected abstract void handleDoubleClick(Object firstElement);
protected abstract void refreshModel();
protected void reportChangedElement(Object element) {
elementsChangedLastTime.add(element);
}
protected abstract void setupTreeViewer(TreeViewer viewer);
}