~mutse-young/ubuntu-docviewer-app/trunk

« back to all changes in this revision

Viewing changes to src/app/qml/ZoomableImage.qml

  • Committer: Tarmac
  • Author(s): Stefano Verzegnassi
  • Date: 2014-11-29 12:22:51 UTC
  • mfrom: (39.2.3 ubuntu-docviewer-app)
  • Revision ID: tarmac-20141129122251-5lc2a70oz1qv31g2
Use ZoomableImage from Unity 8 to show images.

Approved by Riccardo Padovani, Ubuntu Phone Apps Jenkins Bot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2014 Canonical, Ltd.
 
3
 *
 
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.
 
7
 *
 
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.
 
12
 *
 
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/>.
 
15
 */
 
16
 
 
17
import QtQuick 2.0
 
18
import Ubuntu.Components 0.1
 
19
 
 
20
/*! \brief Zoomable for image.
 
21
 
 
22
    This widget shows image contained in source,
 
23
    can be zoomable accordingly with zoomable.
 
24
 */
 
25
 
 
26
Item {
 
27
    id: root
 
28
    property alias source: imageRenderer.source
 
29
    property var zoomable: false
 
30
    property alias imageStatus: imageRenderer.status
 
31
    property alias asynchronous: imageRenderer.asynchronous
 
32
 
 
33
    Flickable {
 
34
        id: flickable
 
35
        objectName: "flickable"
 
36
        clip: true // FIXME maybe we can remove this, or just not clip in few cases
 
37
        contentHeight: imageContainer.height
 
38
        contentWidth: imageContainer.width
 
39
 
 
40
        onHeightChanged: image.resetScale()
 
41
        onWidthChanged: image.resetScale()
 
42
        anchors.fill: parent
 
43
 
 
44
        Item {
 
45
            id: imageContainer
 
46
            objectName: "imageContainer"
 
47
            width: Math.max(image.width * image.scale, flickable.width)
 
48
            height: Math.max(image.height * image.scale, flickable.height)
 
49
 
 
50
            Item {
 
51
                id: image
 
52
                objectName: "image"
 
53
                property alias imageStatus: imageRenderer.status
 
54
                property var prevScale
 
55
                anchors.centerIn: parent
 
56
 
 
57
                signal imageReloaded
 
58
 
 
59
                Image {
 
60
                    id: imageRenderer
 
61
                    objectName: "imageRenderer"
 
62
                    smooth: !flickable.movingVertically
 
63
                    anchors.fill: parent
 
64
                    fillMode: Image.PreserveAspectFit
 
65
 
 
66
                    readonly property int sourceSizeMultiplier: 3
 
67
 
 
68
                    sourceSize.width: root.width * sourceSizeMultiplier <= root.height * sourceSizeMultiplier ? root.width * sourceSizeMultiplier : 0
 
69
                    sourceSize.height: root.height * sourceSizeMultiplier <= root.width * sourceSizeMultiplier ? root.height * sourceSizeMultiplier : 0
 
70
 
 
71
                    onStatusChanged: {
 
72
                        if (status === Image.Ready) {
 
73
                            image.imageReloaded();
 
74
                        }
 
75
                    }
 
76
                }
 
77
 
 
78
                onImageReloaded: {
 
79
                    image.height = imageRenderer.implicitHeight
 
80
                    image.width = imageRenderer.implicitWidth
 
81
                    image.resetScale();
 
82
                }
 
83
 
 
84
                function resetScale() {
 
85
                    image.scale = Math.min(flickable.width / image.width, flickable.height / image.height);
 
86
                    pinchArea.minScale = image.scale;
 
87
                    prevScale = Math.min(image.scale, 1);
 
88
                }
 
89
 
 
90
                onScaleChanged: {
 
91
                    var currentWidth = width * scale
 
92
                    var currentHeight = height * scale
 
93
                    var scaleRatio = scale / prevScale
 
94
                    if (currentWidth > flickable.width) {
 
95
                        var xpos = flickable.width / 2 + flickable.contentX;
 
96
                        var xoff = xpos * scaleRatio;
 
97
                        flickable.contentX = xoff - flickable.width / 2;
 
98
                    }
 
99
                    if (currentHeight > flickable.height) {
 
100
                        var ypos = flickable.height / 2 + flickable.contentY;
 
101
                        var yoff = ypos * scaleRatio;
 
102
                        flickable.contentY = yoff - flickable.height / 2;
 
103
                    }
 
104
                    prevScale = scale;
 
105
                }
 
106
            }
 
107
        }
 
108
 
 
109
        PinchArea {
 
110
            id: pinchArea
 
111
            objectName: "pinchArea"
 
112
            property real minScale: 1.0
 
113
            anchors.fill: parent
 
114
            enabled: zoomable ? zoomable : false
 
115
 
 
116
            pinch.target: image
 
117
            pinch.minimumScale: minScale
 
118
            pinch.maximumScale: 10
 
119
 
 
120
            onPinchFinished: flickable.returnToBounds()
 
121
        }
 
122
 
 
123
        MouseArea {
 
124
            id: mouseArea
 
125
            objectName: "mouseArea"
 
126
 
 
127
            anchors.fill: parent
 
128
            enabled: zoomable ? zoomable : false
 
129
 
 
130
            onWheel: {
 
131
                var startScale = image.scale;
 
132
                if (wheel.angleDelta.y > 0) {
 
133
                    image.scale = startScale + 0.1;
 
134
                } else if (wheel.angleDelta.y < 0) {
 
135
                    if (image.scale > 0.1 && image.scale > pinchArea.minScale) {
 
136
                        image.scale = startScale - 0.1;
 
137
                    }
 
138
                }
 
139
                wheel.accepted = true;
 
140
            }
 
141
 
 
142
            onPressed: {
 
143
                mouse.accepted = false;
 
144
            }
 
145
 
 
146
            onReleased: {
 
147
                mouse.accepted = false;
 
148
            }
 
149
 
 
150
            onClicked: {
 
151
                mouse.accepted = false;
 
152
            }
 
153
        }
 
154
    }
 
155
}