From 1315f9d97170d7f1bb8ef28ab95e0fafc3e72b68 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sat, 28 Mar 2015 21:51:10 +0100 Subject: Implement StackView in C++ Change-Id: Ia5387aa16325453c676a2542f80c827d4c069ca9 Reviewed-by: J-P Nurmi --- src/imports/controls/StackView.js | 63 -- src/imports/controls/StackView.qml | 914 +-------------------------- src/imports/controls/StackViewDelegate.qml | 142 ----- src/imports/controls/StackViewTransition.qml | 56 -- src/imports/controls/controls.pro | 3 - src/imports/controls/qmldir | 2 - 6 files changed, 9 insertions(+), 1171 deletions(-) delete mode 100644 src/imports/controls/StackView.js delete mode 100644 src/imports/controls/StackViewDelegate.qml delete mode 100644 src/imports/controls/StackViewTransition.qml (limited to 'src/imports/controls') diff --git a/src/imports/controls/StackView.js b/src/imports/controls/StackView.js deleted file mode 100644 index 37e2066d..00000000 --- a/src/imports/controls/StackView.js +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Controls module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -var stackView = []; - -function push(p) -{ - if (!p) - return - stackView.push(p) - __depth++ - return p -} - -function pop() -{ - if (stackView.length === 0) - return null - var p = stackView.pop() - __depth-- - return p -} - -function current() -{ - if (stackView.length === 0) - return null - return stackView[stackView.length-1] -} - diff --git a/src/imports/controls/StackView.qml b/src/imports/controls/StackView.qml index 2c75f063..396778b7 100644 --- a/src/imports/controls/StackView.qml +++ b/src/imports/controls/StackView.qml @@ -34,921 +34,25 @@ ** ****************************************************************************/ -import QtQuick 2.2 +import QtQuick 2.4 import QtQuick.Controls 2.0 -import "StackView.js" as JSArray - -/*! - \qmltype StackView - \inherits Item - \ingroup views - \inqmlmodule QtQuick.Controls - \since 5.1 - - \brief Provides a stack-based navigation model. - - \image stackview.png - - StackView implements a stack-based navigation model, which can be used - with a set of interlinked information pages. Items are pushed onto the stack - as the user navigates deeper into the material, and popped off again when he - chooses to go back. - - The \l{Qt Quick Controls - Touch Gallery}{touch gallery} example is a good - starting point to understand how StackView works. The following snippet - from the example shows how it can be used: - - \qml - StackView { - id: stack - initialItem: view - - Component { - id: view - - MouseArea { - Text { - text: stack.depth - anchors.centerIn: parent - } - onClicked: stack.push(view) - } - } - } - \endqml - - \section1 Using StackView in an Application - Using the StackView in the application is typically a simple matter of adding - the StackView as a child of a Window. The stack is usually anchored to the - edges of the window, except at the top or bottom where it might be anchored - to a status bar, or some other similar UI component. The stack can then be - used by invoking its navigation methods. The first item to show in the StackView - is commonly loaded assigning it to \l initialItem. - - \note Items pushed onto the stack view have \l{Supported Attached Properties}{Stack attached properties}. - - \section1 Basic Navigation - There are three primary navigation operations in StackView: push(), pop(), and - replace (replace by specifying argument \c replace to push()). - These correspond to classic stack operations where "push" adds an item to the - top of a stack, "pop" removes the top item from the stack, and "replace" is like a - pop followed by a push in that it replaces the topmost item on the stack with - a new item (but the applied transtition might be different). The topmost item - in the stack corresponds to the one that is \l{StackView::currentItem} {currently} - visible on the screen. That means that "push" is the logical equivalent of navigating - forward or deeper into the application, "pop" is the equivalent of navigating back, - and "replace" is the equivalent of replacing the current item. - - Sometimes it is necessary to go back more than a single step in the stack, for - example, to return to a "main" item or some kind of section item in the application. - For this use case, it is possible to specify an item as a parameter for pop(). - This is called an "unwind" operation as the stack gets unwound to the specified item. - If the item is not found then the stack unwinds until there is only a single item in - the stack, which becomes the current item. To explicitly unwind to the bottom - of the stack it is recommended to use \l{pop()} {pop(null)}, though technically any - non-existent item will do. - - Given the stack [A, B, C]: - - \list - \li \l{push()}{push(D)} => [A, B, C, D] - "push" transition animation between C and D - \li pop() => [A, B] - "pop" transition animation between C and B - \li \l{push()}{push(D, replace)} => [A, B, D] - "replace" transition between C and D - \li \l{pop()}{pop(A)} => [A] - "pop" transition between C and A - \endlist - - \note Note that when the stack is empty, a push() will not perform a - transition animation because there is nothing to transition from (typically during - application start-up). A pop() on a stack with depth 1 or 0 is a no-operation. - If removing all items from the stack is needed, a separate function clear() is - available. - - Calling push() returns the item that was pushed onto the stack. - Calling pop() returns the item that was popped off the stack. When pop() is - called in an unwind operation the top-most item (the first item that was - popped, which will also be the one transitioning out) is returned. - - \section1 Deep Linking - \e{Deep linking} means launching an application into a particular state. For example, - a newspaper application could be launched into showing a particular article, - bypassing the front item (and possibly a section item) that would normally have - to be navigated through to get to the article concerned. In terms of StackView, deep - linking means the ability to modify the state of the stack, so much so that it is - possible to push a set of items to the top of the stack, or to completely reset - the stack to a given state. - - The API for deep linking in StackView is the same as for basic navigation. Pushing - an array instead of a single item, will involve that all the items in that array will - be pushed onto the stack. The transition animation, however, will be conducted as - if only the last item in the array was pushed onto the stack. The normal semantics - of push() apply for deep linking, meaning that push() adds whatever is pushed onto - the stack. Note also that only the last item of the array will be loaded. - The rest will be lazy-loaded as needed when entering the screen upon subsequent - calls to pop (or when requesting the item by using \a get). - - This gives us the following result, given the stack [A, B, C]: - - \list - \li \l{push()}{push([D, E, F])} => [A, B, C, D, E, F] - "push" transition animation between C and F - \li \l{push()}{push([D, E, F], replace)} => [A, B, D, E, F] - "replace" transition animation between C and F - \li clear(); \l{push()}{push([D, E, F])} => [D, E, F] - no transition animation (since the stack was empty) - \endlist - - \section1 Pushing items - - An item pushed onto the StackView can be either an Item, a URL, a string - with a URL, or a Component. To push it, assign it to a property "item" - inside a property list, and send it as an argument to \l{StackView::push}{push}: - - \code - stackView.push({item: yourItem}) - \endcode - - The list can contain several properties that control how the item should be pushed: - \list - \li \c item: this property is required, and holds the item to be pushed. - \li \c properties: a list of QML properties to be assigned to the item upon push. These - properties will be copied into the item at load time, or when the item will become - the current item (normally upon push). - \li \c immediate: set this property to \c true to skip transition effects. When pushing - an array, this property only needs to be set on the first element to make the - whole operation immediate. - \li \c replace: set this property to replace the current item on the stack. When pushing - an array, you only need to set this property on the first element to replace - as many elements on the stack as inside the array. - \li \c destroyOnPop: set this boolean to true if StackView needs to destroy the item when - it is popped off the stack. By default (if \a destroyOnPop is not specified), StackView - will destroy items pushed as components or URLs. Items not destroyed will be re-parented - back to the original parents they had before being pushed onto the stack and hidden. - If you need to set this property, do it with care, so that items are not leaked. - \endlist - - If the only argument needed is "item", the following short-hand notation can be applied: - - \code - stackView.push(yourItem) - \endcode - - You can push several items in one go by using an array of property lists. This is - optimizing compared to pushing items one by one, since StackView then can load only the - last item in the list. The rest will be loaded as they are about to become - the current item (which happens when the stack is popped). The following example shows how - to push an array of items: - - \code - stackView.push([{item: yourItem1}, {item: yourItem2}]) - \endcode - - If an inline item is pushed, the item is temporarily re-parented into the StackView. When the item - is later popped off, it gets re-parented back to its original owner again. - If, however, an item is pushed as a component or a URL, the actual item will be created as an - item from that component. This happens automatically when the item is about to become the current - item in the stack. Ownership of the item will then normally be taken by the StackView. It will as - such automatically destroy the item when it is later popped off. The component that declared the item, by - contrast, remains in the ownership of the application and is not destroyed by the stack. - This can be overridden by explicitly setting \c{destroyOnPop} in the list of arguments given to push. - - If the \c properties to be pushed are specified, they will be copied into the item at loading time - (in case of a component or URL), or when the item will become the current item (in case of an inline - item). The following example shows how this can be done: - - \code - stackView.push({item: someItem, properties: {fgcolor: "red", bgcolor: "blue"}}) - \endcode - - - \note Note that if an item is declared inside another item, and if that parent gets destroyed, - (even if a component was used), that child item will also be destroyed. - This follows normal Qt parent-child destruction rules, but sometimes comes as a surprise - for developers. - - \section1 Lifecycle - An item's lifecycle in the StackView can have the following transitions: - \list 1 - \li instantiation - \li inactive - \li activating - \li active - \li deactivating - \li inactive - \li destruction - \endlist - - It can move any number of times between inactive and active. When an item is activated, - it's visible on the screen and is considered to be the current item. An item - in a StackView that is not visible is not activated, even if the item is currently the - top-most item in the stack. When the stack becomes visible, the item that is top-most gets - activated. Likewise if the stack is then hidden, the topmost item would be deactivated. - Popping the item off the top of the stack at this point would not result in further - deactivation since the item is not active. - - There is an attached \l{Stack::status}{Stack.status} property that tracks the lifecycle. The - status values list is an enumeration with values \c Stack.Inactive, \c Stack.Activating, - \c Stack.Active and \c Stack.Deactivating. Combined with the normal \c Component.onComplete and - \c Component.onDestruction signals the entire lifecycle is thus: - - \list - \li Created: Component.onCompleted() - \li Activating: Stack.onStatusChanged (Stack.status is Stack.Activating) - \li Acivated: Stack.onStatusChanged (Stack.status is Stack.Active) - \li Deactivating: Stack.onStatusChanged (Stack.status is Stack.Deactivating) - \li Deactivated: Stack.onStatusChanged (Stack.status is Stack.Inactive) - \li Destruction: Component.onDestruction() - \endlist - - \section1 Finding items - Sometimes it is necessary to search for an item, for example, in order to unwind the stack to - an item to which the application does not have a reference. This is facilitated using a - function find() in StackView. The find() function takes a callback function as its - only argument. The callback gets invoked for each item in the stack (starting at the top). - If the callback returns true, then it signals that a match has been found and the find() - function returns that item. If the callback fails to return true (no match is found), - then find() returns \c null. - - The code below searches for an item in the stack that has a name "order_id" and then unwinds to - that item. Note that since find() returns \c {null} if no item is found, and since pop unwinds to - the bottom of the stack if null is given as the target item, the code works well even in - case no matching item is found. - - \code - stackView.pop(stackView.find(function(item) { - return item.name == "order_id"; - })); - \endcode - - You can also get to an item in the stack using \l {get()}{get(index)}. You should use - this function if your item depends on another item in the stack, as the function will - ensure that the item at the given index gets loaded before it is returned. - - \code - previousItem = stackView.get(myItem.Stack.index - 1)); - \endcode - - \section1 Transitions - - A transition is performed whenever a item is pushed or popped, and consists of - two items: enterItem and exitItem. The StackView itself will never move items - around, but instead delegate the job to an external animation set provided - by the style or the application developer. How items should visually enter and leave the stack - (and the geometry they should end up with) is therefore completely controlled from the outside. - - When the transition starts, the StackView will search for a transition that - matches the operation executed. There are three transitions to choose - from: pushTransition, popTransition, and replaceTransition. Each implements how - enterItem should animate in, and exitItem out. The transitions are - collected inside a StackViewDelegate object assigned to - \l {StackView::delegate}{delegate}. By default, popTransition and - replaceTransition will be the same as pushTransition, unless you set them - to something else. - - A simple fade transition could be implemented as: - - \qml - StackView { - delegate: StackViewDelegate { - function transitionFinished(properties) - { - properties.exitItem.opacity = 1 - } - - pushTransition: StackViewTransition { - PropertyAnimation { - target: enterItem - property: "opacity" - from: 0 - to: 1 - } - PropertyAnimation { - target: exitItem - property: "opacity" - from: 1 - to: 0 - } - } - } - } - \endqml - - PushTransition needs to inherit from StackViewTransition, which is a ParallelAnimation that - contains the properties \c enterItem and \c exitItem. You set the target of your - inner animations to those items. Since the same items instance can be pushed several - times to a StackView, you should always override - \l {StackViewDelegate::transitionFinished()}{StackViewDelegate.transitionFinished()}. - Implement this function to reset any properties animated on the exitItem so that later - transitions can expect the items to be in a default state. - - A more complex example could look like the following. Here, the items are lying on the side before - being rotated to an upright position: - - \qml - StackView { - delegate: StackViewDelegate { - function transitionFinished(properties) - { - properties.exitItem.x = 0 - properties.exitItem.rotation = 0 - } - - pushTransition: StackViewTransition { - SequentialAnimation { - ScriptAction { - script: enterItem.rotation = 90 - } - PropertyAnimation { - target: enterItem - property: "x" - from: enterItem.width - to: 0 - } - PropertyAnimation { - target: enterItem - property: "rotation" - from: 90 - to: 0 - } - } - PropertyAnimation { - target: exitItem - property: "x" - from: 0 - to: -exitItem.width - } - } - } - } - \endqml - - \section2 Advanced usage - - When the StackView needs a new transition, it first calls - \l {StackViewDelegate::getTransition()}{StackViewDelegate.getTransition()}. - The base implementation of this function just looks for a property named \c properties.name inside - itself (root), which is how it finds \c {property Component pushTransition} in the examples above. - - \code - function getTransition(properties) - { - return root[properties.name] - } - \endcode - - You can override this function for your delegate if you need extra logic to decide which - transition to return. You could for example introspect the items, and return different animations - depending on the their internal state. StackView will expect you to return a Component that - contains a StackViewTransition, or a StackViewTransition directly. The former is easier, as StackView will - then create the transition and later destroy it when it's done, while avoiding any sideeffects - caused by the transition being alive long after it has run. Returning a StackViewTransition directly - can be useful if you need to write some sort of transition caching for performance reasons. - As an optimization, you can also return \c null to signal that you just want to show/hide the items - immediately without creating or running any transitions. You can also override this function if - you need to alter the items in any way before the transition starts. - - \c properties contains the properties that will be assigned to the StackViewTransition before - it runs. In fact, you can add more properties to this object during the call - if you need to initialize additional properties of your custom StackViewTransition when the returned - component is instantiated. - - The following example shows how you can decide which animation to use during runtime : - - \qml - StackViewDelegate { - function getTransition(properties) - { - return (properties.enterItem.Stack.index % 2) ? horizontalTransition : verticalTransition - } - - function transitionFinished(properties) - { - properties.exitItem.x = 0 - properties.exitItem.y = 0 - } - - property Component horizontalTransition: StackViewTransition { - PropertyAnimation { - target: enterItem - property: "x" - from: target.width - to: 0 - duration: 300 - } - PropertyAnimation { - target: exitItem - property: "x" - from: 0 - to: target.width - duration: 300 - } - } - - property Component verticalTransition: StackViewTransition { - PropertyAnimation { - target: enterItem - property: "y" - from: target.height - to: 0 - duration: 300 - } - PropertyAnimation { - target: exitItem - property: "y" - from: 0 - to: target.height - duration: 300 - } - } - } - \endqml - - \section1 Supported Attached Properties - - Items in a StackView support these attached properties: - \list - \li \l{Stack::index}{Stack.index} - Contains the index of the item inside the StackView - \li \l{Stack::view}{Stack.view} - Contains the StackView the item is in - \li \l{Stack::status}{Stack.status} - Contains the status of the item - \endlist -*/ AbstractStackView { id: root - depth: root.__depth - currentItem: root.__currentItem - initialItem: null - busy: __currentTransition !== null - - /*! The transitions to use when pushing or popping items. - For better understanding on how to apply custom transitions, read \l{Transitions}. - \sa {Stack::transitions}{Stack.transitions} */ - property StackViewDelegate delegate: StackViewDelegate {} - - /*! Pushes an item onto the stack. The function takes a property list as argument, which - should contain one or more of the following properties: - \list - \li \c item: this property is required, and holds the item you want to push. - \li \c properties: a list of QML properties that should be assigned - to the item upon push. These properties will be copied into the item when it is - loaded (in case of a component or URL), or when it becomes the current item for the - first time (normally upon push). - \li \c immediate: set this property to \c true to skip transition effects. When pushing - an array, you only need to set this property on the first element to make the - whole operation immediate. - \li \c replace: set this property to replace the current item on the stack. When pushing - an array, you only need to set this property on the first element to replace - as many elements on the stack as inside the array. - \li \c destroyOnPop: set this property to specify if the item needs to be destroyed - when its popped off the stack. By default (if \a destroyOnPop is not specified), - StackView will destroy items pushed as components or URLs. Items - not destroyed will be re-parented to the original parents they had before being - pushed onto the stack, and hidden. If you need to set this property, do it with - care, so that items are not leaked. - \endlist - - You can also push an array of items (property lists) if you need to push several items - in one go. A transition will then only occur between the current item and the last - item in the list. Loading the other items will be deferred until needed. - - Examples: - \list - \li stackView.push({item:anItem}) - \li stackView.push({item:aURL, immediate: true, replace: true}) - \li stackView.push({item:aRectangle, properties:{color:"red"}}) - \li stackView.push({item:aComponent, properties:{color:"red"}}) - \li stackView.push({item:aComponent.createObject(), destroyOnPop:true}) - \li stackView.push([{item:anitem, immediate:true}, {item:aURL}]) - \endlist - - \note Note: if the only argument needed is "item", you can apply the following short- - hand notation: \c{stackView.push(anItem)}. - - Returns the item that became current. - - \sa initialItem - \sa {Pushing items} - */ - function push(item) { - // Note: we support two different APIs in this function; The old meego API, and - // the new "property list" API. Hence the reason for hiding the fact that you - // can pass more arguments than shown in the signature: - if (__recursionGuard(true)) - return - var properties = arguments[1] - var immediate = arguments[2] - var replace = arguments[3] - var arrayPushed = (item instanceof Array) - var firstItem = arrayPushed ? item[0] : item - immediate = (immediate || JSArray.stackView.length === 0) - - if (firstItem && firstItem.item && firstItem.hasOwnProperty("x") === false) { - // Property list API used: - immediate = immediate || firstItem.immediate - replace = replace || firstItem.replace - } - - // Create, and push, a new javascript object, called "element", onto the stack. - // This element contains all the information necessary to construct the item, and - // will, after loaded, also contain the loaded item: - if (arrayPushed) { - if (item.length === 0) - return - var outElement = replace ? JSArray.pop() : JSArray.current() - for (var i=0; i 1 && item !== undefined && item !== inElement.item) { - // Pop from the top until we find 'item', and return the corresponding - // element. Skip all non-loaded items (except the first), since no one - // has any references to such items anyway: - while (__depth > 1 && !JSArray.current().loaded) - JSArray.pop() - inElement = JSArray.current() - while (__depth > 1 && item !== inElement.item) { - JSArray.pop() - __cleanup(inElement) - while (__depth > 1 && !JSArray.current().loaded) - JSArray.pop() - inElement = JSArray.current() - } - } - - var transition = { - inElement: inElement, - outElement: outElement, - immediate: immediate, - replace: false, - push: false - } - __performTransition(transition) - __recursionGuard(false) - return outElement.item; - } - - /*! Remove all items from the stack. No animations will be applied. */ - function clear() { - if (__recursionGuard(true)) - return - if (__currentTransition) - __currentTransition.animation.complete() - __currentItem = null - var count = __depth - for (var i=0; i=0; --i) { - var element = JSArray.stackView[i]; - if (onlySearchLoadedItems !== true) - __loadElement(element) - else if (!element.item) - continue - if (func(element.item, i)) - return element.item - } - return null; - } - - /*! Returns the item at position \a index in - the stack. If \a dontLoad is true, the - item will not be forced to load (and \c null - will be returned if not yet loaded) */ - function get(index, dontLoad) - { - if (index < 0 || index >= JSArray.stackView.length) - return null - var element = JSArray.stackView[index] - if (dontLoad !== true) { - __loadElement(element) - return element.item - } else if (element.item) { - return element.item - } else { - return null - } - } - - /*! Immediately completes any ongoing transition. - /sa Animation.complete - */ - function completeTransition() - { - if (__recursionGuard(true)) - return - if (__currentTransition) - __currentTransition.animation.complete() - __recursionGuard(false) - } - - /********* DEPRECATED API *********/ - - /*! \internal - \deprecated Use Push() instead */ - function replace(item, properties, immediate) { - push(item, properties, immediate, true) + popExit: Transition { + NumberAnimation { property: "x"; from: 0; to: root.width; duration: 400; easing.type: Easing.OutCubic } } - /********* PRIVATE API *********/ - - /*! \internal The currently top-most item on the stack. */ - property Item __currentItem: null - /*! \internal The number of items currently pushed onto the stack. */ - property int __depth: 0 - /*! \internal Stores the transition info while a transition is ongoing */ - property var __currentTransition: null - /*! \internal Stops the user from pushing items while preparing a transition */ - property bool __guard: false - - Component.onCompleted: { - if (initialItem) - push(initialItem) - } - - Component.onDestruction: { - if (__currentTransition) - __currentTransition.animation.complete() - __currentItem = null - } - - /*! \internal */ - function __recursionGuard(use) - { - if (use && __guard) { - console.warn("Warning: StackView: You cannot push/pop recursively!") - console.trace() - return true - } - __guard = use - } - - /*! \internal */ - function __loadElement(element) - { - if (element.loaded) { - if (!element.item) { - element.item = invalidItemReplacement.createObject(root) - element.item.text = "\nError: The item has been deleted outside StackView!" - } - return - } - if (!element.itemComponent) { - element.item = invalidItemReplacement.createObject(root) - element.item.text = "\nError: Invalid item (item was 'null'). " - + "This might indicate that the item was deleted outside StackView!" - return - } - - var comp = __resolveComponent(element.itemComponent, element) - - // Assign properties to item: - if (!element.properties) - element.properties = {} - - if (comp.hasOwnProperty("createObject")) { - if (comp.status === Component.Error) { - element.item = invalidItemReplacement.createObject(root) - element.item.text = "\nError: Could not load: " + comp.errorString() - } else { - element.item = comp.createObject(root, element.properties) - // Destroy items we create unless the user specified something else: - if (!element.hasOwnProperty("destroyOnPop")) - element.destroyOnPop = true - } - } else { - // comp is already an Item, so just re-parent it into the StackView: - element.item = comp - element.originalParent = parent - element.item.parent = root - for (var prop in element.properties) { - if (element.item.hasOwnProperty(prop)) - element.item[prop] = element.properties[prop]; - } - // Do not destroy items we didn't create, unless the user specified something else: - if (!element.hasOwnProperty("destroyOnPop")) - element.destroyOnPop = false - } - -//TODO element.item.Stack.__index = element.index -//TODO element.item.Stack.__view = root - // Let item fill all available space by default: - element.item.width = Qt.binding(function() { return root.width }) - element.item.height = Qt.binding(function() { return root.height }) - element.loaded = true - } - - /*! \internal */ - function __resolveComponent(unknownObjectType, element) - { - // We need this extra resolve function since we don't really - // know what kind of object the user pushed. So we try to - // figure it out by inspecting the object: - if (unknownObjectType.hasOwnProperty("createObject")) { - return unknownObjectType - } else if (typeof unknownObjectType == "string") { - return Qt.createComponent(unknownObjectType) - } else if (unknownObjectType.hasOwnProperty("x")) { - return unknownObjectType - } else if (unknownObjectType.hasOwnProperty("item")) { - // INVARIANT: user pushed a JS-object - element.properties = unknownObjectType.properties - if (!unknownObjectType.item) - unknownObjectType.item = invalidItemReplacement - if (unknownObjectType.hasOwnProperty("destroyOnPop")) - element.destroyOnPop = unknownObjectType.destroyOnPop - return __resolveComponent(unknownObjectType.item, element) - } else { - // We cannot determine the type, so assume its a URL: - return Qt.createComponent(unknownObjectType) - } - } - - /*! \internal */ - function __cleanup(element) { - // INVARIANT: element has been removed from JSArray. Destroy its - // item, or re-parent it back to the parent it had before it was pushed: - var item = element.item - if (element.destroyOnPop) { - item.destroy() - } else { - // Mark the item as no longer part of the StackView. It - // might reenter on pop if pushed several times: - item.visible = false - __setStatus(item, Stack.Inactive) -//TODO item.Stack.__view = null -//TODO item.Stack.__index = -1 - if (element.originalParent) - item.parent = element.originalParent - } - } - - /*! \internal */ - function __setStatus(item, status) { - item.Stack.status = status - } - - /*! \internal */ - function __performTransition(transition) - { - // Animate item in "outElement" out, and item in "inElement" in. Set a guard to protect - // the user from pushing new items on signals that will fire while preparing for the transition - // (e.g Stack.onCompleted, Stack.onStatusChanged, Stack.onIndexChanged etc). Otherwise, we will enter - // this function several times, which causes the items to be updated half-way. - if (__currentTransition) - __currentTransition.animation.complete() - __loadElement(transition.inElement) - - transition.name = transition.replace ? "replaceTransition" : (transition.push ? "pushTransition" : "popTransition") - var enterItem = transition.inElement.item - transition.enterItem = enterItem - - // Since an item can be pushed several times, we need to update its properties: - enterItem.parent = root -//TODO enterItem.Stack.__view = root -//TODO enterItem.Stack.__index = transition.inElement.index - __currentItem = enterItem - - if (!transition.outElement) { - // A transition consists of two items, but we got just one. So just show the item: - enterItem.visible = true - __setStatus(enterItem, Stack.Activating) - __setStatus(enterItem, Stack.Active) - return - } - - var exitItem = transition.outElement.item - transition.exitItem = exitItem - if (enterItem === exitItem) - return - - if (root.delegate) { - transition.properties = { - "name":transition.name, - "enterItem":transition.enterItem, - "exitItem":transition.exitItem, - "immediate":transition.immediate } - var anim = root.delegate.getTransition(transition.properties) - if (anim.createObject) { - anim = anim.createObject(null, transition.properties) - anim.runningChanged.connect(function(){ if (anim.running === false) anim.destroy() }) - } - transition.animation = anim - } - - if (!transition.animation) { - console.warn("Warning: StackView: no", transition.name, "found!") - return - } - if (enterItem.anchors.fill || exitItem.anchors.fill) - console.warn("Warning: StackView: cannot transition an item that is anchored!") - - __currentTransition = transition - __setStatus(exitItem, Stack.Deactivating) - enterItem.visible = true - __setStatus(enterItem, Stack.Activating) - transition.animation.runningChanged.connect(animationFinished) - transition.animation.start() - // NB! For empty animations, "animationFinished" is already - // executed at this point, leaving __animation === null: - if (transition.immediate === true && transition.animation) - transition.animation.complete() - } - - /*! \internal */ - function animationFinished() - { - if (!__currentTransition || __currentTransition.animation.running) - return - - __currentTransition.animation.runningChanged.disconnect(animationFinished) - __currentTransition.exitItem.visible = false - __setStatus(__currentTransition.exitItem, Stack.Inactive); - __setStatus(__currentTransition.enterItem, Stack.Active); - __currentTransition.properties.animation = __currentTransition.animation - root.delegate.transitionFinished(__currentTransition.properties) - - if (!__currentTransition.push || __currentTransition.replace) - __cleanup(__currentTransition.outElement) - - __currentTransition = null + pushEnter: Transition { + NumberAnimation { property: "x"; from: root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } - /*! \internal */ - property Component invalidItemReplacement: Component { - Text { - width: parent.width - height: parent.height - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - } + pushExit: Transition { + NumberAnimation { property: "x"; from: 0; to: -root.width; duration: 400; easing.type: Easing.OutCubic } } } diff --git a/src/imports/controls/StackViewDelegate.qml b/src/imports/controls/StackViewDelegate.qml deleted file mode 100644 index 2d4355bd..00000000 --- a/src/imports/controls/StackViewDelegate.qml +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Controls module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.2 - -/*! - \qmltype StackViewDelegate - \inqmlmodule QtQuick.Controls - \since 5.1 - - \brief A delegate used by StackView for loading transitions. - - See the documentation for the \l {StackView} component. - -*/ -QtObject { - id: root - - property bool horizontal: true - - function getTransition(properties) - { - return root[horizontal ? "horizontalSlide" : "verticalSlide"][properties.name] - } - - function transitionFinished(properties) - { - properties.exitItem.x = 0 - properties.exitItem.y = 0 - } - - property QtObject horizontalSlide: QtObject { - property Component pushTransition: StackViewTransition { - PropertyAnimation { - target: enterItem - property: "x" - from: target.width - to: 0 - duration: 400 - easing.type: Easing.OutCubic - } - PropertyAnimation { - target: exitItem - property: "x" - from: 0 - to: -target.width - duration: 400 - easing.type: Easing.OutCubic - } - } - - property Component popTransition: StackViewTransition { - PropertyAnimation { - target: enterItem - property: "x" - from: -target.width - to: 0 - duration: 400 - easing.type: Easing.OutCubic - } - PropertyAnimation { - target: exitItem - property: "x" - from: 0 - to: target.width - duration: 400 - easing.type: Easing.OutCubic - } - } - property Component replaceTransition: pushTransition - } - - property QtObject verticalSlide: QtObject { - property Component pushTransition: StackViewTransition { - PropertyAnimation { - target: enterItem - property: "y" - from: target.height - to: 0 - duration: 300 - } - PropertyAnimation { - target: exitItem - property: "y" - from: 0 - to: -target.height - duration: 300 - } - } - - property Component popTransition: StackViewTransition { - PropertyAnimation { - target: enterItem - property: "y" - from: -target.height - to: 0 - duration: 300 - } - PropertyAnimation { - target: exitItem - property: "y" - from: 0 - to: target.height - duration: 300 - } - property Component replaceTransition: pushTransition - } - } -} diff --git a/src/imports/controls/StackViewTransition.qml b/src/imports/controls/StackViewTransition.qml deleted file mode 100644 index f057791c..00000000 --- a/src/imports/controls/StackViewTransition.qml +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Controls module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.2 - -ParallelAnimation { - id: root - /*! The name of the animation that is running. Can be one of the following: - \list - \li 'PushTransition' - \li 'PopTransition' - \li 'ReplaceTransition' - \endlist - */ - property string name - /*! The page that is transitioning in. */ - property Item enterItem - /*! The page that is transitioning out */ - property Item exitItem - /*! Set to \c true if the transition is told to - fast-forward directly to its end-state */ - property bool immediate -} diff --git a/src/imports/controls/controls.pro b/src/imports/controls/controls.pro index 44e2a5e6..48c8cd48 100644 --- a/src/imports/controls/controls.pro +++ b/src/imports/controls/controls.pro @@ -22,10 +22,7 @@ QML_FILES = \ ScrollBar.qml \ ScrollIndicator.qml \ Slider.qml \ - StackView.js \ StackView.qml \ - StackViewDelegate.qml \ - StackViewTransition.qml \ Switch.qml \ TabBar.qml \ TabButton.qml \ diff --git a/src/imports/controls/qmldir b/src/imports/controls/qmldir index b54df22c..eaedbbb5 100644 --- a/src/imports/controls/qmldir +++ b/src/imports/controls/qmldir @@ -15,8 +15,6 @@ ScrollBar 2.0 ScrollBar.qml ScrollIndicator 2.0 ScrollIndicator.qml Slider 2.0 Slider.qml StackView 2.0 StackView.qml -StackViewDelegate 2.0 StackViewDelegate.qml -StackViewTransition 2.0 StackViewTransition.qml Switch 2.0 Switch.qml TabBar 2.0 TabBar.qml TabButton 2.0 TabButton.qml -- cgit v1.2.3