logic: Return to last scroll position in code view on undo

* fixed scrolling on undo
* refactored autoscrolling in code view
* save scroll position of user with MessageScrollCode
This commit is contained in:
Eberhard Graether
2016-01-29 13:08:30 +01:00
parent 427c94457b
commit ead0abfba2
20 changed files with 240 additions and 91 deletions
+5
View File
@@ -173,6 +173,11 @@ std::shared_ptr<TokenLocationFile> QtCodeArea::getTokenLocationFile() const
return m_locationFile;
}
QtCodeFile* QtCodeArea::getFile() const
{
return m_fileWidget;
}
void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event)
{
QPainter painter(m_lineNumberArea);
+1
View File
@@ -71,6 +71,7 @@ public:
uint getEndLineNumber() const;
std::shared_ptr<TokenLocationFile> getTokenLocationFile() const;
QtCodeFile* getFile() const;
void lineNumberAreaPaintEvent(QPaintEvent* event);
int lineNumberDigits() const;
+9 -10
View File
@@ -265,13 +265,13 @@ QtCodeSnippet* QtCodeFile::findFirstActiveSnippet() const
return nullptr;
}
bool QtCodeFile::openCollapsedActiveSnippet() const
bool QtCodeFile::isCollapsedActiveFile() const
{
bool isActiveFile = false;
if (m_locationFile)
{
std::vector<Id> ids = getActiveTokenIds();
bool isActiveFile = false;
m_locationFile->forEachTokenLocation(
[&](TokenLocation* location)
{
@@ -281,15 +281,9 @@ bool QtCodeFile::openCollapsedActiveSnippet() const
}
}
);
if (isActiveFile)
{
showSnippets();
return true;
}
}
return false;
return isActiveFile;
}
void QtCodeFile::updateContent()
@@ -430,7 +424,7 @@ void QtCodeFile::clickedMaximizeButton() const
).dispatch();
}
void QtCodeFile::showSnippets() const
void QtCodeFile::requestSnippets() const
{
if (m_snippetsRequested)
{
@@ -450,6 +444,11 @@ void QtCodeFile::showSnippets() const
msg.dispatch();
}
bool QtCodeFile::hasSnippets() const
{
return m_snippets.size() > 0;
}
void QtCodeFile::handleMessage(MessageWindowFocus* message)
{
updateTitleBar();
+3 -2
View File
@@ -59,7 +59,7 @@ public:
);
QtCodeSnippet* findFirstActiveSnippet() const;
bool openCollapsedActiveSnippet() const;
bool isCollapsedActiveFile() const;
void updateContent();
@@ -69,7 +69,8 @@ public:
void setSnippets();
void setMaximized();
void showSnippets() const;
void requestSnippets() const;
bool hasSnippets() const;
public slots:
void clickedMinimizeButton() const;
+77 -25
View File
@@ -2,10 +2,12 @@
#include <QPropertyAnimation>
#include <QScrollBar>
#include <QTimer>
#include <QVariant>
#include <QVBoxLayout>
#include "utility/file/FileSystem.h"
#include "utility/messaging/type/MessageScrollCode.h"
#include "data/location/TokenLocationFile.h"
#include "qt/element/QtCodeFile.h"
@@ -13,6 +15,8 @@
QtCodeFileList::QtCodeFileList(QWidget* parent)
: QScrollArea(parent)
, m_scrollToFile(nullptr)
, m_value(0)
{
setObjectName("code_file_list_base");
@@ -28,6 +32,7 @@ QtCodeFileList::QtCodeFileList(QWidget* parent)
setWidgetResizable(true);
setWidget(m_frame.get());
connect(this->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(scrolled(int)));
connect(this, SIGNAL(shouldScrollToSnippet(QtCodeSnippet*)), this, SLOT(scrollToSnippet(QtCodeSnippet*)), Qt::QueuedConnection);
}
@@ -112,37 +117,26 @@ void QtCodeFileList::showActiveTokenIds()
updateFiles();
}
bool QtCodeFileList::scrollToFirstActiveSnippet()
void QtCodeFileList::showFirstActiveSnippet(bool scrollTo)
{
updateFiles();
QtCodeSnippet* snippet = nullptr;
for (std::shared_ptr<QtCodeFile> file: m_files)
{
snippet = file->findFirstActiveSnippet();
if (snippet)
{
if (!snippet->isVisible())
{
file->showSnippets();
}
QtCodeSnippet* snippet = getFirstActiveSnippet();
emit shouldScrollToSnippet(snippet);
return true;
}
if (!snippet)
{
expandActiveSnippetFile(scrollTo);
return;
}
return false;
}
void QtCodeFileList::expandActiveSnippetFile()
{
for (std::shared_ptr<QtCodeFile> file: m_files)
if (!snippet->isVisible())
{
if (file->openCollapsedActiveSnippet())
{
return;
}
snippet->getFile()->setSnippets();
}
if (scrollTo)
{
emit shouldScrollToSnippet(snippet);
}
}
@@ -193,11 +187,36 @@ void QtCodeFileList::showContents()
}
}
void QtCodeFileList::scrollToValue(int value)
{
m_value = value;
QTimer::singleShot(100, this, SLOT(setValue()));
}
void QtCodeFileList::scrollToActiveFileIfRequested()
{
if (m_scrollToFile && m_scrollToFile->hasSnippets())
{
showFirstActiveSnippet(true);
m_scrollToFile = nullptr;
}
}
void QtCodeFileList::scrolled(int value)
{
MessageScrollCode(value).dispatch();
}
void QtCodeFileList::scrollToSnippet(QtCodeSnippet* snippet)
{
this->ensureWidgetVisibleAnimated(snippet, snippet->getFirstActiveLineRect());
}
void QtCodeFileList::setValue()
{
this->verticalScrollBar()->setValue(m_value);
}
QtCodeFile* QtCodeFileList::getFile(const FilePath filePath)
{
QtCodeFile* file = nullptr;
@@ -225,6 +244,21 @@ QtCodeFile* QtCodeFileList::getFile(const FilePath filePath)
return file;
}
QtCodeSnippet* QtCodeFileList::getFirstActiveSnippet() const
{
QtCodeSnippet* snippet = nullptr;
for (std::shared_ptr<QtCodeFile> file: m_files)
{
snippet = file->findFirstActiveSnippet();
if (snippet)
{
break;
}
}
return snippet;
}
void QtCodeFileList::updateFiles()
{
for (std::shared_ptr<QtCodeFile> file: m_files)
@@ -233,6 +267,24 @@ void QtCodeFileList::updateFiles()
}
}
void QtCodeFileList::expandActiveSnippetFile(bool scrollTo)
{
for (std::shared_ptr<QtCodeFile> file: m_files)
{
if (file->isCollapsedActiveFile())
{
file->requestSnippets();
if (scrollTo)
{
m_scrollToFile = file.get();
}
return;
}
}
}
void QtCodeFileList::ensureWidgetVisibleAnimated(QWidget *childWidget, QRectF rect)
{
if (!widget()->isAncestorOf(childWidget))
@@ -259,7 +311,7 @@ void QtCodeFileList::ensureWidgetVisibleAnimated(QWidget *childWidget, QRectF re
if (scrollBar && value != 0)
{
QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value");
anim->setDuration(500);
anim->setDuration(300);
anim->setStartValue(scrollBar->value());
anim->setEndValue(scrollBar->value() + value);
anim->setEasingCurve(QEasingCurve::InOutQuad);
+10 -2
View File
@@ -55,8 +55,7 @@ public:
void showActiveTokenIds();
bool scrollToFirstActiveSnippet();
void expandActiveSnippetFile();
void showFirstActiveSnippet(bool scrollTo);
void focusTokenIds(const std::vector<Id>& focusedTokenIds);
void defocusTokenIds();
@@ -66,15 +65,21 @@ public:
void setFileMaximized(const FilePath path);
void showContents();
void scrollToValue(int value);
void scrollToActiveFileIfRequested();
private slots:
void scrolled(int value);
void scrollToSnippet(QtCodeSnippet* snippet);
void setValue();
private:
QtCodeFile* getFile(const FilePath filePath);
QtCodeSnippet* getFirstActiveSnippet() const;
void updateFiles();
void expandActiveSnippetFile(bool scrollTo);
void ensureWidgetVisibleAnimated(QWidget *childWidget, QRectF rect);
std::shared_ptr<QFrame> m_frame;
@@ -83,6 +88,9 @@ private:
std::vector<Id> m_activeTokenIds;
std::vector<Id> m_focusedTokenIds;
std::vector<std::string> m_errorMessages;
QtCodeFile* m_scrollToFile;
int m_value;
};
#endif // QT_CODE_FILE_LIST
+5
View File
@@ -110,6 +110,11 @@ QtCodeSnippet::~QtCodeSnippet()
{
}
QtCodeFile* QtCodeSnippet::getFile() const
{
return m_codeArea->getFile();
}
uint QtCodeSnippet::getStartLineNumber() const
{
return m_codeArea->getStartLineNumber();
+2
View File
@@ -32,6 +32,8 @@ public:
);
virtual ~QtCodeSnippet();
QtCodeFile* getFile() const;
uint getStartLineNumber() const;
uint getEndLineNumber() const;
+18 -17
View File
@@ -16,12 +16,12 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout)
, m_addCodeSnippetsFunctor(std::bind(&QtCodeView::doAddCodeSnippets, this, std::placeholders::_1, std::placeholders::_2))
, m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1))
, m_setFileStateFunctor(std::bind(&QtCodeView::doSetFileState, this, std::placeholders::_1, std::placeholders::_2))
, m_doShowFirstActiveSnippetFunctor(std::bind(&QtCodeView::doShowFirstActiveSnippet, this, std::placeholders::_1))
, m_doShowFirstActiveSnippetFunctor(std::bind(&QtCodeView::doShowFirstActiveSnippet, this, std::placeholders::_1, std::placeholders::_2))
, m_doShowActiveTokenIdsFunctor(std::bind(&QtCodeView::doShowActiveTokenIds, this, std::placeholders::_1))
, m_focusTokenIdsFunctor(std::bind(&QtCodeView::doFocusTokenIds, this, std::placeholders::_1))
, m_defocusTokenIdsFunctor(std::bind(&QtCodeView::doDefocusTokenIds, this))
, m_showContentsFunctor(std::bind(&QtCodeView::doShowContents, this))
, m_isExpanding(false)
, m_scrollToValueFunctor(std::bind(&QtCodeView::doScrollToValue, this, std::placeholders::_1))
{
m_widget = new QtCodeFileList();
setStyleSheet();
@@ -75,9 +75,9 @@ void QtCodeView::setFileState(const FilePath filePath, FileState state)
m_setFileStateFunctor(filePath, state);
}
void QtCodeView::showFirstActiveSnippet(const std::vector<Id>& activeTokenIds)
void QtCodeView::showFirstActiveSnippet(const std::vector<Id>& activeTokenIds, bool scrollTo)
{
m_doShowFirstActiveSnippetFunctor(activeTokenIds);
m_doShowFirstActiveSnippetFunctor(activeTokenIds, scrollTo);
}
void QtCodeView::showActiveTokenIds(const std::vector<Id>& activeTokenIds)
@@ -100,6 +100,11 @@ void QtCodeView::showContents()
m_showContentsFunctor();
}
void QtCodeView::scrollToValue(int value)
{
m_scrollToValueFunctor(value);
}
void QtCodeView::doRefreshView()
{
setStyleSheet();
@@ -155,11 +160,7 @@ void QtCodeView::doAddCodeSnippets(const std::vector<CodeSnippetParams>& snippet
setStyleSheet(); // so property "isLast" of QtCodeSnippet is computed correctly
if (m_isExpanding)
{
m_widget->scrollToFirstActiveSnippet();
m_isExpanding = false;
}
m_widget->scrollToActiveFileIfRequested();
}
void QtCodeView::doShowCodeFile(const CodeSnippetParams& params)
@@ -183,15 +184,10 @@ void QtCodeView::doSetFileState(const FilePath filePath, FileState state)
}
}
void QtCodeView::doShowFirstActiveSnippet(const std::vector<Id>& activeTokenIds)
void QtCodeView::doShowFirstActiveSnippet(const std::vector<Id>& activeTokenIds, bool scrollTo)
{
m_widget->setActiveTokenIds(activeTokenIds);
if (!m_widget->scrollToFirstActiveSnippet())
{
m_widget->expandActiveSnippetFile();
m_isExpanding = true;
}
m_widget->showFirstActiveSnippet(scrollTo);
}
void QtCodeView::doShowActiveTokenIds(const std::vector<Id>& activeTokenIds)
@@ -210,11 +206,16 @@ void QtCodeView::doDefocusTokenIds()
m_widget->defocusTokenIds();
}
void QtCodeView::doShowContents() const
void QtCodeView::doShowContents()
{
m_widget->showContents();
}
void QtCodeView::doScrollToValue(int value)
{
m_widget->scrollToValue(value);
}
void QtCodeView::setStyleSheet() const
{
utility::setWidgetBackgroundColor(m_widget, ColorScheme::getInstance()->getColor("code/background"));
+9 -6
View File
@@ -35,7 +35,7 @@ public:
virtual void setFileState(const FilePath filePath, FileState state);
virtual void showFirstActiveSnippet(const std::vector<Id>& activeTokenIds);
virtual void showFirstActiveSnippet(const std::vector<Id>& activeTokenIds, bool scrollTo);
virtual void showActiveTokenIds(const std::vector<Id>& activeTokenIds);
virtual void focusTokenIds(const std::vector<Id>& focusedTokenIds);
@@ -43,6 +43,8 @@ public:
virtual void showContents();
virtual void scrollToValue(int value);
private:
void doRefreshView();
@@ -52,13 +54,15 @@ private:
void doSetFileState(const FilePath filePath, FileState state);
void doShowFirstActiveSnippet(const std::vector<Id>& activeTokenIds);
void doShowFirstActiveSnippet(const std::vector<Id>& activeTokenIds, bool scrollTo);
void doShowActiveTokenIds(const std::vector<Id>& activeTokenIds);
void doFocusTokenIds(const std::vector<Id>& focusedTokenIds);
void doDefocusTokenIds();
void doShowContents() const;
void doShowContents();
void doScrollToValue(int value);
void setStyleSheet() const;
@@ -67,18 +71,17 @@ private:
QtThreadedFunctor<const std::vector<CodeSnippetParams>&, bool> m_addCodeSnippetsFunctor;
QtThreadedFunctor<const CodeSnippetParams&> m_showCodeFileFunctor;
QtThreadedFunctor<const FilePath, FileState> m_setFileStateFunctor;
QtThreadedFunctor<const std::vector<Id>&> m_doShowFirstActiveSnippetFunctor;
QtThreadedFunctor<const std::vector<Id>&, bool> m_doShowFirstActiveSnippetFunctor;
QtThreadedFunctor<const std::vector<Id>&> m_doShowActiveTokenIdsFunctor;
QtThreadedFunctor<const std::vector<Id>&> m_focusTokenIdsFunctor;
QtThreadedFunctor<> m_defocusTokenIdsFunctor;
QtThreadedFunctor<> m_showContentsFunctor;
QtThreadedFunctor<int> m_scrollToValueFunctor;
QtCodeFileList* m_widget;
std::vector<Id> m_activeTokenIds;
std::vector<std::string> m_errorMessages;
bool m_isExpanding;
};
# endif // QT_CODE_VIEW_H