From 5d6bef7eb5d47b620bbbbfc49c44c6eb07bf0720 Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Sun, 13 Mar 2016 15:28:52 -0400 Subject: [PATCH] Bug 489505 - Add hovering support to the traditional memory render Change-Id: I06d7264835a8199398aad1a0215d775caa29e079 --- .../ui/memory/traditional/AbstractPane.java | 16 +- .../debug/ui/memory/traditional/DataPane.java | 175 +++++++++++++++++- 2 files changed, 186 insertions(+), 5 deletions(-) diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AbstractPane.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AbstractPane.java index fbb321fa644..62bf19282ce 100755 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AbstractPane.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AbstractPane.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2015 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2016 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 @@ -8,6 +8,7 @@ * Contributors: * Ted R Williams (Wind River Systems, Inc.) - initial implementation * Teodor Madan (Freescale) - Fix PageDn/PageUp + * Alvaro Sanchez-leon (Ericsson) - Add hovering support to the traditional memory render (Bug 489505) *******************************************************************************/ package org.eclipse.cdt.debug.ui.memory.traditional; @@ -26,6 +27,7 @@ import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Font; @@ -323,6 +325,8 @@ public abstract class AbstractPane extends Canvas this.addMouseMoveListener(createMouseMoveListener()); + this.addMouseTrackListener(createMouseHoverListener()); + this.addKeyListener(createKeyListener()); this.addFocusListener(createFocusListener()); @@ -336,6 +340,16 @@ public abstract class AbstractPane extends Canvas return new AbstractPaneMouseMoveListener(); } + /** + * @since 1.4 + */ + protected MouseTrackAdapter createMouseHoverListener() { + // This method provides an empty implementation of MouseTrackAdapter + // The non empty implementation instance is left to the subclasses that do support Hovering + return new MouseTrackAdapter() { + }; + } + protected FocusListener createFocusListener() { return new AbstractPaneFocusListener(); } diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/DataPane.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/DataPane.java index 8bc4e12eaee..444496514e1 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/DataPane.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/DataPane.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006-2013 Wind River Systems, Inc. and others. + * Copyright (c) 2006-2016 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 @@ -7,6 +7,7 @@ * * Contributors: * Ted R Williams (Wind River Systems, Inc.) - initial implementation + * Alvaro Sanchez-leon (Ericsson) - Add hovering support to the traditional memory render (Bug 489505) *******************************************************************************/ package org.eclipse.cdt.debug.ui.memory.traditional; @@ -15,12 +16,23 @@ import java.math.BigInteger; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; public class DataPane extends AbstractPane { + private Shell fToolTipShell; public DataPane(Rendering parent) { super(parent); @@ -128,6 +140,17 @@ public class DataPane extends AbstractPane + (fRendering.getCellPadding() * 2); } + /** + * @return The width length in pixels needed to draw the characters of an addressable unit + */ + private int getAddressableWidth() { + // derive the number of characters per addressable size e.g. 2 * NumOfOctets + int charsPerOctet = 2; + int addressCharacterCount = fRendering.getAddressableSize() * charsPerOctet; + // derive width by multiplying by the size of a character + return addressCharacterCount * getCellCharacterWidth(); + } + @Override protected int getCellCharacterCount() { @@ -160,6 +183,43 @@ public class DataPane extends AbstractPane return address; } + + /** + * @return The address associated to the hovering location + */ + private BigInteger getAddressAt(int x, int y) { + // Resolve the first address in the cell + BigInteger cellBaseAddress; + try { + cellBaseAddress = getCellAddressAt(x, y); + } catch (DebugException e) { + fRendering.logError(TraditionalRenderingMessages.getString("TraditionalRendering.FAILURE_DETERMINE_ADDRESS_LOCATION"), e); //$NON-NLS-1$ + return null; + } + + if (cellBaseAddress == null) { + return null; + } + + // Get the start location of the cell + Point cellPosition = getCellLocation(cellBaseAddress); + if (cellPosition == null) { + return null; + } + + // Resolve the horizontal offset between hover location and + // the start of the cell + int offset = x - cellPosition.x; + if (offset < 0) { + return null; + } + + // Resolve the number of addresses between hover location and first address in the cell + int addressableOffset = offset / getAddressableWidth(); + assert addressableOffset <= getAddressableOctetsPerColumn(); + + return cellBaseAddress.add(BigInteger.valueOf(addressableOffset)); + } @Override protected Point getCellLocation(BigInteger cellAddress) @@ -167,7 +227,8 @@ public class DataPane extends AbstractPane try { BigInteger address = fRendering.getViewportStartAddress(); - + + // cell offset from base address in octets int cellOffset = cellAddress.subtract(address).intValue(); cellOffset *= fRendering.getAddressableSize(); @@ -264,7 +325,7 @@ public class DataPane extends AbstractPane try { - BigInteger start = fRendering.getViewportStartAddress(); + BigInteger startAddress = fRendering.getViewportStartAddress(); for(int i = 0; i < this.getBounds().height / cellHeight; i++) { @@ -277,7 +338,7 @@ public class DataPane extends AbstractPane else gc.setForeground(fRendering.getTraditionalRendering().getColorTextAlternate()); - BigInteger cellAddress = start.add(BigInteger.valueOf((i + BigInteger cellAddress = startAddress.add(BigInteger.valueOf((i * fRendering.getColumnCount() + col) * fRendering.getAddressesPerColumn())); @@ -400,5 +461,111 @@ public class DataPane extends AbstractPane } } } + + @Override + public void dispose() { + super.dispose(); + if (fToolTipShell != null) { + fToolTipShell.dispose(); + fToolTipShell = null; + } + } + @Override + protected MouseTrackAdapter createMouseHoverListener() { + return new DataPaneMouseHoverListener(); + } + + private int getAddressableOctetsPerColumn() { + // Prevent division by zero + int addressableSize = (fRendering.getAddressableSize() > 0) ? fRendering.getAddressableSize() : 1; + return fRendering.getBytesPerColumn() / addressableSize; + } + + + class DataPaneMouseHoverListener extends MouseTrackAdapter { + private BigInteger fTooltipAddress = null; + private final Label fLabelContent; + + DataPaneMouseHoverListener() { + fLabelContent = createToolTip(); + } + + @Override + public void mouseExit(MouseEvent e) { + if (fToolTipShell != null && !fToolTipShell.isDisposed()) { + fToolTipShell.setVisible(false); + fTooltipAddress = null; + } + } + + @Override + public void mouseHover(MouseEvent e) { + if (e.widget == null || !(e.widget instanceof Control) || fToolTipShell == null || fToolTipShell.isDisposed()) { + return; + } + + Control control = (Control) e.widget; + + // Resolve the address associated to the hovering location + BigInteger address = getAddressAt(e.x, e.y); + + if (address == null) { + // Invalid Address at location + return; + } + + // Display tooltip if there is a change in hover + Point hoverPoint = control.toDisplay(new Point(e.x, e.y)); + if (!fToolTipShell.isVisible() || !address.equals(fTooltipAddress)) { + diplayToolTip(hoverPoint, address); + } else { + // Still pointing to the same cell + return; + } + + // Keep Track of the latest visited address + fTooltipAddress = address; + } + + private void diplayToolTip(Point hoverPoint, BigInteger subAddress) { + // Show the current hovering address as the first line in the tooltip + StringBuilder sb = new StringBuilder("0x").append(subAddress.toString(16)); + + fLabelContent.setText(sb.toString()); + + // Setting location of the tool tip + Rectangle shellBounds = fToolTipShell.getBounds(); + shellBounds.x = hoverPoint.x; + shellBounds.y = hoverPoint.y + getCellHeight(); + + fToolTipShell.setBounds(shellBounds); + fToolTipShell.pack(); + + fToolTipShell.setVisible(true); + } + + private Label createToolTip() { + if (fToolTipShell != null) { + fToolTipShell.dispose(); + } + + fToolTipShell = new Shell(getShell(), SWT.ON_TOP | SWT.RESIZE); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + gridLayout.marginWidth = 2; + gridLayout.marginHeight = 0; + fToolTipShell.setLayout(gridLayout); + fToolTipShell.setBackground(fToolTipShell.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + return createToolTipContent(fToolTipShell); + } + + private Label createToolTipContent(Composite composite) { + Label toolTipContent = new Label(composite, SWT.NONE); + toolTipContent.setForeground(composite.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + toolTipContent.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + toolTipContent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER)); + return toolTipContent; + } + } }