package org.ntlab.traceDebugger;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableColorProvider;
import org.eclipse.jface.viewers.ITreeViewerListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeExpansionEvent;
import org.eclipse.jface.viewers.TreeNode;
import org.eclipse.jface.viewers.TreeNodeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.ntlab.traceAnalysisPlatform.tracer.trace.TracePoint;
import org.ntlab.traceDebugger.analyzerProvider.AbstractAnalyzer;
import org.ntlab.traceDebugger.analyzerProvider.DeltaExtractionAnalyzer;
import org.ntlab.traceDebugger.analyzerProvider.DeltaMarkerManager;
public class VariableView extends ViewPart {
private TreeViewer viewer;
private IAction jumpAction;
private IAction deltaAction;
private Variable selectedVariable;
private Variables variables = Variables.getInstance();
public static final String ID = "org.ntlab.traceDebugger.variableView";
public VariableView() {
// TODO Auto-generated constructor stub
System.out.println("VariableViewクラスが生成されたよ!");
}
@Override
public void createPartControl(Composite parent) {
// TODO Auto-generated method stub
System.out.println("VariableView#createPartControl(Composite)が呼ばれたよ!");
viewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
Tree tree = viewer.getTree();
tree.setHeaderVisible(true);
tree.setLinesVisible(true);
String[] treeColumnTexts = {"Name", "Value"};
int[] treeColumnWidth = {100, 200};
TreeColumn[] treeColumns = new TreeColumn[treeColumnTexts.length];
for (int i = 0; i < treeColumns.length; i++) {
treeColumns[i] = new TreeColumn(tree, SWT.NULL);
treeColumns[i].setText(treeColumnTexts[i]);
treeColumns[i].setWidth(treeColumnWidth[i]);
}
viewer.setContentProvider(new TreeNodeContentProvider());
viewer.setLabelProvider(new VariableLabelProvider());
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection sel = (IStructuredSelection)event.getSelection();
Object element = sel.getFirstElement();
if (element instanceof TreeNode) {
Object value = ((TreeNode)element).getValue();
if (value instanceof Variable) {
selectedVariable = (Variable)value;
}
}
}
});
viewer.addTreeListener(new ITreeViewerListener() {
@Override
public void treeExpanded(TreeExpansionEvent event) {
// ツリーを開いた後に実行される。 ここでは開いたノードから3つ先のノードを生成して追加する。
Object element = event.getElement();
if (!(element instanceof TreeNode)) return;
TreeNode expandedNode = (TreeNode)element;
Object value = expandedNode.getValue();
if (!(value instanceof Variable)) return;
TreeNode[] childNodes = expandedNode.getChildren();
if (childNodes == null) return;
for (TreeNode childNode : childNodes) {
TreeNode[] grandChildNodes = childNode.getChildren();
if (grandChildNodes == null) continue;
for (TreeNode grandChildNode : grandChildNodes) {
Variable grandChildVariable = (Variable)grandChildNode.getValue();
grandChildVariable.createNextHierarchyState();
List<Variable> list = grandChildVariable.getChildren();
TreeNode[] nodes = new TreeNode[list.size()];
for (int i = 0; i < list.size(); i++) {
nodes[i] = new TreeNode(list.get(i));
}
grandChildNode.setChildren(nodes);
}
}
viewer.refresh();
}
@Override
public void treeCollapsed(TreeExpansionEvent event) {}
});
createActions();
createToolBar();
createMenuBar();
createPopupMenu();
}
@Override
public void setFocus() {
// TODO Auto-generated method stub
viewer.getControl().setFocus();
}
private void createActions() {
jumpAction = new Action() {
public void run() {
TracePoint tp = selectedVariable.getLastUpdatePoint();
if (tp == null) return;
DebuggingController controller = DebuggingController.getInstance();
controller.jumpToTheTracePoint(tp);
controller.stepOverAction();
}
};
jumpAction.setText("Jump to Creation Point");
jumpAction.setToolTipText("Jump to Creation Point");
deltaAction = new Action() {
@Override
public void run() {
AbstractAnalyzer analyzer = TraceDebuggerPlugin.getAnalyzer();
if (analyzer instanceof DeltaExtractionAnalyzer) {
DeltaExtractionAnalyzer deltaAnalyzer = (DeltaExtractionAnalyzer)analyzer;
deltaAnalyzer.extractDelta(selectedVariable);
TracePoint coordinatorPoint = deltaAnalyzer.getCoordinatorPoint();
DebuggingController controller = DebuggingController.getInstance();
controller.jumpToTheTracePoint(coordinatorPoint);
IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchPage workbenchPage = workbench.getActiveWorkbenchWindow().getActivePage();
try {
// note: 同一ビューを複数開くテスト
workbenchPage.showView("org.eclipse.ui.views.AllMarkersView", "tmp" + Math.random(), IWorkbenchPage.VIEW_ACTIVATE);
} catch (PartInitException e) {
e.printStackTrace();
}
expandParticularNodes();
}
}
};
deltaAction.setText("Extract Delta");
deltaAction.setToolTipText("Extract Delta");
}
private void expandParticularNodes() {
Map<String, Set<String>> markerIdToObjectIdSet = DeltaMarkerManager.getInstance().getMarkerIdToObjectIdSet();
Set<String> srcSideIdSet = new HashSet<>(markerIdToObjectIdSet.get(DeltaMarkerManager.DELTA_MARKER_ID));
Set<String> dstSideIdSet = new HashSet<>(markerIdToObjectIdSet.get(DeltaMarkerManager.DELTA_MARKER_ID_2));
// Set<String> idSet = new HashSet<>(DeltaMarkerManager.getInstance().getIdSet());
Set<TreeNode> expandNodes = new HashSet<>();
Object obj = viewer.getTree().getTopItem().getData();
if (!(obj instanceof TreeNode)) return;
TreeNode node = (TreeNode)obj;
Object value = node.getValue();
if (!(value instanceof Variable)) return;
expandParticularNodes(srcSideIdSet, dstSideIdSet, expandNodes, node);
viewer.setExpandedElements(expandNodes.toArray(new Object[expandNodes.size()]));
}
private void expandParticularNodes(Set<String> srcSideIdSet, Set<String> dstSideIdSet, Set<TreeNode> expandNodes, TreeNode node) {
// if (idSet.isEmpty()) return;
Object value = node.getValue();
if (!(value instanceof Variable)) return;
Variable variable = (Variable)value;
String id = variable.getId();
if (srcSideIdSet.contains(id)) {
variable.setSrcSideRelatedDelta(true);
srcSideIdSet.remove(id);
TreeNode parent = node.getParent();
if (parent != null) {
expandNodes.add(node.getParent());
}
} else if (dstSideIdSet.contains(id)) {
variable.setDstSideRelatedDelta(true);
dstSideIdSet.remove(id);
TreeNode parent = node.getParent();
if (parent != null) {
expandNodes.add(node.getParent());
}
}
TreeNode[] children = node.getChildren();
if (children == null) return;
for (TreeNode child : children) {
expandParticularNodes(srcSideIdSet, dstSideIdSet, expandNodes, child);
}
}
private void createToolBar() {
IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();
}
private void createMenuBar() {
IMenuManager mgr = getViewSite().getActionBars().getMenuManager();
}
private void createPopupMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager manager) {
manager.add(jumpAction);
manager.add(deltaAction);
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, viewer);
}
public void reset() {
variables.resetData();
viewer.setInput(variables.getVariablesTreeNodes());
viewer.refresh();
}
public void updateVariablesByTracePoint(TracePoint tp, boolean isReturned) {
variables.getAllObjectDataByTracePoint(tp, isReturned);
viewer.setInput(variables.getVariablesTreeNodes());
}
private IViewPart getOtherView(String viewId) {
IWorkbenchPage workbenchPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
try {
return workbenchPage.showView(viewId);
} catch (PartInitException e) {
throw new RuntimeException(e);
}
}
}