2import Dekko.Controls 1.0
9 property var stackView: [];
22 if (stackView.length === 0)
24 var p = stackView.pop()
31 if (stackView.length === 0)
33 return stackView[stackView.length-1]
41 readonly
property alias depth: root.__depth
47 readonly
property alias currentItem: root.__currentItem
63 property var initialItem: null
67 readonly
property bool busy: __currentTransition !== null
121 function push(item) {
125 if (__recursionGuard(
true))
127 var properties = arguments[1]
128 var immediate = arguments[2]
129 var replace = arguments[3]
130 var arrayPushed = (item instanceof Array)
131 var firstItem = arrayPushed ? item[0] : item
132 immediate = (immediate || jsArray.stackView.length === 0)
134 if (firstItem && firstItem.item && firstItem.hasOwnProperty(
"x") === false) {
136 immediate = immediate || firstItem.immediate
137 replace = replace || firstItem.replace
144 if (item.length === 0)
146 var outElement = replace ? jsArray.pop() : jsArray.current()
147 for (var i=0; i<item.length; ++i)
148 jsArray.push({itemComponent:item[i], loaded: false, index: __depth, properties: properties});
150 outElement = replace ? jsArray.pop() : jsArray.current()
151 jsArray.push({itemComponent:item, loaded:
false, index: __depth, properties: properties})
154 var currentElement = jsArray.current()
156 inElement: currentElement,
157 outElement: outElement,
158 immediate: immediate,
162 __performTransition(transition)
163 __recursionGuard(
false)
197 if (item && item.hasOwnProperty(
"x") ===
false) {
199 var immediate = (item.immediate ===
true)
202 immediate = (arguments[1] ===
true)
205 if (item === __currentItem)
208 if (__recursionGuard(
true))
211 var outElement = jsArray.pop()
212 var inElement = jsArray.current()
214 if (__depth > 1 && item !== undefined && item !== inElement.item) {
218 while (__depth > 1 && !jsArray.current().loaded)
220 inElement = jsArray.current()
221 while (__depth > 1 && item !== inElement.item) {
224 while (__depth > 1 && !jsArray.current().loaded)
226 inElement = jsArray.current()
231 inElement: inElement,
232 outElement: outElement,
233 immediate: immediate,
237 __performTransition(transition)
238 __recursionGuard(
false)
239 return outElement.item;
245 if (__recursionGuard(
true))
247 if (__currentTransition)
248 __currentTransition.animation.complete()
251 for (var i=0; i<count; ++i) {
252 var element = jsArray.pop()
256 __recursionGuard(
false)
267 function find(func, onlySearchLoadedItems) {
268 for (var i=__depth-1; i>=0; --i) {
269 var element = jsArray.stackView[i];
270 if (onlySearchLoadedItems !==
true)
271 __loadElement(element)
272 else if (!element.item)
274 if (func(element.item))
285 function get(index, dontLoad)
287 if (index < 0 || index >= jsArray.stackView.length)
289 var element = jsArray.stackView[index]
290 if (dontLoad !==
true) {
291 __loadElement(element)
293 }
else if (element.item) {
304 function completeTransition()
306 if (__recursionGuard(
true))
308 if (__currentTransition)
309 __currentTransition.animation.complete()
310 __recursionGuard(
false)
317 function replace(item, properties, immediate) {
318 push(item, properties, immediate,
true)
324 property Item __currentItem: null
326 property int __depth: 0
328 property var __currentTransition: null
330 property bool __guard:
false
332 Component.onCompleted: {
337 Component.onDestruction: {
338 if (__currentTransition)
339 __currentTransition.animation.complete()
344 function __recursionGuard(use)
346 if (use && __guard) {
347 console.warn(
"Warning: StackView: You cannot push/pop recursively!")
355 function __loadElement(element)
357 if (element.loaded) {
359 element.item = invalidItemReplacement.createObject(root)
360 element.item.text =
"\nError: The item has been deleted outside StackView!"
364 if (!element.itemComponent) {
365 element.item = invalidItemReplacement.createObject(root)
366 element.item.text =
"\nError: Invalid item (item was 'null'). "
367 +
"This might indicate that the item was deleted outside StackView!"
371 var comp = __resolveComponent(element.itemComponent, element)
374 if (!element.properties)
375 element.properties = {}
377 if (comp.hasOwnProperty(
"createObject")) {
378 if (comp.status === Component.Error) {
379 element.item = invalidItemReplacement.createObject(root)
380 element.item.text =
"\nError: Could not load: " + comp.errorString()
382 element.item = comp.createObject(root, element.properties)
384 if (!element.hasOwnProperty(
"destroyOnPop"))
385 element.destroyOnPop =
true
390 element.originalParent = parent
391 element.item.parent = root
392 for (var prop in element.properties) {
393 if (element.item.hasOwnProperty(prop))
394 element.item[prop] = element.properties[prop];
397 if (!element.hasOwnProperty(
"destroyOnPop"))
398 element.destroyOnPop =
false
401 element.item.Stack.__index = element.index
402 element.item.Stack.__view = root
404 element.item.width = Qt.binding(function() {
return root.width })
405 element.item.height = Qt.binding(function() {
return root.height })
406 element.loaded =
true
410 function __resolveComponent(unknownObjectType, element)
415 if (unknownObjectType.hasOwnProperty(
"createObject")) {
416 return unknownObjectType
417 }
else if (typeof unknownObjectType ==
"string") {
418 return Qt.createComponent(unknownObjectType)
419 }
else if (unknownObjectType.hasOwnProperty(
"x")) {
420 return unknownObjectType
421 }
else if (unknownObjectType.hasOwnProperty(
"item")) {
423 element.properties = unknownObjectType.properties
424 if (!unknownObjectType.item)
425 unknownObjectType.item = invalidItemReplacement
426 if (unknownObjectType.hasOwnProperty(
"destroyOnPop"))
427 element.destroyOnPop = unknownObjectType.destroyOnPop
428 return __resolveComponent(unknownObjectType.item, element)
431 return Qt.createComponent(unknownObjectType)
436 function __cleanup(element) {
439 var item = element.item
440 if (element.destroyOnPop) {
441 console.log(
"Destroying item: ", item)
448 __setStatus(item, Stack.Inactive)
449 item.Stack.__view = null
450 item.Stack.__index = -1
451 if (element.originalParent)
452 item.parent = element.originalParent
457 function __setStatus(item, status) {
458 item.Stack.__status = status
462 function __performTransition(transition)
468 if (__currentTransition)
469 __currentTransition.animation.complete()
470 __loadElement(transition.inElement)
472 transition.name = transition.replace ? "replaceTransition" : (transition.push ? "pushTransition" : "popTransition")
473 var enterItem = transition.inElement.item
474 transition.enterItem = enterItem
477 enterItem.parent = root
478 enterItem.Stack.__view = root
479 enterItem.Stack.__index = transition.inElement.index
480 __currentItem = enterItem
482 if (!transition.outElement) {
484 enterItem.visible =
true
485 __setStatus(enterItem, Stack.Activating)
486 __setStatus(enterItem, Stack.Active)
490 var exitItem = transition.outElement.item
491 transition.exitItem = exitItem
492 if (enterItem === exitItem)
496 transition.properties = {
497 "name":transition.name,
498 "enterItem":transition.enterItem,
499 "exitItem":transition.exitItem,
500 "immediate":transition.immediate }
501 var anim = root.delegate.getTransition(transition.properties)
502 if (anim.createObject) {
503 anim = anim.createObject(null, transition.properties)
504 anim.runningChanged.connect(function(){
if (anim.running ===
false) anim.destroy() })
506 transition.animation = anim
509 if (!transition.animation) {
510 console.warn(
"Warning: StackView: no", transition.name,
"found!")
513 if (enterItem.anchors.fill || exitItem.anchors.fill)
514 console.warn(
"Warning: StackView: cannot transition an item that is anchored!")
516 __currentTransition = transition
517 __setStatus(exitItem, Stack.Deactivating)
518 enterItem.visible = true
519 __setStatus(enterItem, Stack.Activating)
520 transition.animation.runningChanged.connect(animationFinished)
521 transition.animation.start()
524 if (transition.immediate === true && transition.animation)
525 transition.animation.complete()
529 function animationFinished()
531 if (!__currentTransition || __currentTransition.animation.running)
534 __currentTransition.animation.runningChanged.disconnect(animationFinished)
535 __currentTransition.exitItem.visible =
false
536 __setStatus(__currentTransition.exitItem, Stack.Inactive);
537 __setStatus(__currentTransition.enterItem, Stack.Active);
538 __currentTransition.properties.animation = __currentTransition.animation
539 root.delegate.transitionFinished(__currentTransition.properties)
541 if (!__currentTransition.push || __currentTransition.replace)
542 __cleanup(__currentTransition.outElement)
544 __currentTransition = null
548 property Component invalidItemReplacement: Component {
551 height: parent.height
552 wrapMode: Text.WrapAtWordBoundaryOrAnywhere