diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF
index f42d50dbd38..f21cbf7eb1b 100644
--- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF
+++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.debug.ui.memory.traditional;singleton:=true
-Bundle-Version: 1.4.0.qualifier
+Bundle-Version: 1.5.0.qualifier
Bundle-Localization: plugin
Require-Bundle: org.eclipse.debug.core,
org.eclipse.debug.ui,
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/pom.xml b/memory/org.eclipse.cdt.debug.ui.memory.traditional/pom.xml
index c0d5618df0a..7d9ff4916ab 100644
--- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/pom.xml
+++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/pom.xml
@@ -11,7 +11,7 @@
../../pom.xml
- 1.4.0-SNAPSHOT
+ 1.5.0-SNAPSHOT
org.eclipse.cdt.debug.ui.memory.traditional
eclipse-plugin
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java
index 820a90a9ce5..71c3ec2395d 100755
--- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java
+++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java
@@ -163,11 +163,22 @@ public class Rendering extends Composite implements IDebugEventSetListener
/**
* Maintains the subset of items visible in the current view address range.
* This information is refreshed when the associated Panes are about to be redrawn
+ * Note: Only the start address of each entry is included i.e. one entry per information item
* @since 1.4
*/
protected final Map> fMapStartAddrToInfoItems = Collections
.synchronizedMap(new HashMap>());
+ /**
+ * Maps any address within a memory information range to a corresponding list of information items
+ * sharing that address.
+ * This is useful to e.g. produce a tooltip while hovering over any memory location of a memory information range
+ *
+ * @since 1.5
+ */
+ protected final Map> fMapAddrToInfoItems = Collections
+ .synchronizedMap(new HashMap>());
+
public Rendering(Composite parent, TraditionalRendering renderingParent)
{
super(parent, SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.H_SCROLL
@@ -1198,6 +1209,7 @@ public class Rendering extends Composite implements IDebugEventSetListener
}
fMapStartAddrToInfoItems.clear();
+ fMapAddrToInfoItems.clear();
super.dispose();
}
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/RenderingAddressInfo.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/RenderingAddressInfo.java
index 95405a0a51d..f449221b7d2 100644
--- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/RenderingAddressInfo.java
+++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/RenderingAddressInfo.java
@@ -132,6 +132,7 @@ public class RenderingAddressInfo extends Rendering
fSelectedContext = null;
fMapStartAddrToInfoItems.clear();
+ fMapAddrToInfoItems.clear();
fAddressInfoTypeStatusMap.clear();
fAddressInfoItems = null;
@@ -261,6 +262,7 @@ public class RenderingAddressInfo extends Rendering
// The selection has changed, so our Address information may no longer be valid
fAddressInfoItems = addressInfoItems;
fMapStartAddrToInfoItems.clear();
+ fMapAddrToInfoItems.clear();
if (fBinaryPane.isVisible()) {
redrawPanes();
@@ -334,6 +336,7 @@ public class RenderingAddressInfo extends Rendering
IMemoryBlockAddressInfoItem[] items = fAddressInfoItems;
if (items == null || !fParent.isShowCrossRefInfoGlobalPref()) {
fMapStartAddrToInfoItems.clear();
+ fMapAddrToInfoItems.clear();
return fMapStartAddrToInfoItems;
}
@@ -343,6 +346,7 @@ public class RenderingAddressInfo extends Rendering
// unless the cell size matches the addressable size of the target system
if (fParent.getAddressableSize() != getBytesPerColumn()) {
fMapStartAddrToInfoItems.clear();
+ fMapAddrToInfoItems.clear();
return fMapStartAddrToInfoItems;
}
}
@@ -357,6 +361,7 @@ public class RenderingAddressInfo extends Rendering
synchronized (fMapStartAddrToInfoItems) {
// Refreshing the Address to InfoItem data map
fMapStartAddrToInfoItems.clear();
+ fMapAddrToInfoItems.clear();
BigInteger startAddress = getViewportStartAddress();
// Get the endAddress considering a page that uses single height,
// Note: The UI may some times present rows with double height even if the user does not see items
@@ -395,6 +400,29 @@ public class RenderingAddressInfo extends Rendering
if (itemStartIsInRange || itemEndIsInRange || itemSpansOverVisibleRange) {
fMapStartAddrToInfoItems.put(item.getAddress(), allValuesMap.get(item.getAddress()));
filteredValuesMap.put(item.getAddress(), allValuesMap.get(item.getAddress()));
+ // Add information items for each address within the range
+ // But establish the limits to only add information to visible items (i.e. limiting the processing)
+ BigInteger firstItemVisibleAddress = itemStartIsInRange ? item.getAddress() : startAddress;
+ BigInteger lastItemVisibleAddress = itemEndIsInRange ? item.getAddress().add(item.getRangeInAddressableUnits().subtract(BigInteger.ONE)) : endAddress;
+
+ for (BigInteger candidateAddress=firstItemVisibleAddress; candidateAddress.compareTo(lastItemVisibleAddress) <=0; candidateAddress = candidateAddress.add(BigInteger.ONE)) {
+ List allItemsAtBase = allValuesMap.get(item.getAddress());
+ List newInfoItems = filterToItemsValidForAddress(allItemsAtBase, item.getAddress(), candidateAddress);
+
+ // Add new valid items to the map, associating it to candidate address
+ List existingItems = fMapAddrToInfoItems.get(candidateAddress);
+ if (existingItems == null) {
+ // Brand new list of items
+ fMapAddrToInfoItems.put(candidateAddress, newInfoItems);
+ } else {
+ // Appending new items to the existing list
+ for (IMemoryBlockAddressInfoItem newItem : newInfoItems) {
+ if (!existingItems.contains(newItem)) {
+ existingItems.add(newItem);
+ }
+ }
+ }
+ }
}
}
}
@@ -402,10 +430,56 @@ public class RenderingAddressInfo extends Rendering
return filteredValuesMap;
}
+ /**
+ * @param allBaseItems - Set of items sharing the same starting address
+ * @param baseAddress - The starting address
+ * @param candidateAddress - An address higher than base address
+ * @return - The set of items that are still overlapping at the incremented address
+ */
+ private List filterToItemsValidForAddress(List allBaseItems,
+ BigInteger baseAddress, BigInteger candidateAddress) {
+
+ List items = new ArrayList<>();
+
+ // Keep info items applicable for the given address
+ BigInteger range = candidateAddress.subtract(baseAddress);
+
+ // sanity check - should not happen
+ if (range.compareTo(BigInteger.ZERO) < 0) {
+ // return empty list
+ return items;
+ }
+ else if (range.compareTo(BigInteger.ZERO) == 0) {
+ // Since all items share the same start address,
+ // all items must be valid for a single address span
+ return allBaseItems;
+ }
+
+ // Aggregate elements having a length equal or higher than the span between base address and current address
+ for (IMemoryBlockAddressInfoItem item : allBaseItems) {
+ if (item.getRangeInAddressableUnits().compareTo(range) >=0 ) {
+ items.add(item);
+ }
+ }
+
+ return items;
+ }
+
@Override
String buildAddressInfoString(BigInteger cellAddress, String separator, boolean addTypeHeaders) {
- List infoItems = fMapStartAddrToInfoItems.get(cellAddress);
+ List infoItems;
+ if (addTypeHeaders) {
+ // Tooltip information
+ infoItems = fMapAddrToInfoItems.get(cellAddress);
+ } else {
+ // element information
+ infoItems = fMapStartAddrToInfoItems.get(cellAddress);
+ }
+ return buildAddressInfoString(cellAddress, separator, addTypeHeaders, infoItems);
+ }
+
+ private String buildAddressInfoString(BigInteger cellAddress, String separator, boolean addTypeHeaders, List infoItems) {
if (infoItems == null || infoItems.size() < 1) {
// No information to display
return "";
@@ -455,7 +529,7 @@ public class RenderingAddressInfo extends Rendering
@Override
boolean hasAddressInfo(BigInteger cellAddress) {
- return fMapStartAddrToInfoItems.keySet().contains(cellAddress);
+ return fMapAddrToInfoItems.keySet().contains(cellAddress);
}
/**