summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@qt.io>2017-05-23 14:34:22 +0200
committerDavid Schulz <david.schulz@qt.io>2017-06-15 09:24:07 +0000
commit2b83869236d08b8e635c94c99095630d9a12130e (patch)
tree7f9aee52a8bf304b473aeeb328ef247893a81ba3
parent752662e478d1cd8594993b1dc7915ec2dfc6ff50 (diff)
downloadqt-creator-2b83869236d08b8e635c94c99095630d9a12130e.tar.gz
TextEditor: Animate navigation within file
Change-Id: I490d70a785c947cd41809503e15a317152126641 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
-rw-r--r--src/plugins/cppeditor/cppoutline.cpp2
-rw-r--r--src/plugins/cpptools/cppeditoroutline.cpp2
-rw-r--r--src/plugins/texteditor/displaysettings.cpp7
-rw-r--r--src/plugins/texteditor/displaysettings.h2
-rw-r--r--src/plugins/texteditor/displaysettingspage.cpp2
-rw-r--r--src/plugins/texteditor/displaysettingspage.ui9
-rw-r--r--src/plugins/texteditor/texteditor.cpp75
-rw-r--r--src/plugins/texteditor/texteditor.h3
8 files changed, 89 insertions, 13 deletions
diff --git a/src/plugins/cppeditor/cppoutline.cpp b/src/plugins/cppeditor/cppoutline.cpp
index 3b1209c1c8..def7d11a6e 100644
--- a/src/plugins/cppeditor/cppoutline.cpp
+++ b/src/plugins/cppeditor/cppoutline.cpp
@@ -173,7 +173,7 @@ void CppOutlineWidget::updateTextCursor(const QModelIndex &proxyIndex)
Core::EditorManager::addCurrentPositionToNavigationHistory();
// line has to be 1 based, column 0 based!
- m_editor->gotoLine(symbol->line(), symbol->column() - 1);
+ m_editor->gotoLine(symbol->line(), symbol->column() - 1, true, true);
m_blockCursorSync = false;
}
}
diff --git a/src/plugins/cpptools/cppeditoroutline.cpp b/src/plugins/cpptools/cppeditoroutline.cpp
index a5192f4441..8bd16ac98b 100644
--- a/src/plugins/cpptools/cppeditoroutline.cpp
+++ b/src/plugins/cpptools/cppeditoroutline.cpp
@@ -252,7 +252,7 @@ void CppEditorOutline::gotoSymbolInEditor()
Core::EditorManager::cutForwardNavigationHistory();
Core::EditorManager::addCurrentPositionToNavigationHistory();
- m_editorWidget->gotoLine(link.targetLine, link.targetColumn);
+ m_editorWidget->gotoLine(link.targetLine, link.targetColumn, true, true);
m_editorWidget->activateEditor();
}
diff --git a/src/plugins/texteditor/displaysettings.cpp b/src/plugins/texteditor/displaysettings.cpp
index a2a06eff78..d15cf52dca 100644
--- a/src/plugins/texteditor/displaysettings.cpp
+++ b/src/plugins/texteditor/displaysettings.cpp
@@ -42,6 +42,8 @@ static const char centerCursorOnScrollKey[] = "CenterCursorOnScroll";
static const char openLinksInNextSplitKey[] = "OpenLinksInNextSplitKey";
static const char displayFileEncodingKey[] = "DisplayFileEncoding";
static const char scrollBarHighlightsKey[] = "ScrollBarHighlights";
+static const char animateNavigationWithinFileKey[] = "AnimateNavigationWithinFile";
+static const char animateWithinFileTimeMaxKey[] = "AnimateWithinFileTimeMax";
static const char groupPostfix[] = "DisplaySettings";
namespace TextEditor {
@@ -66,6 +68,7 @@ void DisplaySettings::toSettings(const QString &category, QSettings *s) const
s->setValue(QLatin1String(openLinksInNextSplitKey), m_openLinksInNextSplit);
s->setValue(QLatin1String(displayFileEncodingKey), m_displayFileEncoding);
s->setValue(QLatin1String(scrollBarHighlightsKey), m_scrollBarHighlights);
+ s->setValue(QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile);
s->endGroup();
}
@@ -92,6 +95,8 @@ void DisplaySettings::fromSettings(const QString &category, const QSettings *s)
m_openLinksInNextSplit = s->value(group + QLatin1String(openLinksInNextSplitKey), m_openLinksInNextSplit).toBool();
m_displayFileEncoding = s->value(group + QLatin1String(displayFileEncodingKey), m_displayFileEncoding).toBool();
m_scrollBarHighlights = s->value(group + QLatin1String(scrollBarHighlightsKey), m_scrollBarHighlights).toBool();
+ m_animateNavigationWithinFile = s->value(group + QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile).toBool();
+ m_animateWithinFileTimeMax = s->value(group + QLatin1String(animateWithinFileTimeMaxKey), m_animateWithinFileTimeMax).toInt();
}
bool DisplaySettings::equals(const DisplaySettings &ds) const
@@ -111,6 +116,8 @@ bool DisplaySettings::equals(const DisplaySettings &ds) const
&& m_forceOpenLinksInNextSplit == ds.m_forceOpenLinksInNextSplit
&& m_displayFileEncoding == ds.m_displayFileEncoding
&& m_scrollBarHighlights == ds.m_scrollBarHighlights
+ && m_animateNavigationWithinFile == ds.m_animateNavigationWithinFile
+ && m_animateWithinFileTimeMax == ds.m_animateWithinFileTimeMax
;
}
diff --git a/src/plugins/texteditor/displaysettings.h b/src/plugins/texteditor/displaysettings.h
index 08d2077768..fabebd96d8 100644
--- a/src/plugins/texteditor/displaysettings.h
+++ b/src/plugins/texteditor/displaysettings.h
@@ -56,6 +56,8 @@ public:
bool m_forceOpenLinksInNextSplit = false;
bool m_displayFileEncoding = false;
bool m_scrollBarHighlights = true;
+ bool m_animateNavigationWithinFile = false;
+ int m_animateWithinFileTimeMax = 333; // read only setting
bool equals(const DisplaySettings &ds) const;
};
diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp
index 946234c0ec..147fa97080 100644
--- a/src/plugins/texteditor/displaysettingspage.cpp
+++ b/src/plugins/texteditor/displaysettingspage.cpp
@@ -118,6 +118,7 @@ void DisplaySettingsPage::settingsFromUI(DisplaySettings &displaySettings,
displaySettings.m_openLinksInNextSplit = d->m_page->openLinksInNextSplit->isChecked();
displaySettings.m_displayFileEncoding = d->m_page->displayFileEncoding->isChecked();
displaySettings.m_scrollBarHighlights = d->m_page->scrollBarHighlights->isChecked();
+ displaySettings.m_animateNavigationWithinFile = d->m_page->animateNavigationWithinFile->isChecked();
}
void DisplaySettingsPage::settingsToUI()
@@ -140,6 +141,7 @@ void DisplaySettingsPage::settingsToUI()
d->m_page->openLinksInNextSplit->setChecked(displaySettings.m_openLinksInNextSplit);
d->m_page->displayFileEncoding->setChecked(displaySettings.m_displayFileEncoding);
d->m_page->scrollBarHighlights->setChecked(displaySettings.m_scrollBarHighlights);
+ d->m_page->animateNavigationWithinFile->setChecked(displaySettings.m_animateNavigationWithinFile);
}
const DisplaySettings &DisplaySettingsPage::displaySettings() const
diff --git a/src/plugins/texteditor/displaysettingspage.ui b/src/plugins/texteditor/displaysettingspage.ui
index ee8b15cfdf..b91965a192 100644
--- a/src/plugins/texteditor/displaysettingspage.ui
+++ b/src/plugins/texteditor/displaysettingspage.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>501</width>
- <height>331</height>
+ <height>339</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
@@ -174,6 +174,13 @@
</property>
</widget>
</item>
+ <item row="7" column="1">
+ <widget class="QCheckBox" name="animateNavigationWithinFile">
+ <property name="text">
+ <string>Animate navigation within file</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 2eed90f3c7..86d74f28ad 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -99,7 +99,9 @@
#include <QPainter>
#include <QPrintDialog>
#include <QPrinter>
+#include <QPropertyAnimation>
#include <QDrag>
+#include <QSequentialAnimationGroup>
#include <QScrollBar>
#include <QShortcut>
#include <QStyle>
@@ -457,6 +459,8 @@ public:
bool m_assistRelevantContentAdded = false;
QList<BaseHoverHandler *> m_hoverHandlers; // Not owned
+ QPointer<QSequentialAnimationGroup> m_navigationAnimation;
+
QPointer<TextEditorAnimator> m_bracketsAnimator;
// Animation and highlighting of auto completed text
@@ -2515,7 +2519,7 @@ void TextEditorWidget::doSetTextCursor(const QTextCursor &cursor)
doSetTextCursor(cursor, false);
}
-void TextEditorWidget::gotoLine(int line, int column, bool centerLine)
+void TextEditorWidget::gotoLine(int line, int column, bool centerLine, bool animate)
{
d->m_lastCursorChangeWasInteresting = false; // avoid adding the previous position to history
const int blockNumber = qMin(line, document()->blockCount()) - 1;
@@ -2531,12 +2535,61 @@ void TextEditorWidget::gotoLine(int line, int column, bool centerLine)
}
cursor.setPosition(pos);
}
- setTextCursor(cursor);
- if (centerLine)
- centerCursor();
- else
- ensureCursorVisible();
+ const DisplaySettings &ds = d->m_displaySettings;
+ if (animate && ds.m_animateNavigationWithinFile) {
+ const QScrollBar *scrollBar = verticalScrollBar();
+ const int start = scrollBar->value();
+
+ setTextCursor(cursor);
+ ensureBlockIsUnfolded(block);
+
+ const int visibleLines = lastVisibleLine() - firstVisibleLine();
+
+ int end = 0;
+ auto it = document()->firstBlock();
+ while (it.isValid() && it != block) {
+ if (it.isVisible())
+ ++end;
+ it = it.next();
+ }
+
+ if (centerLine)
+ end = qMin(scrollBar->maximum(), qMax(scrollBar->minimum(), end - visibleLines / 2));
+
+ const int delta = end - start;
+ // limit the number of steps for the animation otherwise you wont be able to tell
+ // the direction of the animantion for large delta values
+ const int steps = qMax(-ds.m_animateWithinFileTimeMax,
+ qMin(ds.m_animateWithinFileTimeMax, delta));
+ // limit the duration of the animation to at least 4 pictures on a 60Hz Monitor and
+ // at most to the number of absolute steps
+ const int durationMinimum = int (4 // number of pictures
+ * float(1) / 60 // on a 60 Hz Monitor
+ * 1000); // milliseconds
+ const int duration = qMax(durationMinimum, qAbs(steps));
+
+ d->m_navigationAnimation = new QSequentialAnimationGroup(this);
+ auto startAnimation = new QPropertyAnimation(verticalScrollBar(), "value");
+ startAnimation->setEasingCurve(QEasingCurve::InExpo);
+ startAnimation->setStartValue(start);
+ startAnimation->setEndValue(start + steps / 2);
+ startAnimation->setDuration(duration / 2);
+ d->m_navigationAnimation->addAnimation(startAnimation);
+ auto endAnimation = new QPropertyAnimation(verticalScrollBar(), "value");
+ endAnimation->setEasingCurve(QEasingCurve::OutExpo);
+ endAnimation->setStartValue(end - steps / 2);
+ endAnimation->setEndValue(end);
+ endAnimation->setDuration(duration / 2);
+ d->m_navigationAnimation->addAnimation(endAnimation);
+ d->m_navigationAnimation->start(QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ setTextCursor(cursor);
+ if (centerLine)
+ centerCursor();
+ else
+ ensureCursorVisible();
+ }
}
d->saveCurrentCursorPositionForNavigation();
}
@@ -5224,7 +5277,12 @@ void TextEditorWidget::extraAreaMouseEvent(QMouseEvent *e)
void TextEditorWidget::ensureCursorVisible()
{
- QTextBlock block = textCursor().block();
+ ensureBlockIsUnfolded(textCursor().block());
+ QPlainTextEdit::ensureCursorVisible();
+}
+
+void TextEditorWidget::ensureBlockIsUnfolded(QTextBlock block)
+{
if (!block.isVisible()) {
TextDocumentLayout *documentLayout = qobject_cast<TextDocumentLayout*>(document()->documentLayout());
QTC_ASSERT(documentLayout, return);
@@ -5246,7 +5304,6 @@ void TextEditorWidget::ensureCursorVisible()
documentLayout->requestUpdate();
documentLayout->emitDocumentSizeChanged();
}
- QPlainTextEdit::ensureCursorVisible();
}
void TextEditorWidgetPrivate::toggleBlockVisible(const QTextBlock &block)
@@ -5493,7 +5550,7 @@ bool TextEditorWidget::openLink(const Link &link, bool inNextSplit)
if (!inNextSplit && textDocument()->filePath().toString() == link.targetFileName) {
EditorManager::addCurrentPositionToNavigationHistory();
- gotoLine(link.targetLine, link.targetColumn);
+ gotoLine(link.targetLine, link.targetColumn, true, true);
setFocus();
return true;
}
diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h
index 9b996dd61b..841324891c 100644
--- a/src/plugins/texteditor/texteditor.h
+++ b/src/plugins/texteditor/texteditor.h
@@ -183,7 +183,7 @@ public:
// IEditor
QByteArray saveState() const;
bool restoreState(const QByteArray &state);
- void gotoLine(int line, int column = 0, bool centerLine = true);
+ void gotoLine(int line, int column = 0, bool centerLine = true, bool animate = false);
int position(TextPositionOperation posOp = CurrentPosition,
int at = -1) const;
void convertPosition(int pos, int *line, int *column) const;
@@ -297,6 +297,7 @@ public:
const BehaviorSettings &behaviorSettings() const;
void ensureCursorVisible();
+ void ensureBlockIsUnfolded(QTextBlock block);
static Core::Id FakeVimSelection;
static Core::Id SnippetPlaceholderSelection;