/**
* This file is licensed under the University of Illinois/NCSA Open Source License. See LICENSE.TXT for details.
*/
package edu.illinois.codingtracker.replaying;
import java.text.SimpleDateFormat;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;
import edu.illinois.codingtracker.operations.UserOperation;
/**
*
* @author Stas Negara
*
*/
public class OperationSequenceView extends ViewPart {
public static final String ID= "edu.illinois.codingtracker.replaying.views.OperationSequenceView";
private static final SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss:SS");
private static final Color whiteColor= Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);
private static final Color yellowColor= Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);
private static final Color redColor= Display.getCurrent().getSystemColor(SWT.COLOR_RED);
private final OperationSequenceFilter operationSequenceFilter;
private final UserOperationReplayer userOperationReplayer;
private TableViewer tableViewer;
private Text operationTextPane;
private boolean isDoubleClickRefresh= false;
public OperationSequenceView() {
operationSequenceFilter= new OperationSequenceFilter(this);
userOperationReplayer= new UserOperationReplayer(this);
}
@Override
public void setFocus() {
tableViewer.getControl().setFocus();
}
@Override
public void createPartControl(Composite parent) {
parent.setLayout(new GridLayout(1, false));
createViewer(parent);
createOperationTextPane(parent);
}
private void createOperationTextPane(Composite parent) {
final int textPaneRowsCount= 10;
operationTextPane= new Text(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.READ_ONLY | SWT.MULTI | SWT.BORDER);
GC gc= new GC(operationTextPane);
int textPaneHeight= textPaneRowsCount * gc.getFontMetrics().getHeight();
GridData gridData= new GridData();
gridData.heightHint= textPaneHeight;
gridData.grabExcessHorizontalSpace= true;
gridData.horizontalAlignment= GridData.FILL;
operationTextPane.setLayoutData(gridData);
}
private void createViewer(Composite parent) {
tableViewer= new TableViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
tableViewer.setContentProvider(ArrayContentProvider.getInstance());
tableViewer.addFilter(operationSequenceFilter);
createViewerColumns();
createViewerToolBar();
layoutViewer();
addViewerListeners();
}
private void createViewerColumns() {
TableViewerColumn descriptionColumn= createColumn("Operation description", 200);
descriptionColumn.setLabelProvider(new StyledCellLabelProvider() {
@Override
public void update(ViewerCell cell) {
cell.setText(((UserOperation)cell.getElement()).getDescription());
updateCellAppearance(cell);
}
});
TableViewerColumn dateColumn= createColumn("Date", 150);
dateColumn.setLabelProvider(new StyledCellLabelProvider() {
@Override
public void update(ViewerCell cell) {
cell.setText(dateFormat.format(((UserOperation)cell.getElement()).getDate()));
updateCellAppearance(cell);
}
});
TableViewerColumn timestampColumn= createColumn("Timestamp", 90);
timestampColumn.setLabelProvider(new StyledCellLabelProvider() {
@Override
public void update(ViewerCell cell) {
cell.setText(String.valueOf(((UserOperation)cell.getElement()).getTime()));
updateCellAppearance(cell);
}
});
}
private void updateCellAppearance(ViewerCell cell) {
Object cellElement= cell.getElement();
if (userOperationReplayer.isBreakpoint(cellElement)) {
cell.setBackground(redColor);
}
if (userOperationReplayer.isCurrentUserOperation(cellElement)) {
cell.setBackground(yellowColor);
if (!isDoubleClickRefresh) {
cell.scrollIntoView();
}
}
if (!userOperationReplayer.isBreakpoint(cellElement) && !userOperationReplayer.isCurrentUserOperation(cellElement)) {
cell.setBackground(whiteColor);
}
}
private TableViewerColumn createColumn(String title, int width) {
TableViewerColumn viewerColumn= new TableViewerColumn(tableViewer, SWT.NONE);
TableColumn tableColumn= viewerColumn.getColumn();
tableColumn.setText(title);
tableColumn.setWidth(width);
tableColumn.setResizable(true);
tableColumn.setMoveable(false);
return viewerColumn;
}
private void createViewerToolBar() {
userOperationReplayer.addToolBarActions();
operationSequenceFilter.addToolBarActions();
}
private void layoutViewer() {
Table table= tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
GridData gridData= new GridData();
gridData.horizontalAlignment= GridData.FILL;
gridData.verticalAlignment= GridData.FILL;
gridData.grabExcessHorizontalSpace= true;
gridData.grabExcessVerticalSpace= true;
tableViewer.getControl().setLayoutData(gridData);
}
private void addViewerListeners() {
tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
displayInOperationTextPane(((IStructuredSelection)event.getSelection()).getFirstElement());
}
});
tableViewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
UserOperation userOperation= (UserOperation)((IStructuredSelection)event.getSelection()).getFirstElement();
userOperationReplayer.toggleBreakpoint(userOperation);
removeSelection();
isDoubleClickRefresh= true;
updateTableViewerElement(userOperation);
isDoubleClickRefresh= false;
}
});
}
IToolBarManager getToolBarManager() {
return getViewSite().getActionBars().getToolBarManager();
}
Shell getShell() {
return tableViewer.getControl().getShell();
}
Display getDisplay() {
return tableViewer.getControl().getDisplay();
}
void setTableViewerInput(Object object) {
tableViewer.setInput(object);
}
void updateTableViewerElement(UserOperation userOperation) {
tableViewer.update(userOperation, null);
}
void refreshTableViewer() {
tableViewer.refresh();
}
OperationSequenceFilter getOperationSequenceFilter() {
return operationSequenceFilter;
}
void setSelection(ISelection selection) {
tableViewer.setSelection(selection, true);
}
void removeSelection() {
tableViewer.setSelection(null, false);
}
void displayInOperationTextPane(Object object) {
if (object != null) {
//remove \r chars, because they are displayed as little squares
operationTextPane.setText(object.toString().replace("\r", ""));
} else {
operationTextPane.setText("");
}
}
}