2 * Copyright (C) 2014 Canonical, Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 import Ubuntu.Components 1.3
19 import "../Components"
21 /*! \brief Zoomable for image.
23 This widget shows image contained in source,
24 can be zoomable accordingly with zoomable.
29 property alias source: imageRenderer.source
30 property var zoomable: false
31 property alias imageStatus: imageRenderer.status
32 property alias asynchronous: imageRenderer.asynchronous
33 readonly property alias status: imageRenderer.status
37 objectName: "flickable"
38 clip: true // FIXME maybe we can remove this, or just not clip in few cases
39 contentHeight: imageContainer.height
40 contentWidth: imageContainer.width
42 onHeightChanged: image.resetScale()
43 onWidthChanged: image.resetScale()
48 objectName: "imageContainer"
49 width: Math.max(image.width * image.scale, flickable.width)
50 height: Math.max(image.height * image.scale, flickable.height)
55 property alias imageStatus: imageRenderer.status
56 property var prevScale
57 anchors.centerIn: parent
63 objectName: "imageRenderer"
64 smooth: !flickable.movingVertically
66 fillMode: Image.PreserveAspectFit
68 readonly property int sourceSizeMultiplier: 3
70 sourceSize.width: root.width * sourceSizeMultiplier <= root.height * sourceSizeMultiplier ? root.width * sourceSizeMultiplier : 0
71 sourceSize.height: root.height * sourceSizeMultiplier <= root.width * sourceSizeMultiplier ? root.height * sourceSizeMultiplier : 0
74 if (status === Image.Ready) {
75 image.imageReloaded();
81 image.height = imageRenderer.implicitHeight
82 image.width = imageRenderer.implicitWidth
86 function resetScale() {
87 image.scale = Math.min(flickable.width / image.width, flickable.height / image.height);
88 pinchArea.minScale = image.scale;
89 prevScale = Math.min(image.scale, 1);
93 var currentWidth = width * scale
94 var currentHeight = height * scale
95 var scaleRatio = scale / prevScale
96 if (currentWidth > flickable.width) {
97 var xpos = flickable.width / 2 + flickable.contentX;
98 var xoff = xpos * scaleRatio;
99 flickable.contentX = xoff - flickable.width / 2;
101 if (currentHeight > flickable.height) {
102 var ypos = flickable.height / 2 + flickable.contentY;
103 var yoff = ypos * scaleRatio;
104 flickable.contentY = yoff - flickable.height / 2;
113 objectName: "pinchArea"
114 property real minScale: 1.0
116 enabled: zoomable ? zoomable : false
119 pinch.minimumScale: minScale
120 pinch.maximumScale: 10
122 onPinchFinished: flickable.returnToBounds()
127 objectName: "mouseArea"
130 enabled: zoomable ? zoomable : false
133 var startScale = image.scale;
134 if (wheel.angleDelta.y > 0) {
135 image.scale = startScale + 0.1;
136 } else if (wheel.angleDelta.y < 0) {
137 if (image.scale > 0.1 && image.scale > pinchArea.minScale) {
138 image.scale = startScale - 0.1;
141 wheel.accepted = true;
145 mouse.accepted = false;
149 mouse.accepted = false;
153 mouse.accepted = false;