/******************************************************************************* * 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 TextPane extends AbstractPane { public TextPane(Rendering parent) { super(parent); } protected int getCellCharacterCount() { return fRendering.getBytesPerColumn() / fRendering.getBytesPerCharacter(); } protected String getCellText(MemoryByte bytes[]) { return fRendering.formatText(bytes, fRendering .isTargetLittleEndian(), fRendering.getTextMode()); } 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); byte byteData[] = cellTextBuffer.toString().getBytes(fRendering.getCharacterSet(fRendering.getTextMode())); 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]); if(bytes[i].getValue() != byteData[i]) { bytesToSet[i].setEdited(true); } else { bytesToSet[i].setChanged(bytes[i].isChanged()); } } fRendering.getViewportCache().setEditedValue(address, bytesToSet); advanceCursor(); redraw(); } catch(Exception e) { // this is ok } } protected int getCellWidth() { GC gc = new GC(this); gc.setFont(fRendering.getFont()); int width = gc.getAdvanceWidth('F'); gc.dispose(); return fRendering.getBytesPerColumn() / fRendering.getBytesPerCharacter() * width; } public Point computeSize(int wHint, int hHint) { return new Point(fRendering.getColumnCount() * getCellWidth() + fRendering.getRenderSpacing(), 100); } 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() / fRendering .getBytesPerCharacter()); cellOffset -= row * fRendering.getColumnCount() * fRendering.getBytesPerColumn() / fRendering.getBytesPerCharacter(); int col = cellOffset / fRendering.getBytesPerColumn() / fRendering.getBytesPerCharacter(); 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; } } 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() / fRendering.getBytesPerCharacter())); address = address.add(BigInteger.valueOf(col * fRendering.getAddressesPerColumn())); return address; } 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 x2 = offset / getCellCharacterWidth(); if(x2 == this.getCellCharacterCount()) { cellAddress = cellAddress.add(BigInteger.valueOf(fRendering .getAddressesPerColumn())); x2 = 0; cellPosition = getCellLocation(cellAddress); } fCaret.setLocation(cellPosition.x + x2 * getCellCharacterWidth(), cellPosition.y); this.fCaretAddress = cellAddress; this.fSubCellCaretPosition = x2; 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() / fRendering.getBytesPerCharacter())); return address; } protected void paint(PaintEvent pe) { super.paint(pe); GC gc = pe.gc; gc.setFont(fRendering.getFont()); int cellHeight = getCellHeight(); int cellWidth = getCellWidth(); final int columns = fRendering.getColumnCount(); final boolean isLittleEndian = fRendering.isTargetLittleEndian(); gc.setForeground(fRendering.getTraditionalRendering().getColorBackground()); gc.fillRectangle(columns * cellWidth, 0, this.getBounds().width, this .getBounds().height); 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 * columns + col) * fRendering.getAddressesPerColumn())); TraditionalMemoryByte bytes[] = fRendering.getBytes(cellAddress, fRendering.getBytesPerColumn()); if(fRendering.getSelection().isSelected(cellAddress)) { gc.setBackground(fRendering.getTraditionalRendering().getColorSelection()); gc.fillRectangle(cellWidth * col, cellHeight * i, cellWidth, cellHeight); gc.setForeground(fRendering.getTraditionalRendering().getColorBackground()); } else { gc.setBackground(fRendering.getTraditionalRendering().getColorBackground()); gc.fillRectangle(cellWidth * col, cellHeight * i, cellWidth, cellHeight); applyCustomColor(gc, bytes, col); } gc.drawText(fRendering.formatText(bytes, isLittleEndian, fRendering.getTextMode()), cellWidth * col, cellHeight * i + fRendering.getCellPadding()); if(fRendering.isDebug()) gc.drawRectangle(cellWidth * col, 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; } } } } } }