Warning, /graphics/kphotoalbum/AndroidRemoteControl/qml/Zoomable.qml is written in an unsupported language. File is not indexed.

0001 /* SPDX-FileCopyrightText: 2014 Jesper K. Pedersen <blackie@kde.org>
0002 
0003    SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 import QtQuick 2.0
0006 
0007 Item {
0008     id: root
0009 
0010     // Should the image be fitted on the screen intially (so all of the image can be seen), or should we use all the screen space instead?
0011     property bool fitOnScreen: false
0012     property alias sourceComponent : target.sourceComponent
0013     property bool isZoomedOut: flick.contentWidth <= initialWidth() && flick.contentHeight <= initialHeight()
0014 
0015     signal zoomStarted()
0016 
0017     readonly property bool inPortraitMode: width < height
0018 
0019     Flickable {
0020         id: flick
0021         anchors.fill: parent
0022 
0023         contentX: initialX()
0024         contentY: initialY()
0025         contentWidth: initialWidth()
0026         contentHeight: initialHeight()
0027         leftMargin: -initialX()
0028         topMargin: -initialY()
0029         interactive: !isZoomedOut
0030 
0031         Loader {
0032             id: target
0033             anchors.fill: flick.contentItem
0034 
0035             PinchArea {
0036                 id:pinchArea
0037                 width: Math.max(flick.contentWidth, flick.width)
0038                 height: Math.max(flick.contentHeight, flick.height)
0039 
0040                 property real initialZoomWidth
0041                 property real initialZoomHeight
0042 
0043                 onPinchStarted: {
0044                     initialZoomWidth = flick.contentWidth
0045                     initialZoomHeight = flick.contentHeight
0046 
0047                     flick.contentWidth = Qt.binding(function() {return flick.contentItem.width})
0048                     flick.contentHeight = Qt.binding(function() {return flick.contentItem.height})
0049 
0050                     // We need to disable the Flickable, otherwise it will move the item as soon as the first finger is released.
0051                     flick.interactive = false
0052                     root.zoomStarted()
0053                 }
0054 
0055                 onPinchUpdated: {
0056                     flick.contentX += pinch.previousCenter.x - pinch.center.x
0057                     flick.contentY += pinch.previousCenter.y - pinch.center.y
0058 
0059                     var width = initialZoomWidth * pinch.scale
0060                     var height = initialZoomHeight * pinch.scale
0061                     if (width < initialWidth())
0062                         width = initialWidth()
0063                     if (height < initialHeight())
0064                         height = initialHeight()
0065                     flick.resizeContent(width, height, pinch.center)
0066                 }
0067 
0068                 onPinchFinished: {
0069                     flick.interactive = Qt.binding(function() { return !isZoomedOut })
0070                     flick.returnToBounds()
0071                 }
0072 
0073 
0074                 MouseArea {
0075                     anchors.fill: parent
0076                     onDoubleClicked: returnToFullScreen()
0077                     propagateComposedEvents: true
0078                 }
0079             }
0080         }
0081     }
0082 
0083     function returnToFullScreen() {
0084         // If these were just assignments, the centering of the image would not work when the device was rotated.
0085         flick.contentWidth = Qt.binding(function() { return initialWidth() })
0086         flick.contentHeight = Qt.binding(function() { return initialHeight() })
0087         flick.contentX = Qt.binding( function() { return initialX() })
0088         flick.contentY = Qt.binding( function() { return initialY() })
0089         flick.leftMargin = Qt.binding(function() { return -initialX() })
0090         flick.topMargin = Qt.binding(function() { return -initialY() })
0091     }
0092 
0093     function aspect() {
0094         return  target.item.sourceSize.width / target.item.sourceSize.height
0095     }
0096 
0097     // Scale factor that will make the image fit on the screen
0098     function fitScale() {
0099         return Math.min(root.width/target.item.sourceSize.width, root.height/target.item.sourceSize.height)
0100     }
0101 
0102     function initialWidth() {
0103         if (root.fitOnScreen)
0104             return target.item.sourceSize.width * fitScale()
0105         else
0106             return inPortraitMode ? root.height * aspect() : root.width
0107     }
0108 
0109     function initialHeight() {
0110         if (root.fitOnScreen)
0111             return target.item.sourceSize.height * fitScale()
0112         else
0113             return inPortraitMode ? root.height : root.width / aspect()
0114     }
0115 
0116     function initialX() {
0117         return flick.contentWidth > root.width ? 0 : -(root.width-flick.contentWidth)/2
0118     }
0119 
0120     function initialY() {
0121         return flick.contentHeight > root.height ? 0 : -(root.height-flick.contentHeight)/2
0122     }
0123 }