Moved FocusReticle to Camera instead of CameraPage.
[harmattan/cameraplus] / qml / FocusReticle.qml
1 // -*- qml -*-
2
3 /*!
4  * This file is part of CameraPlus.
5  *
6  * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 import QtQuick 1.1
24 import QtCamera 1.0
25 import CameraPlus 1.0
26
27 // TODO: I've seen the reticle color changing to red while dragging it but failed to reproduce :(
28 // TODO: animate move
29 // TODO: hide all controls when we are focusing
30 // TODO: hide all controls when we are dragging
31
32 MouseArea {
33         property int cafStatus: AutoFocus.None
34         property int status: AutoFocus.None
35         property Camera cam: null
36         id: mouse
37
38         // A 100x100 central "rectangle"
39         property variant centerRect: Qt.rect((mouse.width / 2 - 50), (mouse.height / 2) - 50, 100, 100);
40
41         property alias touchMode: reticle.touchMode
42
43         x: cam ? cam.renderArea.x : 0
44         y: cam ? cam.renderArea.y : 0
45         width: cam ? cam.renderArea.width : 0
46         height: cam ? cam.renderArea.height : 0
47
48         Connections {
49                 target: settings
50                 // Changing mode (which implies changing pages) will not reset ROI
51                 // thus we do it here
52                 onModeChanged: {
53                         moveToCenter();
54                         cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
55                 }
56         }
57
58         Connections {
59                 target: cam
60                 onRunningChanged: {
61                         if (!cam.running) {
62                                 moveToCenter();
63                                 cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
64                         }
65                 }
66         }
67 /*
68         // This is for debugging
69         Rectangle {
70                 color: "blue"
71                 opacity: 0.2
72                 anchors.fill: parent
73         }
74
75         Rectangle {
76                 color: "red"
77                 opacity: 0.4
78                 x: centerRect.x
79                 y: centerRect.y
80                 width: centerRect.width
81                 height: centerRect.height
82         }
83 */
84         drag.target: reticle
85         drag.axis: Drag.XandYAxis
86         drag.minimumX: 0 - (0.1 * reticle.width)
87         drag.minimumY: 0 - (0.1 * reticle.height)
88         drag.maximumX: width - reticle.width + (0.1 * reticle.width)
89         drag.maximumY: height - reticle.height + (0.1 * reticle.height)
90
91         onStatusChanged: {
92                 if (status != AutoFocus.Running) {
93                         reticle.visible = true;
94                 }
95         }
96
97         function predictColor(caf, status) {
98                 if (status == AutoFocus.Success) {
99                         return "steelblue";
100                 }
101                 else if (status == AutoFocus.Fail) {
102                         return "red";
103                 }
104                 else if (status == AutoFocus.Running) {
105                         return "white";
106                 }
107                 else if (caf == AutoFocus.Success) {
108                         return "steelblue";
109                 }
110                 else {
111                         return "white";
112                 }
113         }
114
115         function moveToCenter() {
116                 reticle.x = reticle.center.x;
117                 reticle.y = reticle.center.y;
118         }
119
120         function moveReticle(x, y) {
121                 var xPos = x - ((reticle.width * 1) / 2);
122                 var yPos = y - ((reticle.height * 1) / 2);
123                 xPos = Math.min(Math.max(xPos, drag.minimumX), drag.maximumX);
124                 yPos = Math.min(Math.max(yPos, drag.minimumY), drag.maximumY);
125                 reticle.x = xPos;
126                 reticle.y = yPos;
127         }
128
129         function moveToCenterIfNeeded(x, y) {
130                 if (x >= centerRect.x && y >= centerRect.y &&
131                     x <= centerRect.x + centerRect.width &&
132                     y <= centerRect.y + centerRect.height) {
133                         reticle.x = reticle.center.x
134                         reticle.y = reticle.center.y
135                 }
136         }
137
138         function setRegionOfInterest() {
139                 if (!reticle.touchMode) {
140                         cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
141                         return;
142                 }
143
144                 // take into account scale:
145                 var x = reticle.x + (reticle.width * 0.1);
146                 var y = reticle.y + (reticle.height * 0.1);
147
148                 var width = reticle.width * 0.8;
149                 var height = reticle.height * 0.8;
150
151                 // in terms of video resolution:
152                 x = (cam.videoResolution.width * x) / mouse.width;
153                 width = (cam.videoResolution.width * width) / mouse.width;
154                 y = (cam.videoResolution.height * y) / mouse.height;
155                 height = (cam.videoResolution.height * height) / mouse.height;
156
157                 // Translate to normalized coordinates (1x1 square) as expected by our C++ backend
158                 x = x / cam.videoResolution.width;
159                 width = width / cam.videoResolution.width;
160                 y = y / cam.videoResolution.height;
161                 height = height / cam.videoResolution.height;
162
163                 cam.autoFocus.setRegionOfInterest(Qt.rect(x, y, width, height));
164         }
165
166         onReleased: {
167                 moveToCenterIfNeeded(mouse.x, mouse.y);
168                 setRegionOfInterest();
169         }
170
171         onPressed: {
172                 moveReticle(mouse.x, mouse.y);
173         }
174
175         FocusRectangle {
176                 id: reticle
177                 property variant center: Qt.point((mouse.width - width) / 2, (mouse.height - height) / 2);
178                 property bool touchMode: !(reticle.x == center.x && reticle.y == center.y)
179
180                 scale: mouse.pressed ? 0.6 : touchMode ? 0.8 : 1.0
181
182                 width: 250
183                 height: 150
184                 x: center.x
185                 y: center.y
186
187                 color: predictColor(cafStatus, status);
188         }
189
190         Timer {
191                 interval: 500
192                 running: status == AutoFocus.Running
193                 triggeredOnStart: true
194                 repeat: true
195                 onTriggered: reticle.visible = !reticle.visible
196         }
197 }