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 0.1
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
36 objectName: "flickable"
37 clip: true // FIXME maybe we can remove this, or just not clip in few cases
38 contentHeight: imageContainer.height
39 contentWidth: imageContainer.width
41 onHeightChanged: image.resetScale()
42 onWidthChanged: image.resetScale()
47 objectName: "imageContainer"
48 width: Math.max(image.width * image.scale, flickable.width)
49 height: Math.max(image.height * image.scale, flickable.height)
54 property alias imageStatus: imageRenderer.status
55 property var prevScale
56 anchors.centerIn: parent
62 objectName: "imageRenderer"
63 smooth: !flickable.movingVertically
65 fillMode: Image.PreserveAspectFit
67 readonly property int sourceSizeMultiplier: 3
69 sourceSize.width: root.width * sourceSizeMultiplier <= root.height * sourceSizeMultiplier ? root.width * sourceSizeMultiplier : 0
70 sourceSize.height: root.height * sourceSizeMultiplier <= root.width * sourceSizeMultiplier ? root.height * sourceSizeMultiplier : 0
73 if (status === Image.Ready) {
74 image.imageReloaded();
80 image.height = imageRenderer.implicitHeight
81 image.width = imageRenderer.implicitWidth
85 function resetScale() {
86 image.scale = Math.min(flickable.width / image.width, flickable.height / image.height);
87 pinchArea.minScale = image.scale;
88 prevScale = Math.min(image.scale, 1);
92 var currentWidth = width * scale
93 var currentHeight = height * scale
94 var scaleRatio = scale / prevScale
95 if (currentWidth > flickable.width) {
96 var xpos = flickable.width / 2 + flickable.contentX;
97 var xoff = xpos * scaleRatio;
98 flickable.contentX = xoff - flickable.width / 2;
100 if (currentHeight > flickable.height) {
101 var ypos = flickable.height / 2 + flickable.contentY;
102 var yoff = ypos * scaleRatio;
103 flickable.contentY = yoff - flickable.height / 2;
112 objectName: "mouseArea"
115 enabled: zoomable ? zoomable : false
118 var startScale = image.scale;
119 if (wheel.angleDelta.y > 0) {
120 image.scale = startScale + 0.1;
121 } else if (wheel.angleDelta.y < 0) {
122 if (image.scale > 0.1 && image.scale > pinchArea.minScale) {
123 image.scale = startScale - 0.1;
126 wheel.accepted = true;
130 mouse.accepted = false;
134 mouse.accepted = false;
138 mouse.accepted = false;
145 objectName: "pinchArea"
146 property real minScale: 1.0
147 anchors.fill: flickable
148 enabled: zoomable ? zoomable : false
151 pinch.minimumScale: minScale
152 pinch.maximumScale: 10
154 onPinchFinished: flickable.returnToBounds()