diff options
author | Jens Bache-Wiig <jens.bache-wiig@digia.com> | 2013-02-07 18:47:37 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-02-08 12:22:28 +0100 |
commit | 2e0048afd1283e5995ec26a1d31643dc32e8d97a (patch) | |
tree | e5426d6bb214563251f482b82fb9b6d6cf4d5496 /src/qtdesktop/private/Splitter.qml | |
parent | 898f4b1cc506ecee1d4c293110563cd2500d1b32 (diff) | |
download | qtquickcontrols-2e0048afd1283e5995ec26a1d31643dc32e8d97a.tar.gz |
Introduce private plugin
Change-Id: I4beedc773df5b9b207554b55e86aa1439cb4d06e
Reviewed-by: Jens Bache-Wiig <jens.bache-wiig@digia.com>
Diffstat (limited to 'src/qtdesktop/private/Splitter.qml')
-rw-r--r-- | src/qtdesktop/private/Splitter.qml | 471 |
1 files changed, 0 insertions, 471 deletions
diff --git a/src/qtdesktop/private/Splitter.qml b/src/qtdesktop/private/Splitter.qml deleted file mode 100644 index b24840b6..00000000 --- a/src/qtdesktop/private/Splitter.qml +++ /dev/null @@ -1,471 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Components project. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.0 -import QtDesktop 1.0 - -Splitter { - id: root - default property alias items: splitterItems.children - property alias handles: splitterHandles.children - property Component handleDelegate: Rectangle { width:3; color: "black" } - property int handleWidth: -1 - property real preferredSize: 0 - property int orientation: Qt.Horizontal - - clip: true - Component.onCompleted: d.init(); - onWidthChanged: d.updateLayout(); - onHeightChanged: d.updateLayout(); - - QtObject { - id: d - - property bool horizontal: orientation == Qt.Horizontal - property string size: horizontal ? "width" : "height" - property string minimum: horizontal ? "minimumWidth" : "minimumHeight" - property string maximum: horizontal ? "maximumWidth" : "maximumHeight" - - property string offset: horizontal ? "x" : "y" - property int expandingIndex: -1 - property bool updateLayoutGuard: true - property bool itemWidthGuard: false - property bool itemExpandingGuard: true - - function init() - { - for (var i=0; i<items.length; ++i) { - var item = items[i]; - - item.Splitter.itemIndex = i - // Assign one, and only one, item to be expanding: - if (item.Splitter.expanding === true) { - if (d.expandingIndex === -1 && item.visible === true) - d.expandingIndex = i - else - item.Splitter.expanding = false - } - - // Anchor each item to fill out all space vertically: - if (d.horizontal) { - item.anchors.top = splitterItems.top - item.anchors.bottom = splitterItems.bottom - } else { - item.anchors.left = splitterItems.left - item.anchors.right = splitterItems.right - - } - - // Listen for changes to width and expanding: - propertyChangeListener.createObject(item, {"itemIndex":i}); - if (i < items.length-1) { - // Create a handle for the item, unless its the last: - var handle = handleloader.createObject(splitterHandles, {"handleIndex":i}); - - if (d.horizontal) { - handle.anchors.top = splitterHandles.top - handle.anchors.bottom = splitterHandles.bottom - } else { - handle.anchors.left = splitterHandles.left - handle.anchors.right = splitterHandles.right - } - } - } - - if (d.expandingIndex === -1) { - // INVARIANT: No item was set as expanding. - // We then choose the last visible item instead: - d.expandingIndex = items.length - 1 - for (i=items.length-1; i>=0; --i) { - var item = items[i] - if (item.visible === true) { - d.expandingIndex = i - item = items[i] - break - } - } - if (items.length && item.visible) { - item.Splitter.expanding = true - } - } - - d.itemExpandingGuard = false - d.updateLayoutGuard = false - d.updateLayout() - } - - function accumulatedSize(firstIndex, lastIndex, includeExpandingMinimum) - { - // Go through items and handles, and - // calculate their acummulated width. - var w = 0 - for (var i=firstIndex; i<lastIndex; ++i) { - var item = items[i] - if (item.visible) { - if (i !== d.expandingIndex) - w += item[d.size]; - else if (includeExpandingMinimum && item.Splitter[minimum] != -1) - w += item.Splitter[minimum] - } - - var handle = handles[i] - if (handle && items[i + ((d.expandingIndex > i) ? 0 : 1)].visible) - w += handle[d.size] - } - return w - } - - function updateLayout() - { - // This function will reposition both handles and - // items according to the _width of the each item_ - if (items.length === 0) - return; - if (d.updateLayoutGuard === true) - return - d.updateLayoutGuard = true - - // Use a temporary variable to store values to avoid breaking - // property bindings when the value does not actually change: - var newValue - - // Ensure all items within min/max: - for (var i=0; i<items.length; ++i) { - if (i !== d.expandingIndex) { - item = items[i]; - // If the item is using percentage width, convert - // that number to real width now: - if (item.Splitter.percentageSize !== -1) { - newValue = item.Splitter.percentageSize * (root[d.size] / 100) - if (newValue !== item[d.size]) - item[d.size] = newValue - } - // Ensure item width is not more than maximumSize: - if (item.Splitter[maximum] !== -1) { - newValue = Math.min(item[d.size], item.Splitter[maximum]) - if (newValue !== item[d.size]) - item[d.size] = newValue - } - // Ensure item width is not more less minimumWidth: - if (item.Splitter[minimum] !== -1) { - newValue = Math.max(item[d.size], item.Splitter[minimum]) - if (newValue !== item[d.size]) - item[d.size] = newValue - } - } - } - - // Special case: set width of expanding item to available space: - newValue = root[d.size] - d.accumulatedSize(0, items.length, false); - var expandingItem = items[d.expandingIndex] - var expandingMinimum = 0 - if (expandingItem.Splitter[minimum] !== -1) - expandingMinimum = expandingItem.Splitter[minimum] - newValue = Math.max(newValue, expandingMinimum) - if (expandingItem[d.size] !== 0 && expandingItem.Splitter.percentageSize !== -1) - expandingItem.Splitter.percentageSize = newValue * (100 / root[d.size]) - if (expandingItem[d.size] !== newValue) - expandingItem[d.size] = newValue - - // Then, position items and handles according to their width: - var item, lastVisibleItem - var handle, lastVisibleHandle - var newpreferredSize = expandingMinimum - expandingItem[d.size] - - for (i=0; i<items.length; ++i) { - // Position item to the right of the previous visible handle: - item = items[i]; - if (item.visible) { - if (lastVisibleHandle) { - newValue = lastVisibleHandle[d.offset] + lastVisibleHandle[d.size] - if (newValue !== item[d.offset]) - item[d.offset] = newValue - } else { - newValue = 0 - if (newValue !== item[d.offset]) - item[d.offset] = newValue - } - newpreferredSize += item[d.size] - lastVisibleItem = item - } - - // Position handle to the right of the previous visible item. We use an alterative way of - // checking handle visibility because that property might not have updated correctly yet: - handle = handles[i] - if (handle && items[i + ((d.expandingIndex > i) ? 0 : 1)].visible) { - newValue = lastVisibleItem[d.offset] + Math.max(0, lastVisibleItem[d.size]) - if (newValue !== handle[d.offset]) - handle[d.offset] = newValue - newpreferredSize += handle[d.size] - lastVisibleHandle = handle - } - } - - root.preferredSize = newpreferredSize - d.updateLayoutGuard = false - } - } - - Component { - id: handleloader - Loader { - id: myHandle - property int handleIndex: 0 - property Item handle: myHandle - property Item splitterItem: items[handleIndex + ((d.expandingIndex > handleIndex) ? 0 : 1)] - - // 'splitterRow' should be an alias, but that fails to resolve runtime: - property Item splitterRow: root - property Item background: item - - visible: splitterItem.visible - sourceComponent: handleDelegate - onWidthChanged: d.updateLayout() - onHeightChanged: d.updateLayout() - - onXChanged: { - // For some unknown reason, dragging by X axis only not working in MouseArea, so - // to enable it Drag.XandYAxis should be used, therefore not only Y coordinate - // changes, but also X and we need to filter out this events, if we have splitter, - // that should move vertically - if (d.horizontal) { - moveHandle() - } - } - - onYChanged: { - moveHandle() - } - - function moveHandle() { - // Moving the handle means resizing an item. Which one, - // left or right, depends on where the expanding item is. - // 'updateLayout' will override in case new width violates max/min. - // And 'updateLayout will be triggered when an item changes width. - if (d.updateLayoutGuard) - return - - var leftHandle, leftItem, rightItem, rightHandle - var leftEdge, rightEdge, newWidth, leftStopX, rightStopX - var i - - if (d.expandingIndex > handleIndex) { - // Resize item to the left. - // Ensure that the handle is not crossing other handles. So - // find the first visible handle to the left to determine the left edge: - leftEdge = 0 - for (i=handleIndex-1; i>=0; --i) { - leftHandle = handles[i] - if (leftHandle.visible) { - leftEdge = leftHandle[d.offset] + leftHandle[d.size] - break; - } - } - - // Ensure: leftStopX >= myHandle[d.offset] >= rightStopX - var min = d.accumulatedSize(handleIndex+1, items.length, true) - rightStopX = root[d.size] - min - myHandle[d.size] - leftStopX = Math.max(leftEdge, myHandle[d.offset]) - myHandle[d.offset] = Math.min(rightStopX, Math.max(leftStopX, myHandle[d.offset])) - - newWidth = myHandle[d.offset] - leftEdge - leftItem = items[handleIndex] - if (root[d.size] != 0 && leftItem.Splitter.percentageSize !== -1) - leftItem.Splitter.percentageSize = newWidth * (100 / root[d.size]) - // The next line will trigger 'updateLayout' inside 'propertyChangeListener': - leftItem[d.size] = newWidth - } else { - // Resize item to the right. - // Ensure that the handle is not crossing other handles. So - // find the first visible handle to the right to determine the right edge: - rightEdge = root[d.size] - for (i=handleIndex+1; i<handles.length; ++i) { - rightHandle = handles[i] - if (rightHandle.visible) { - rightEdge = rightHandle[d.offset] - break; - } - } - - // Ensure: leftStopX <= myHandle[d.offset] <= rightStopX - var min = d.accumulatedSize(0, handleIndex+1, true) - leftStopX = min - myHandle[d.size] - rightStopX = Math.min((rightEdge - myHandle[d.size]), myHandle[d.offset]) - myHandle[d.offset] = Math.max(leftStopX, Math.min(myHandle[d.offset], rightStopX)) - - newWidth = rightEdge - (myHandle[d.offset] + myHandle[d.size]) - rightItem = items[handleIndex+1] - if (root[d.size] !== 0 && rightItem[d.percentageSize] !== -1) - rightItem.Splitter.percentageSize = newWidth * (100 / root[d.size]) - // The next line will trigger 'updateLayout' inside 'propertyChangeListener': - rightItem[d.size] = newWidth - } - } - } - } - - Item { - id: splitterItems - anchors.fill: parent - } - Item { - id: splitterHandles - anchors.fill: parent - } - - Component { - // This dummy item becomes a child of all - // items it the splitter, just to provide a way - // to listen for changes to their width, expanding etc. - id: propertyChangeListener - Item { - id: target - width: (d.horizontal ? parent[d.size] : 0) - height: (!d.horizontal ? parent[d.size] : 0) - property bool expanding: parent.Splitter.expanding - property real percentageSize: parent.Splitter.percentageSize - property real minimumWidth: parent.Splitter[d.minimum] - property real maximumSize: parent.Splitter[d.maximum] - property int itemIndex: parent.Splitter.itemIndex - - onPercentageSizeChanged: d.updateLayout(); - onMinimumWidthChanged: d.updateLayout(); - onMaximumSizeChanged: d.updateLayout(); - onExpandingChanged: updateExpandingIndex() - - function updateExpandingIndex() - { - // The following code is needed to avoid a binding - // loop, since we might change 'expanding' again to a different item: - if (d.itemExpandingGuard === true) - return - d.itemExpandingGuard = true - // break binding: - expanding = false - - // 'expanding' follows radio button behavior: - // First, find the new expanding item: - var newIndex = items.length-1 - for (var i=0; i<items.length; ++i) { - var item = items[i] - if (i !== d.expandingIndex && item.Splitter.expanding === true && item.visible === true) { - newIndex = i - break - } - } - item = items[newIndex] - if (item.visible === false) { - // So now we ended up with the last item in the splitter to be - // expanding, but it turns out to not be visible. So we need to - // traverse backwards again to find one that is visible... - for (i=items.length-2; i>=0; --i) { - var item = items[i] - if (item.visible === true) { - newIndex = i - item = items[newIndex] - break - } - } - } - - // Tell the found item that it is expanding: - if (item.Splitter.expanding !== true) - item.Splitter.expanding = true - // ...and the old one that it is not: - if (newIndex !== d.expandingIndex) { - item = items[d.expandingIndex] - if (item.Splitter.expanding !== false) - item.Splitter.expanding = false - } - // update index: - d.expandingIndex = newIndex - d.updateLayout(); - // recreate binding: - expanding = Qt.binding(function() { return parent.Splitter.expanding }) - d.itemExpandingGuard = false - } - - function handleSizeChanged() { - // We need to update the layout. - // The following code is needed to avoid a binding - // loop, since we might change 'width' again to a different value: - if (d.itemWidthGuard === true) - return - d.itemWidthGuard = true - // Break binding: - if (d.horizontal) { - width = 0 - } else { - height = 0 - } - - d.updateLayout() - - // Restablish binding: - if (d.horizontal) { - width = Qt.binding(function() { return parent[d.size]; }) - } else { - height = Qt.binding(function() { return parent[d.size]; }) - } - d.itemWidthGuard = false - } - - onWidthChanged: handleSizeChanged() - onHeightChanged: handleSizeChanged() - onVisibleChanged: { - // Hiding the expanding item forces us to - // select a new one (and therefore not recommended): - if (d.expandingIndex === itemIndex) { - updateExpandingIndex() - } else { - if (visible) { - // Try to keep all items within the SplitterRow. When an item - // has been hidden, the expanding item might no longer be large enough - // to give away space to the new items width. So we need to resize: - var overflow = d.accumulatedSize(0, items.length, true) - root[d.size]; - if (overflow > 0) - parent[d.size] -= overflow - } - d.updateLayout() - } - } - } - } -} |