wrong assignment lead to the ability to drag the reticle outside the page
[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 MouseArea {
29         property int cafStatus: AutoFocus.None
30         property int status: AutoFocus.None
31         id: mouse
32
33         // A 100x100 central "rectangle"
34         property variant centerRect: Qt.rect((mouse.width / 2 - 50), (mouse.height / 2) - 50, 100, 100);
35
36         property alias touchMode: reticle.touchMode
37
38         x: cam.renderArea.x
39         y: cam.renderArea.y
40         width: cam.renderArea.width
41         height: cam.renderArea.height
42
43         // Changing mode (which implies changing pages) will not reset ROI thus we do it here
44         Component.onCompleted: cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
45
46 /*
47         // This is for debugging
48         Rectangle {
49                 color: "blue"
50                 opacity: 0.2
51                 anchors.fill: parent
52         }
53
54         Rectangle {
55                 color: "red"
56                 opacity: 0.4
57                 x: centerRect.x
58                 y: centerRect.y
59                 width: centerRect.width
60                 height: centerRect.height
61         }
62 */
63         drag.target: reticle
64         drag.axis: Drag.XandYAxis
65         drag.minimumX: 0 - (0.1 * reticle.width)
66         drag.minimumY: 0 - (0.1 * reticle.height)
67         drag.maximumX: width - reticle.width + (0.1 * reticle.width)
68         drag.maximumY: height - reticle.height + (0.1 * reticle.height)
69
70         onStatusChanged: {
71                 if (status != AutoFocus.Running) {
72                         reticle.visible = true;
73                 }
74         }
75
76         function predictColor(caf, status) {
77                 if (status == AutoFocus.Success) {
78                         return "steelblue";
79                 }
80                 else if (status == AutoFocus.Fail) {
81                         return "red";
82                 }
83                 else if (status == AutoFocus.Running) {
84                         return "white";
85                 }
86                 else if (caf == AutoFocus.Success) {
87                         return "steelblue";
88                 }
89                 else {
90                         return "white";
91                 }
92         }
93
94         function moveReticle(x, y) {
95                 var xPos = x - ((reticle.width * 1) / 2);
96                 var yPos = y - ((reticle.height * 1) / 2);
97                 xPos = Math.min(Math.max(xPos, drag.minimumX), drag.maximumX);
98                 yPos = Math.min(Math.max(yPos, drag.minimumY), drag.maximumY);
99                 reticle.x = xPos;
100                 reticle.y = yPos;
101         }
102
103         function moveToCenterIfNeeded(x, y) {
104                 if (x >= centerRect.x && y >= centerRect.y &&
105                     x <= centerRect.x + centerRect.width &&
106                     y <= centerRect.y + centerRect.height) {
107                         reticle.x = reticle.center.x
108                         reticle.y = reticle.center.y
109                 }
110         }
111
112         function setRegionOfInterest() {
113                 if (!reticle.touchMode) {
114                         cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
115                         return;
116                 }
117
118                 // take into account scale:
119                 var x = reticle.x + (reticle.width * 0.1);
120                 var y = reticle.y + (reticle.height * 0.1);
121
122                 var width = reticle.width * 0.8;
123                 var height = reticle.height * 0.8;
124
125                 // in terms of video resolution:
126                 x = (cam.videoResolution.width * x) / mouse.width;
127                 width = (cam.videoResolution.width * width) / mouse.width;
128                 y = (cam.videoResolution.height * y) / mouse.height;
129                 height = (cam.videoResolution.height * height) / mouse.height;
130
131                 // Translate to normalized coordinates (1x1 square) as expected by our C++ backend
132                 x = x / cam.videoResolution.width;
133                 width = width / cam.videoResolution.width;
134                 y = y / cam.videoResolution.height;
135                 height = height / cam.videoResolution.height;
136
137                 cam.autoFocus.setRegionOfInterest(Qt.rect(x, y, width, height));
138         }
139
140         onReleased: {
141                 moveToCenterIfNeeded(mouse.x, mouse.y);
142                 setRegionOfInterest();
143         }
144
145         onPressed: {
146                 moveReticle(mouse.x, mouse.y);
147         }
148
149         FocusRectangle {
150                 id: reticle
151                 property variant center: Qt.point((mouse.width - width) / 2, (mouse.height - height) / 2);
152                 property bool touchMode: !(reticle.x == center.x && reticle.y == center.y)
153
154                 scale: mouse.pressed ? 0.6 : touchMode ? 0.8 : 1.0
155
156                 width: 250
157                 height: 150
158                 x: center.x
159                 y: center.y
160
161                 color: predictColor(cafStatus, status);
162         }
163
164         Timer {
165                 interval: 500
166                 running: status == AutoFocus.Running
167                 triggeredOnStart: true
168                 repeat: true
169                 onTriggered: reticle.visible = !reticle.visible
170         }
171 }