Added primary highlighting border for highlighted ranges that span multiple lines
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user