ui: scroll to code snippet containing clicked edge
This change scrolls animated to the snippet representing the clicked edge instead of showing only this code snippet.
This commit is contained in:
@@ -148,6 +148,21 @@ void QtCodeArea::updateContent()
|
||||
annotateText();
|
||||
}
|
||||
|
||||
bool QtCodeArea::isActive() const
|
||||
{
|
||||
const std::vector<Id>& ids = m_fileWidget->getActiveTokenIds();
|
||||
|
||||
for (const Annotation& annotation: m_annotations)
|
||||
{
|
||||
if (std::find(ids.begin(), ids.end(), annotation.tokenId) != ids.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void QtCodeArea::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QPlainTextEdit::resizeEvent(e);
|
||||
@@ -167,7 +182,6 @@ void QtCodeArea::showEvent(QShowEvent* event)
|
||||
void QtCodeArea::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QPainter painter(viewport());
|
||||
// painter.fillRect(rect(), Qt::white);
|
||||
|
||||
QTextBlock block = firstVisibleBlock();
|
||||
int top = blockBoundingGeometry(block).translated(contentOffset()).top();
|
||||
@@ -177,7 +191,7 @@ void QtCodeArea::paintEvent(QPaintEvent* event)
|
||||
|
||||
for (const ScopeAnnotation& scope : m_scopeAnnotations)
|
||||
{
|
||||
if (scope.isFocused)
|
||||
if (scope.isFocused || scope.startLine == scope.endLine)
|
||||
{
|
||||
qColor = QColor("#90E4EEF2");
|
||||
}
|
||||
@@ -410,7 +424,7 @@ void QtCodeArea::annotateText()
|
||||
selection.cursor.setPosition(annotation.end, QTextCursor::KeepAnchor);
|
||||
scopeAnnotation.endLine = selection.cursor.blockNumber();
|
||||
|
||||
if (annotation.isScope)
|
||||
if (annotation.isScope || (isActive && ids.size() == 1))
|
||||
{
|
||||
if (isActive || isFocused)
|
||||
{
|
||||
@@ -422,7 +436,8 @@ void QtCodeArea::annotateText()
|
||||
scopeAnnotations.push_back(scopeAnnotation);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (!annotation.isScope || (isActive && ids.size() == 1))
|
||||
{
|
||||
extraSelections.append(selection);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ public:
|
||||
|
||||
void updateContent();
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
virtual void showEvent(QShowEvent* event);
|
||||
|
||||
@@ -143,6 +143,19 @@ void QtCodeFile::addCodeSnippet(
|
||||
clickedSnippetButton();
|
||||
}
|
||||
|
||||
QWidget* QtCodeFile::findFirstActiveSnippet() const
|
||||
{
|
||||
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
|
||||
{
|
||||
if (snippet->isActive())
|
||||
{
|
||||
return snippet.get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void QtCodeFile::updateContent()
|
||||
{
|
||||
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
|
||||
|
||||
@@ -37,12 +37,16 @@ public:
|
||||
std::shared_ptr<TokenLocationFile> locationFile
|
||||
);
|
||||
|
||||
QWidget* findFirstActiveSnippet() const;
|
||||
|
||||
void updateContent();
|
||||
|
||||
public slots:
|
||||
void clickedSnippetButton();
|
||||
|
||||
private slots:
|
||||
void clickedTitle();
|
||||
void clickedMinimizeButton();
|
||||
void clickedSnippetButton();
|
||||
void clickedMaximizeButton();
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "qt/element/QtCodeFileList.h"
|
||||
|
||||
#include <QPropertyAnimation>
|
||||
#include <QScrollBar>
|
||||
#include <QVariant>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "utility/file/FileSystem.h"
|
||||
@@ -23,6 +25,8 @@ QtCodeFileList::QtCodeFileList(QWidget* parent)
|
||||
|
||||
setWidgetResizable(true);
|
||||
setWidget(m_frame.get());
|
||||
|
||||
connect(this, SIGNAL(shouldScrollToSnippet(QWidget*)), this, SLOT(scrollToSnippet(QWidget*)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
QtCodeFileList::~QtCodeFileList()
|
||||
@@ -83,7 +87,6 @@ const std::vector<Id>& QtCodeFileList::getActiveTokenIds() const
|
||||
void QtCodeFileList::setActiveTokenIds(const std::vector<Id>& activeTokenIds)
|
||||
{
|
||||
m_activeTokenIds = activeTokenIds;
|
||||
updateFiles();
|
||||
}
|
||||
|
||||
const std::vector<std::string>& QtCodeFileList::getErrorMessages() const
|
||||
@@ -94,14 +97,26 @@ const std::vector<std::string>& QtCodeFileList::getErrorMessages() const
|
||||
void QtCodeFileList::setErrorMessages(const std::vector<std::string>& errorMessages)
|
||||
{
|
||||
m_errorMessages = errorMessages;
|
||||
updateFiles();
|
||||
}
|
||||
|
||||
void QtCodeFileList::updateFiles()
|
||||
void QtCodeFileList::scrollToFirstActiveSnippet()
|
||||
{
|
||||
updateFiles();
|
||||
|
||||
QWidget* widget = nullptr;
|
||||
for (std::shared_ptr<QtCodeFile> file: m_files)
|
||||
{
|
||||
file->updateContent();
|
||||
widget = file->findFirstActiveSnippet();
|
||||
if (widget)
|
||||
{
|
||||
if (!widget->isVisible())
|
||||
{
|
||||
file->clickedSnippetButton();
|
||||
}
|
||||
|
||||
emit shouldScrollToSnippet(widget);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,3 +131,83 @@ void QtCodeFileList::defocusToken()
|
||||
m_focusedTokenId = 0;
|
||||
updateFiles();
|
||||
}
|
||||
|
||||
void QtCodeFileList::scrollToSnippet(QWidget* widget)
|
||||
{
|
||||
this->ensureWidgetVisibleAnimated(widget);
|
||||
}
|
||||
|
||||
void QtCodeFileList::updateFiles()
|
||||
{
|
||||
for (std::shared_ptr<QtCodeFile> file: m_files)
|
||||
{
|
||||
file->updateContent();
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeFileList::ensureWidgetVisibleAnimated(QWidget *childWidget, int xmargin, int ymargin)
|
||||
{
|
||||
if (!widget()->isAncestorOf(childWidget))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect();
|
||||
const QRect defaultMicroFocus = childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect();
|
||||
QRect focusRect = (microFocus != defaultMicroFocus)
|
||||
? QRect(childWidget->mapTo(widget(), microFocus.topLeft()), microFocus.size())
|
||||
: QRect(childWidget->mapTo(widget(), QPoint(0, 0)), childWidget->size());
|
||||
const QRect visibleRect(-widget()->pos(), viewport()->size());
|
||||
|
||||
if (visibleRect.contains(focusRect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
focusRect.adjust(-xmargin, -ymargin, xmargin, ymargin);
|
||||
|
||||
QScrollBar* scrollBar = nullptr;
|
||||
int value = 0;
|
||||
|
||||
if (focusRect.width() > visibleRect.width())
|
||||
{
|
||||
scrollBar = horizontalScrollBar();
|
||||
value = focusRect.center().x() - viewport()->width() / 2;
|
||||
}
|
||||
else if (focusRect.right() > visibleRect.right())
|
||||
{
|
||||
scrollBar = horizontalScrollBar();
|
||||
value = focusRect.right() - viewport()->width();
|
||||
}
|
||||
else if (focusRect.left() < visibleRect.left())
|
||||
{
|
||||
scrollBar = horizontalScrollBar();
|
||||
value = focusRect.left();
|
||||
}
|
||||
|
||||
if (focusRect.height() > visibleRect.height())
|
||||
{
|
||||
scrollBar = verticalScrollBar();
|
||||
value = focusRect.center().y() - viewport()->height() / 2;
|
||||
}
|
||||
else if (focusRect.bottom() > visibleRect.bottom())
|
||||
{
|
||||
scrollBar = verticalScrollBar();
|
||||
value = focusRect.bottom() - viewport()->height();
|
||||
}
|
||||
else if (focusRect.top() < visibleRect.top())
|
||||
{
|
||||
scrollBar = verticalScrollBar();
|
||||
value = focusRect.top();
|
||||
}
|
||||
|
||||
if (scrollBar)
|
||||
{
|
||||
QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value");
|
||||
anim->setDuration(std::abs(scrollBar->value() - value));
|
||||
anim->setStartValue(scrollBar->value());
|
||||
anim->setEndValue(value);
|
||||
anim->setEasingCurve(QEasingCurve::OutQuad);
|
||||
anim->start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ class QtCodeFileList
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void shouldScrollToSnippet(QWidget* widget);
|
||||
|
||||
public:
|
||||
QtCodeFileList(QWidget* parent = 0);
|
||||
virtual ~QtCodeFileList();
|
||||
@@ -40,12 +43,19 @@ public:
|
||||
const std::vector<std::string>& getErrorMessages() const;
|
||||
void setErrorMessages(const std::vector<std::string>& errorMessages);
|
||||
|
||||
void scrollToFirstActiveSnippet();
|
||||
|
||||
void focusToken(Id tokenId);
|
||||
void defocusToken();
|
||||
|
||||
private slots:
|
||||
void scrollToSnippet(QWidget* widget);
|
||||
|
||||
private:
|
||||
void updateFiles();
|
||||
|
||||
void ensureWidgetVisibleAnimated(QWidget *childWidget, int xmargin = 50, int ymargin = 50);
|
||||
|
||||
std::shared_ptr<QFrame> m_frame;
|
||||
std::vector<std::shared_ptr<QtCodeFile>> m_files;
|
||||
|
||||
|
||||
@@ -71,6 +71,11 @@ void QtCodeSnippet::updateContent()
|
||||
updateDots();
|
||||
}
|
||||
|
||||
bool QtCodeSnippet::isActive() const
|
||||
{
|
||||
return m_codeArea->isActive();
|
||||
}
|
||||
|
||||
void QtCodeSnippet::updateDots()
|
||||
{
|
||||
if (!m_dots)
|
||||
|
||||
@@ -34,6 +34,8 @@ public:
|
||||
void updateLineNumberAreaWidthForDigits(int digits);
|
||||
void updateContent();
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
private:
|
||||
void updateDots();
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout)
|
||||
, m_refreshViewFunctor(std::bind(&QtCodeView::doRefreshView, this))
|
||||
, m_showCodeSnippetsFunctor(std::bind(&QtCodeView::doShowCodeSnippets, this, std::placeholders::_1))
|
||||
, m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1))
|
||||
, m_doScrollToFirstActiveSnippetFunctor(std::bind(&QtCodeView::doScrollToFirstActiveSnippet, this))
|
||||
, m_focusTokenFunctor(std::bind(&QtCodeView::doFocusToken, this, std::placeholders::_1))
|
||||
, m_defocusTokenFunctor(std::bind(&QtCodeView::doDefocusToken, this))
|
||||
{
|
||||
@@ -56,6 +57,21 @@ void QtCodeView::showCodeFile(const CodeSnippetParams& params)
|
||||
m_showCodeFileFunctor(params);
|
||||
}
|
||||
|
||||
void QtCodeView::scrollToFirstActiveSnippet()
|
||||
{
|
||||
m_doScrollToFirstActiveSnippetFunctor();
|
||||
}
|
||||
|
||||
void QtCodeView::focusToken(const Id tokenId)
|
||||
{
|
||||
m_focusTokenFunctor(tokenId);
|
||||
}
|
||||
|
||||
void QtCodeView::defocusToken()
|
||||
{
|
||||
m_defocusTokenFunctor();
|
||||
}
|
||||
|
||||
void QtCodeView::doRefreshView()
|
||||
{
|
||||
setStyleSheet(m_widget);
|
||||
@@ -79,14 +95,10 @@ void QtCodeView::doShowCodeFile(const CodeSnippetParams& params)
|
||||
m_widget->addCodeSnippet(1, params.title, params.code, params.locationFile);
|
||||
}
|
||||
|
||||
void QtCodeView::focusToken(const Id tokenId)
|
||||
void QtCodeView::doScrollToFirstActiveSnippet()
|
||||
{
|
||||
m_focusTokenFunctor(tokenId);
|
||||
}
|
||||
|
||||
void QtCodeView::defocusToken()
|
||||
{
|
||||
m_defocusTokenFunctor();
|
||||
m_widget->setActiveTokenIds(m_activeTokenIds);
|
||||
m_widget->scrollToFirstActiveSnippet();
|
||||
}
|
||||
|
||||
void QtCodeView::doFocusToken(const Id tokenId)
|
||||
|
||||
@@ -32,6 +32,8 @@ public:
|
||||
virtual void showCodeSnippets(const std::vector<CodeSnippetParams>& snippets);
|
||||
virtual void showCodeFile(const CodeSnippetParams& params);
|
||||
|
||||
virtual void scrollToFirstActiveSnippet();
|
||||
|
||||
virtual void focusToken(const Id tokenId);
|
||||
virtual void defocusToken();
|
||||
|
||||
@@ -41,6 +43,8 @@ private:
|
||||
void doShowCodeSnippets(const std::vector<CodeSnippetParams>& snippets);
|
||||
void doShowCodeFile(const CodeSnippetParams& params);
|
||||
|
||||
void doScrollToFirstActiveSnippet();
|
||||
|
||||
void doFocusToken(const Id tokenId);
|
||||
void doDefocusToken();
|
||||
|
||||
@@ -49,6 +53,7 @@ private:
|
||||
QtThreadedFunctor<> m_refreshViewFunctor;
|
||||
QtThreadedFunctor<const std::vector<CodeSnippetParams>&> m_showCodeSnippetsFunctor;
|
||||
QtThreadedFunctor<const CodeSnippetParams&> m_showCodeFileFunctor;
|
||||
QtThreadedFunctor<> m_doScrollToFirstActiveSnippetFunctor;
|
||||
QtThreadedFunctor<const Id&> m_focusTokenFunctor;
|
||||
QtThreadedFunctor<> m_defocusTokenFunctor;
|
||||
|
||||
|
||||
@@ -52,6 +52,12 @@ void CodeController::handleMessage(MessageActivateTokens* message)
|
||||
view->setActiveTokenIds(activeTokenIds);
|
||||
view->setErrorMessages(std::vector<std::string>());
|
||||
|
||||
if (message->isEdge)
|
||||
{
|
||||
view->scrollToFirstActiveSnippet();
|
||||
return;
|
||||
}
|
||||
|
||||
TokenLocationCollection collection = m_storageAccess->getTokenLocationsForTokenIds(activeTokenIds);
|
||||
view->showCodeSnippets(getSnippetsForActiveTokenLocations(collection, declarationId));
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ public:
|
||||
virtual void showCodeSnippets(const std::vector<CodeSnippetParams>& snippets) = 0;
|
||||
virtual void showCodeFile(const CodeSnippetParams& params) = 0;
|
||||
|
||||
virtual void scrollToFirstActiveSnippet() = 0;
|
||||
|
||||
virtual void focusToken(const Id tokenId) = 0;
|
||||
virtual void defocusToken() = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user