/*
RegisterViewer.java
(c) 2011-2014 Edward Swartz
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
*/
package v9t9.gui.client.swt.shells.debugger;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.BaseLabelProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.ejs.gui.common.FontUtils;
import ejs.base.utils.HexUtils;
import v9t9.common.machine.IMachine;
/**
* @author ejs
*
*/
public class RegisterViewer extends Composite {
class RegisterLabelProvider extends BaseLabelProvider implements ITableLabelProvider {
/**
* @param regProvider
*/
public RegisterLabelProvider() {
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
*/
@Override
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
*/
@Override
public String getColumnText(Object element, int columnIndex) {
IRegister reg = (IRegister)element;
if (columnIndex == 0)
return reg.getInfo().id;
int val = reg.getValue();
int size = reg.getInfo().size;
return (size == 1) ? HexUtils.toHex2(val) : HexUtils.toHex4(val);
}
}
private TableViewer[] regViewers;
private Font tableFont;
private Font smallerFont;
private Runnable updateTask;
/**
* @param parent
* @param machine
* @param style
*/
public RegisterViewer(Composite parent, IMachine machine, final IRegisterProvider regProvider, int perColumn) {
super(parent, SWT.NONE);
setLayout(new GridLayout());
Label label = new Label(this, SWT.NONE);
label.setText(regProvider.getLabel());
GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(label);
FontDescriptor fontDescriptor = FontUtils.getFontDescriptor(JFaceResources.getTextFont());
tableFont = fontDescriptor.createFont(getDisplay());
FontDescriptor smallerFontDescriptor = fontDescriptor.increaseHeight(-2);
smallerFont = smallerFontDescriptor.createFont(getDisplay());
ScrolledComposite tableScroller = new ScrolledComposite(this, SWT.H_SCROLL);
GridDataFactory.fillDefaults().grab(true, true).span(1, 1).applyTo(tableScroller);
Composite tables = new Composite(tableScroller, SWT.NONE);
tables.setLayout(new GridLayout());
GridDataFactory.fillDefaults().grab(true, true).span(1, 1).applyTo(tables);
tableScroller.setContent(tables);
tableScroller.setExpandHorizontal(true);
tableScroller.setExpandVertical(true);
int cnt = regProvider.getRegisterCount();
if (cnt % perColumn < 3)
perColumn++;
int numColumns = (cnt + perColumn - 1) / perColumn;
GridLayoutFactory.swtDefaults().numColumns(numColumns).applyTo(tables);
int startReg = 0;
regViewers = new TableViewer[numColumns];
int idx = 0;
while (startReg < cnt) {
int endReg = Math.min(startReg + perColumn, cnt);
regViewers[idx] = createTable(tables, regProvider, startReg, endReg - startReg);
GridDataFactory.fillDefaults().grab(true, true).applyTo(regViewers[idx].getTable());
startReg = endReg;
idx++;
}
tableScroller.setMinSize(tables.computeSize(SWT.DEFAULT, SWT.DEFAULT));
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
tableFont.dispose();
smallerFont.dispose();
}
});
}
/**
* @param tables
* @param regProvider
* @param startReg
* @param i
* @return
*/
private TableViewer createTable(Composite tables,
final IRegisterProvider regProvider, final int startReg, final int count) {
///
final TableViewer regViewer = new TableViewer(tables, SWT.BORDER + SWT.VIRTUAL + SWT.NO_FOCUS + SWT.FULL_SELECTION);
regViewer.setContentProvider(new IStructuredContentProvider() {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
@Override
public Object[] getElements(Object inputElement) {
return regProvider.getRegisters(startReg, count);
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
viewer.refresh();
}
@Override
public void dispose() {
}
});
regViewer.setLabelProvider(new RegisterLabelProvider());
final Table table = regViewer.getTable();
GridDataFactory.fillDefaults().grab(true, true).span(1, 1).applyTo(table);
table.setFont(smallerFont);
GC gc = new GC(getDisplay());
gc.setFont(smallerFont);
int charWidth = gc.stringExtent("M").x;
gc.dispose();
String[] props = new String[6];
props[0] = "Name";
final TableColumn nameColumn = new TableColumn(table, SWT.LEFT);
nameColumn.setText(props[0]);
nameColumn.setWidth(charWidth * 8 + 4);
props[1] = "Value";
final TableColumn valColumn = new TableColumn(table, SWT.LEFT);
valColumn.setText(props[1]);
valColumn.setMoveable(true);
valColumn.setWidth(charWidth * 6);
//table.setHeaderVisible(true);
table.setLinesVisible(true);
regViewer.setColumnProperties(props);
CellEditor[] editors = new CellEditor[2];
editors[0] = null;
editors[1] = new TextCellEditor(table);
regViewer.setColumnProperties(props);
regViewer.setCellModifier(new RegisterCellModifier(regViewer, regProvider.getNumDigits()));
regViewer.setCellEditors(editors);
regViewer.setInput(new Object());
table.addMouseTrackListener(new MouseTrackAdapter() {
@Override
public void mouseHover(MouseEvent e) {
TableItem item = table.getItem(new Point(e.x, e.y));
if (item != null) {
for (int i = 0; i <= 16; i++) {
Rectangle bounds = item.getTextBounds(i);
if (e.x >= bounds.x && e.x < bounds.x + bounds.width) {
IRegister reg = (IRegister) item.getData();
if (reg == null) {
table.setToolTipText(null);
} else {
String tooltip = reg.getTooltip();
String id = reg.getInfo().id;
String descr = reg.getInfo().description;
table.setToolTipText((descr == null ? id : descr) +
(tooltip != null && tooltip.length() > 0 ? ": " + tooltip : "")
);
}
return;
}
}
}
setToolTipText(null);
}
});
// oops, key listeners mess up everything else
/*
table.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.keyCode == '\r' && !regViewer.isCellEditorActive()
&& !regViewer.getSelection().isEmpty()) {
regViewer.editElement(
((IStructuredSelection) regViewer.getSelection()).getFirstElement(),
1);
e.doit = false;
}
}
});
*/
if (false) Display.getDefault().asyncExec(new Runnable() {
public void run() {
nameColumn.pack();
valColumn.pack();
}
});
return regViewer;
}
public synchronized void update() {
if (updateTask == null) {
updateTask = new Runnable() {
public void run() {
for (TableViewer v : regViewers) {
if (!v.getTable().isDisposed() && !v.isCellEditorActive())
v.refresh();
}
updateTask = null;
}
};
Display.getDefault().asyncExec(updateTask);
}
}
}