From c791195ae72c4eb1ffc9755b03819c03cc621f3b Mon Sep 17 00:00:00 2001
From: J-P Nurmi <jpnurmi@digia.com>
Date: Mon, 25 Feb 2013 16:48:54 +0100
Subject: [PATCH] ScrollView & TextArea: fix vertical scrollbar visibility

Avoid binding loops by using recursion guards...

Change-Id: I1fb9f4ac54d6fa3cf930a848e22ec6b23edfa200
Reviewed-by: Jens Bache-Wiig <jens.bache-wiig@digia.com>
---
 examples/gallery/content/Controls.qml |  7 ++++++
 src/controls/TextArea.qml             | 27 +++++++++++++++++++--
 src/private/ScrollViewHelper.qml      | 35 +++++++++++++++++++++++----
 3 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/examples/gallery/content/Controls.qml b/examples/gallery/content/Controls.qml
index 49315d3c7..a2c17619c 100644
--- a/examples/gallery/content/Controls.qml
+++ b/examples/gallery/content/Controls.qml
@@ -146,6 +146,12 @@ Item {
                         id: tickmarkCheck
                         text: "Tickmarks"
                         checked: false
+                        KeyNavigation.tab: wrapCheck
+                    }
+                    CheckBox {
+                        id: wrapCheck
+                        text: "Word wrap"
+                        checked: true
                         KeyNavigation.tab: r1
                     }
                 }
@@ -179,6 +185,7 @@ Item {
                 frameVisible: frameCheckbox.checked
                 text: loremIpsum + loremIpsum
                 KeyNavigation.tab: button1
+                wrapMode: wrapCheck.checked ? TextEdit.WordWrap : TextEdit.NoWrap
                 width: contentRow.width - firstColumn.width - contentRow.spacing
                 height: parent.height - group1.height - group2.height - 2 * parent.spacing
                 anchors { right: parent.right }
diff --git a/src/controls/TextArea.qml b/src/controls/TextArea.qml
index 4f1442cb8..49e31bdbc 100644
--- a/src/controls/TextArea.qml
+++ b/src/controls/TextArea.qml
@@ -616,6 +616,31 @@ ScrollView {
             z: -1
         }
 
+        property bool recursionGuard: false
+
+        function doLayout() {
+            if (!recursionGuard) {
+                recursionGuard = true
+                if (wrapMode == TextEdit.NoWrap) {
+                    horizontalScrollBar.visible = edit.paintedWidth + (2 * documentMargins) > area.viewport.width
+                    edit.width = edit.paintedWidth + (2 * documentMargins)
+                } else {
+                    horizontalScrollBar.visible = false
+                    edit.width = area.viewport.width - (2 * documentMargins)
+                }
+                edit.height = Math.max(area.viewport.height - (2 * documentMargins), paintedHeight + (2 * documentMargins))
+                recursionGuard = false
+            }
+        }
+
+        Connections {
+            target: area.viewport
+            onWidthChanged: edit.doLayout()
+            onHeightChanged: edit.doLayout()
+        }
+        onPaintedWidthChanged: edit.doLayout()
+        onPaintedHeightChanged: edit.doLayout()
+        onWrapModeChanged: edit.doLayout()
 
         renderType: Text.NativeRendering
 
@@ -623,8 +648,6 @@ ScrollView {
         selectionColor: palette.highlight
         selectedTextColor: palette.highlightedText
         wrapMode: TextEdit.WordWrap
-        width: area.viewport.width - (2 * documentMargins)
-        height: Math.max(area.viewport.height - (2 * documentMargins), paintedHeight + (2 * documentMargins))
         x: documentMargins
         y: documentMargins
 
diff --git a/src/private/ScrollViewHelper.qml b/src/private/ScrollViewHelper.qml
index 0386213a7..0eadfb13a 100644
--- a/src/private/ScrollViewHelper.qml
+++ b/src/private/ScrollViewHelper.qml
@@ -53,15 +53,40 @@ Item {
     property alias horizontalScrollBar: hscrollbar
     property alias verticalScrollBar: vscrollbar
     property bool blockUpdates: false
-    property int availableHeight : viewport ? viewport.height : 0
-    property int availableWidth: viewport ? viewport.width : 0
-    property int contentHeight: flickableItem ? flickableItem.contentHeight : 0
-    property int contentWidth: flickableItem ? flickableItem.contentWidth: 0
+    property int availableHeight
+    property int availableWidth
+    property int contentHeight
+    property int contentWidth
 
     anchors.fill: parent
 
     property int frameMargin: outerFrame ? frameWidth : 0
 
+    property bool recursionGuard: false
+
+    function doLayout() {
+        if (!recursionGuard) {
+            recursionGuard = true
+            wheelarea.availableWidth = viewport.width
+            wheelarea.availableHeight = viewport.height
+            wheelarea.contentWidth = flickableItem.contentWidth
+            wheelarea.contentHeight = flickableItem.contentHeight
+            recursionGuard = false
+        }
+    }
+
+    Connections {
+        target: viewport
+        onWidthChanged: doLayout()
+        onHeightChanged: doLayout()
+    }
+
+    Connections {
+        target: flickableItem
+        onContentWidthChanged: doLayout()
+        onContentHeightChanged: doLayout()
+    }
+
     Connections {
         target: flickableItem
         onContentXChanged: {
@@ -126,7 +151,7 @@ Item {
         property bool isTransient: !!styleItem && styleItem.styleHint("transientScrollBars")
         property bool active: !!styleItem && (styleItem.sunken || styleItem.activeControl != "none")
         orientation: Qt.Vertical
-        // visible: contentHeight > availableHeight
+        visible: contentHeight > availableHeight
         width: visible ? implicitWidth : 0
         z: 1
         anchors.bottom: cornerFill.top
-- 
GitLab