/*******************************************************************************
* Copyright (c) 2006-2009 Wind River Systems, Inc. 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:
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
*******************************************************************************/
package org.eclipse.cdt.debug.ui.memory.traditional;
import java.math.BigInteger;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.MemoryByte;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
public class DataPane extends AbstractPane
{
public DataPane(Rendering parent)
{
super(parent);
}
protected String getCellText(MemoryByte bytes[])
{
return fRendering.getRadixText(bytes, fRendering.getRadix(), fRendering
.isTargetLittleEndian());
}
protected void editCell(BigInteger address, int subCellPosition,
char character)
{
try
{
MemoryByte bytes[] = fRendering.getBytes(fCaretAddress, fRendering
.getBytesPerColumn());
String cellText = getCellText(bytes);
if(cellText == null)
return;
StringBuffer cellTextBuffer = new StringBuffer(cellText);
cellTextBuffer.setCharAt(subCellPosition, character);
BigInteger value = new BigInteger(cellTextBuffer.toString().trim(),
fRendering.getNumericRadix(fRendering.getRadix()));
final boolean isSignedType = fRendering.getRadix() == Rendering.RADIX_DECIMAL_SIGNED;
final boolean isSigned = isSignedType
&& value.compareTo(BigInteger.valueOf(0)) < 0;
int bitCount = value.bitLength();
if(isSignedType)
bitCount++;
if(bitCount > fRendering.getBytesPerColumn() * 8)
return;
int byteLen = fRendering.getBytesPerColumn();
byte[] byteData = new byte[byteLen];
for(int i = 0; i < byteLen; i++)
{
int bits = 255;
if(isSignedType && i == byteLen - 1)
bits = 127;
byteData[i] = (byte) (value.and(BigInteger.valueOf(bits))
.intValue() & bits);
value = value.shiftRight(8);
}
if(isSigned)
byteData[byteLen - 1] |= 128;
if(!fRendering.isDisplayLittleEndian())
{
byte[] byteDataSwapped = new byte[byteData.length];
for(int i = 0; i < byteData.length; i++)
byteDataSwapped[i] = byteData[byteData.length - 1 - i];
byteData = byteDataSwapped;
}
if(byteData.length != bytes.length)
return;
TraditionalMemoryByte bytesToSet[] = new TraditionalMemoryByte[bytes.length];
for(int i = 0; i < byteData.length; i++)
{
bytesToSet[i] = new TraditionalMemoryByte(byteData[i]);
bytesToSet[i].setBigEndian(bytes[i].isBigEndian());
// for embedded, the user wants feedback that the change will be sent to the target,
// even if does not change the value. eventually, maybe we need another color to
// indicate change.
//if(bytes[i].getValue() != byteData[i])
{
bytesToSet[i].setEdited(true);
}
//else
{
// if(bytes[i] instanceof TraditionalMemoryByte)
// bytesToSet[i].setEdited(((TraditionalMemoryByte) bytes[i]).isEdited());
bytesToSet[i].setChanged(bytes[i].isChanged());
}
}
fRendering.getViewportCache().setEditedValue(address, bytesToSet);
advanceCursor();
redraw();
}
catch(Exception e)
{
// do nothing
}
}
protected int getCellWidth()
{
return getCellCharacterCount() * getCellCharacterWidth()
+ (fRendering.getCellPadding() * 2);
}
protected int getCellCharacterCount()
{
return fRendering.getRadixCharacterCount(fRendering.getRadix(),
fRendering.getBytesPerColumn());
}
public Point computeSize(int wHint, int hHint)
{
return new Point(fRendering.getColumnCount() * getCellWidth()
+ fRendering.getRenderSpacing(), 100);
}
private BigInteger getCellAddressAt(int x, int y) throws DebugException
{
BigInteger address = fRendering.getViewportStartAddress();
int col = x / getCellWidth();
int row = y / getCellHeight();
if(col >= fRendering.getColumnCount())
return null;
address = address.add(BigInteger.valueOf(row
* fRendering.getColumnCount() * fRendering.getAddressesPerColumn()));
address = address.add(BigInteger.valueOf(col
* fRendering.getAddressesPerColumn()));
return address;
}
protected Point getCellLocation(BigInteger cellAddress)
{
try
{
BigInteger address = fRendering.getViewportStartAddress();
int cellOffset = cellAddress.subtract(address).intValue();
cellOffset *= fRendering.getAddressableSize();
int row = cellOffset
/ (fRendering.getColumnCount() * fRendering.getBytesPerColumn());
cellOffset -= row * fRendering.getColumnCount()
* fRendering.getBytesPerColumn();
int col = cellOffset / fRendering.getBytesPerColumn();
int x = col * getCellWidth() + fRendering.getCellPadding();
int y = row * getCellHeight() + fRendering.getCellPadding();
return new Point(x, y);
}
catch(Exception e)
{
fRendering
.logError(
TraditionalRenderingMessages
.getString("TraditionalRendering.FAILURE_DETERMINE_CELL_LOCATION"), e); //$NON-NLS-1$
return null;
}
}
protected void positionCaret(int x, int y)
{
try
{
BigInteger cellAddress = getCellAddressAt(x, y);
if(cellAddress != null)
{
Point cellPosition = getCellLocation(cellAddress);
int offset = x - cellPosition.x;
int subCellCharacterPosition = offset / getCellCharacterWidth();
if(subCellCharacterPosition == this.getCellCharacterCount())
{
cellAddress = cellAddress.add(BigInteger.valueOf(fRendering
.getAddressesPerColumn()));
subCellCharacterPosition = 0;
cellPosition = getCellLocation(cellAddress);
}
fCaret.setLocation(cellPosition.x + subCellCharacterPosition
* getCellCharacterWidth(), cellPosition.y);
this.fCaretAddress = cellAddress;
this.fSubCellCaretPosition = subCellCharacterPosition;
setCaretAddress(fCaretAddress);
}
}
catch(Exception e)
{
fRendering
.logError(
TraditionalRenderingMessages
.getString("TraditionalRendering.FAILURE_POSITION_CURSOR"), e); //$NON-NLS-1$
}
}
protected BigInteger getViewportAddress(int col, int row)
throws DebugException
{
BigInteger address = fRendering.getViewportStartAddress();
address = address.add(BigInteger.valueOf((row
* fRendering.getColumnCount() + col)
* fRendering.getAddressesPerColumn()));
return address;
}
protected void paint(PaintEvent pe)
{
super.paint(pe);
// Allow subclasses to override this method to do their own painting
doPaintData(pe);
}
// Allow subclasses to override this method to do their own painting
protected void doPaintData(PaintEvent pe)
{
GC gc = pe.gc;
gc.setFont(fRendering.getFont());
int cellHeight = getCellHeight();
int cellWidth = getCellWidth();
int columns = fRendering.getColumnCount();
try
{
BigInteger start = fRendering.getViewportStartAddress();
for(int i = 0; i < this.getBounds().height / cellHeight; i++)
{
for(int col = 0; col < columns; col++)
{
if(isOdd(col))
gc.setForeground(fRendering.getTraditionalRendering().getColorText());
else
gc.setForeground(fRendering.getTraditionalRendering().getColorTextAlternate());
BigInteger cellAddress = start.add(BigInteger.valueOf((i
* fRendering.getColumnCount() + col)
* fRendering.getAddressesPerColumn()));
TraditionalMemoryByte bytes[] = fRendering.getBytes(cellAddress,
fRendering.getBytesPerColumn());
if(fRendering.getSelection().isSelected(cellAddress))
{
gc.setBackground(fRendering.getTraditionalRendering().getColorSelection());
gc.fillRectangle(cellWidth * col
+ fRendering.getCellPadding(), cellHeight * i,
cellWidth, cellHeight);
gc.setForeground(fRendering.getTraditionalRendering().getColorBackground());
}
else
{
gc.setBackground(fRendering.getTraditionalRendering().getColorBackground());
gc.fillRectangle(cellWidth * col
+ fRendering.getCellPadding(), cellHeight * i,
cellWidth, cellHeight);
// Allow subclasses to override this method to do their own coloring
applyCustomColor(gc, bytes, col);
}
gc.drawText(getCellText(bytes), cellWidth * col
+ fRendering.getCellPadding(), cellHeight * i
+ fRendering.getCellPadding());
BigInteger cellEndAddress = cellAddress.add(BigInteger
.valueOf(fRendering.getAddressesPerColumn()));
cellEndAddress = cellEndAddress.subtract(BigInteger
.valueOf(1));
if(fCaretEnabled)
{
if(cellAddress.compareTo(fCaretAddress) <= 0
&& cellEndAddress.compareTo(fCaretAddress) >= 0)
{
int x = cellWidth * col
+ fRendering.getCellPadding()
+ fSubCellCaretPosition
* this.getCellCharacterWidth();
int y = cellHeight * i
+ fRendering.getCellPadding();
fCaret.setLocation(x, y);
}
}
if(fRendering.isDebug())
gc.drawRectangle(cellWidth * col
+ fRendering.getCellPadding(), cellHeight * i
+ fRendering.getCellPadding(), cellWidth,
cellHeight);
}
}
}
catch(Exception e)
{
fRendering.logError(TraditionalRenderingMessages
.getString("TraditionalRendering.FAILURE_PAINT"), e); //$NON-NLS-1$
}
}
// Allow subclasses to override this method to do their own coloring
protected void applyCustomColor(GC gc, TraditionalMemoryByte bytes[], int col)
{
// TODO consider adding finer granularity?
boolean anyByteEditing = false;
for(int n = 0; n < bytes.length && !anyByteEditing; n++)
if(bytes[n] instanceof TraditionalMemoryByte)
if(((TraditionalMemoryByte) bytes[n]).isEdited())
anyByteEditing = true;
if(isOdd(col))
gc.setForeground(fRendering.getTraditionalRendering().getColorText());
else
gc.setForeground(fRendering.getTraditionalRendering().getColorTextAlternate());
gc.setBackground(fRendering.getTraditionalRendering().getColorBackground());
if(anyByteEditing)
{
gc.setForeground(fRendering.getTraditionalRendering().getColorEdit());
}
else
{
boolean isColored = false;
for(int i = 0; i < fRendering.getHistoryDepth() && !isColored; i++)
{
// TODO consider adding finer granularity?
for(int n = 0; n < bytes.length; n++)
{
if(bytes[n].isChanged(i))
{
if(i == 0)
gc.setForeground(fRendering.getTraditionalRendering().getColorsChanged()[i]);
else
gc.setBackground(fRendering.getTraditionalRendering().getColorsChanged()[i]);
isColored = true;
break;
}
}
}
}
}
}