ui: scroll code horizontally to active sourcelocations
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QPushButton>
|
||||
#include <QScrollBar>
|
||||
#include <QTextBlock>
|
||||
@@ -372,6 +373,21 @@ Id QtCodeArea::getLocationIdOfFirstActiveScopeLocation(Id tokenId) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
Id QtCodeArea::getLocationIdOfFirstHighlightedLocation() const
|
||||
{
|
||||
for (const Annotation& annotation : m_annotations)
|
||||
{
|
||||
if ((annotation.locationType == LocationType::LOCATION_TOKEN && annotation.isActive) ||
|
||||
annotation.locationType == LocationType::LOCATION_FULLTEXT_SEARCH ||
|
||||
annotation.locationType == LocationType::LOCATION_ERROR)
|
||||
{
|
||||
return annotation.locationId;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t QtCodeArea::getActiveLocationCount() const
|
||||
{
|
||||
uint count = 0;
|
||||
@@ -475,6 +491,85 @@ void QtCodeArea::clearScreenMatches()
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeArea::ensureLocationIdVisible(Id locationId, int parentWidth, bool animated)
|
||||
{
|
||||
QScrollBar* scrollBar = horizontalScrollBar();
|
||||
if (!scrollBar || scrollBar->minimum() == scrollBar->maximum())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int oldValue = scrollBar->value();
|
||||
scrollBar->setValue(scrollBar->minimum());
|
||||
|
||||
const Annotation* annotationPtr = nullptr;
|
||||
for (const Annotation& annotation : m_annotations)
|
||||
{
|
||||
if (annotation.locationId == locationId)
|
||||
{
|
||||
annotationPtr = &annotation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!annotationPtr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<QRect> rects = getCursorRectsForAnnotation(*annotationPtr);
|
||||
QRect boundingRect;
|
||||
for (QRect rect : rects)
|
||||
{
|
||||
if (boundingRect.width())
|
||||
{
|
||||
boundingRect = boundingRect.united(rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
boundingRect = rect;
|
||||
}
|
||||
}
|
||||
|
||||
if (!boundingRect.width())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
boundingRect.adjust(-50, 0, 50, 0);
|
||||
|
||||
int totalWidth = sizeHint().width() - lineNumberAreaWidth();
|
||||
int visibleWidth = parentWidth - lineNumberAreaWidth();
|
||||
|
||||
int targetWidth = 0;
|
||||
if (boundingRect.right() > visibleWidth)
|
||||
{
|
||||
targetWidth = boundingRect.right() - visibleWidth;
|
||||
|
||||
if (targetWidth > boundingRect.left())
|
||||
{
|
||||
targetWidth = boundingRect.left();
|
||||
}
|
||||
}
|
||||
|
||||
const double percentTarget = double(targetWidth) / (totalWidth - visibleWidth);
|
||||
const int newValue = (scrollBar->maximum() - scrollBar->minimum()) * percentTarget + scrollBar->minimum();
|
||||
|
||||
if (animated && ApplicationSettings::getInstance()->getUseAnimations())
|
||||
{
|
||||
QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value");
|
||||
anim->setDuration(300);
|
||||
anim->setStartValue(oldValue);
|
||||
anim->setEndValue(newValue);
|
||||
anim->setEasingCurve(QEasingCurve::InOutQuad);
|
||||
anim->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollBar->setValue(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeArea::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QPlainTextEdit::resizeEvent(e);
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
|
||||
Id getLocationIdOfFirstActiveLocation(Id tokenId) const;
|
||||
Id getLocationIdOfFirstActiveScopeLocation(Id tokenId) const;
|
||||
Id getLocationIdOfFirstHighlightedLocation() const;
|
||||
|
||||
size_t getActiveLocationCount() const;
|
||||
|
||||
@@ -87,6 +88,8 @@ public:
|
||||
void findScreenMatches(const std::wstring& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches);
|
||||
void clearScreenMatches();
|
||||
|
||||
void ensureLocationIdVisible(Id locationId, int parentWidth, bool animated);
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent* event) Q_DECL_OVERRIDE;
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
|
||||
|
||||
@@ -101,20 +101,16 @@ QSize QtCodeField::sizeHint() const
|
||||
int width = 0;
|
||||
|
||||
QFontMetrics fm = fontMetrics();
|
||||
int maxTextSize = 0;
|
||||
for (QTextBlock block = document()->firstBlock(); block.isValid(); block = block.next())
|
||||
{
|
||||
QRectF rect = blockBoundingGeometry(block);
|
||||
height += rect.height();
|
||||
|
||||
{
|
||||
int blockWidth = fm.boundingRect(
|
||||
0, 0, 1000000, 1000000,
|
||||
Qt::AlignLeft | Qt::AlignTop | Qt::TextExpandTabs, block.text(), tabStopWidth()).width();
|
||||
int blockWidth = fm.boundingRect(
|
||||
0, 0, 1000000, 1000000,
|
||||
Qt::AlignLeft | Qt::AlignTop | Qt::TextExpandTabs, block.text(), tabStopWidth()).width();
|
||||
|
||||
width = std::max(blockWidth, width);
|
||||
maxTextSize = block.text().size();
|
||||
}
|
||||
width = std::max(blockWidth, width);
|
||||
}
|
||||
|
||||
return QSize(width + 1, height + 5);
|
||||
|
||||
@@ -228,6 +228,9 @@ bool QtCodeFileList::requestScroll(const FilePath& filePath, uint lineNumber, Id
|
||||
}
|
||||
|
||||
ensureWidgetVisibleAnimated(m_filesArea, snippet, lineRect, animated, target);
|
||||
|
||||
snippet->ensureLocationIdVisible(locationId, animated);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -197,6 +197,8 @@ bool QtCodeFileSingle::requestScroll(
|
||||
double percentB = endLineNumber ? double(endLineNumber - 1) / m_area->getEndLineNumber() : 0.0f;
|
||||
ensurePercentVisibleAnimated(percentA, percentB, animated, target);
|
||||
|
||||
m_area->ensureLocationIdVisible(locationId, width(), animated);
|
||||
|
||||
m_scrollRequested = true;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -142,6 +142,8 @@ int QtCodeSnippet::lineNumberDigits() const
|
||||
void QtCodeSnippet::updateCodeSnippet(const CodeSnippetParams& params)
|
||||
{
|
||||
m_codeArea->updateSourceLocations(params.locationFile);
|
||||
|
||||
ensureLocationIdVisible(m_codeArea->getLocationIdOfFirstHighlightedLocation(), false);
|
||||
}
|
||||
|
||||
void QtCodeSnippet::updateLineNumberAreaWidthForDigits(int digits)
|
||||
@@ -197,6 +199,11 @@ void QtCodeSnippet::findScreenMatches(const std::wstring& query, std::vector<std
|
||||
m_codeArea->findScreenMatches(query, screenMatches);
|
||||
}
|
||||
|
||||
void QtCodeSnippet::ensureLocationIdVisible(Id locationId, bool animated)
|
||||
{
|
||||
m_codeArea->ensureLocationIdVisible(locationId, width(), animated);
|
||||
}
|
||||
|
||||
void QtCodeSnippet::clickedTitle()
|
||||
{
|
||||
if (m_titleId > 0)
|
||||
|
||||
@@ -54,6 +54,8 @@ public:
|
||||
|
||||
void findScreenMatches(const std::wstring& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches);
|
||||
|
||||
void ensureLocationIdVisible(Id locationId, bool animated);
|
||||
|
||||
private slots:
|
||||
void clickedTitle();
|
||||
void clickedFooter();
|
||||
|
||||
Reference in New Issue
Block a user