Added primary highlighting border for highlighted ranges that span multiple lines

This commit is contained in:
Nav
2023-08-26 02:52:20 +01:00
parent a5d531b1a7
commit 362bc22262
3 changed files with 114 additions and 9 deletions

View File

@@ -146,6 +146,73 @@ namespace Widgets
return output;
}
const ByteItem* HexViewerItemIndex::leftMostByteItemWithinRange(int yStart, int yEnd) const {
const ByteItem* leftMostByteItem = nullptr;
auto leftMostByteItemXPos = 0;
for (const auto* item : this->items(yStart, yEnd)) {
const auto itemPos = item->position();
/*
* Remember, the HexViewerItemIndex::items() function can return items that are outside the given range,
* depending on the grid size of the Y-axis index.
*
* We need to ensure that we exclude those items here.
*/
if (itemPos.y() < yStart) {
continue;
}
if (itemPos.y() > yEnd) {
break;
}
const auto* byteItem = dynamic_cast<const ByteItem*>(item);
if (byteItem == nullptr) {
continue;
}
if (leftMostByteItem == nullptr || itemPos.x() < leftMostByteItemXPos) {
leftMostByteItem = byteItem;
leftMostByteItemXPos = itemPos.x();
}
}
return leftMostByteItem;
}
const ByteItem* HexViewerItemIndex::rightMostByteItemWithinRange(int yStart, int yEnd) const {
const ByteItem* rightMostByteItem = nullptr;
auto rightMostByteItemXPos = 0;
for (const auto* item : this->items(yStart, yEnd)) {
const auto itemPos = item->position();
if (itemPos.y() < yStart) {
continue;
}
if (itemPos.y() > yEnd) {
break;
}
const auto* byteItem = dynamic_cast<const ByteItem*>(item);
if (byteItem == nullptr) {
continue;
}
const auto itemXPos = item->position().x() + item->size().width();
if (rightMostByteItem == nullptr || itemXPos > rightMostByteItemXPos) {
rightMostByteItem = byteItem;
rightMostByteItemXPos = itemXPos;
}
}
return rightMostByteItem;
}
void HexViewerItemIndex::refreshFlattenedItems() {
this->flattenedItems = this->topLevelGroupItem->flattenedItems();
}

View File

@@ -75,6 +75,24 @@ namespace Widgets
*/
std::vector<ByteItem*> intersectingByteItems(const QRectF& rect) const;
/**
* Returns the left-most (smallest position on the X-axis) byte item, within a Y-axis range.
*
* @param yStart
* @param yEnd
* @return
*/
const ByteItem* leftMostByteItemWithinRange(int yStart, int yEnd) const;
/**
* Returns the right-most (largest position on the X-axis) byte item, within a Y-axis range.
*
* @param yStart
* @param yEnd
* @return
*/
const ByteItem* rightMostByteItemWithinRange(int yStart, int yEnd) const;
void refreshFlattenedItems();
void refreshIndex();

View File

@@ -61,7 +61,7 @@ namespace Widgets
break;
}
if (startItemY != endItemY || endItemY < viewportYStart) {
if (endItemY < viewportYStart) {
continue;
}
@@ -242,14 +242,34 @@ namespace Widgets
const auto endItemSize = endItem->size();
auto painterPath = QPainterPath();
painterPath.addRoundedRect(
startItemPos.x() - padding,
startItemPos.y() - padding,
(endItemPos.x() + endItemSize.width()) - startItemPos.x() + (padding * 2),
(endItemPos.y() + endItemSize.height()) - startItemPos.y() + (padding * 2),
rectRadius,
rectRadius
);
if (startItemPos.y() != endItemPos.y()) {
// The highlighted range spans more than one line - draw the border around all lines containing the range
const auto leftMostItem = this->itemIndex.leftMostByteItemWithinRange(startItemPos.y(), endItemPos.y());
const auto leftMostItemPos = leftMostItem->position();
const auto* rightMostItem = this->itemIndex.rightMostByteItemWithinRange(startItemPos.y(), endItemPos.y());
const auto rightMostItemPos = rightMostItem->position();
painterPath.addRoundedRect(
leftMostItemPos.x() - padding,
startItemPos.y() - padding,
(rightMostItemPos.x() + rightMostItem->size().width()) - leftMostItemPos.x() + (padding * 2),
(endItemPos.y() + endItemSize.height()) - startItemPos.y() + (padding * 2),
rectRadius,
rectRadius
);
} else {
painterPath.addRoundedRect(
startItemPos.x() - padding,
startItemPos.y() - padding,
(endItemPos.x() + endItemSize.width()) - startItemPos.x() + (padding * 2),
(endItemPos.y() + endItemSize.height()) - startItemPos.y() + (padding * 2),
rectRadius,
rectRadius
);
}
painter->setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
painter->setPen(QPen(QColor(0x78, 0x78, 0x78), 2));