61 */ |
63 */ |
62 HbVkbGeometryLogicPrivate::HbVkbGeometryLogicPrivate( |
64 HbVkbGeometryLogicPrivate::HbVkbGeometryLogicPrivate( |
63 const QSizeF& screenSize, |
65 const QSizeF& screenSize, |
64 const QSizeF& keypadSize, |
66 const QSizeF& keypadSize, |
65 const QRectF& sceneArea, |
67 const QRectF& sceneArea, |
|
68 bool isPopupType, |
66 bool isVkbOpen, |
69 bool isVkbOpen, |
67 bool hideTitlebar, |
70 bool hideTitlebar, |
68 bool hideStatusbar, |
71 bool hideStatusbar, |
69 const QRectF& containerArea, |
72 const QRectF& containerArea, |
70 const QRectF& editorArea, |
73 const QRectF& editorArea, |
71 const QRectF& cursorArea) |
74 const QRectF& cursorArea) |
|
75 : |
|
76 mIsPopupType(isPopupType) |
72 { |
77 { |
73 // We need to consider situation, when keyboard is already on the screen, in |
78 // We need to consider situation, when keyboard is already on the screen, in |
74 // which case, titlebar and statusbar are already hidden, thus bigger visible area |
79 // which case, titlebar and statusbar are already hidden, thus bigger visible area |
75 // is already in use, so no adjustments needed. |
80 // is already in use, so no adjustments needed. Popups can always use full visible |
76 if ( isVkbOpen ) { |
81 // area. |
|
82 if ( isVkbOpen || isPopupType ) { |
77 mVisibleArea = QRectF(0.0, 0.0, screenSize.width(), screenSize.height() - keypadSize.height()); |
83 mVisibleArea = QRectF(0.0, 0.0, screenSize.width(), screenSize.height() - keypadSize.height()); |
78 mAdjust = 0.0; |
84 mAdjust = 0.0; |
79 } else if ( hideTitlebar || hideStatusbar ) { |
85 } else if ( hideTitlebar || hideStatusbar ) { |
80 // Without titlebar and statusbar, the visible area is from the top of the screen |
86 // Without titlebar and statusbar, the visible area is from the top of the screen |
81 // to the top of the keyboard. Also, container needs to move slightly, when |
87 // to the top of the keyboard. Also, container needs to move slightly, when |
87 // bottom of the titlebar to top of the keyboard. No container movement needed. |
93 // bottom of the titlebar to top of the keyboard. No container movement needed. |
88 mVisibleArea = QRectF(0.0, 0.0, screenSize.width(), sceneArea.height() - keypadSize.height()); |
94 mVisibleArea = QRectF(0.0, 0.0, screenSize.width(), sceneArea.height() - keypadSize.height()); |
89 mAdjust = 0.0; |
95 mAdjust = 0.0; |
90 } |
96 } |
91 |
97 |
92 // Find out the container area. |
98 // Find out the container area. No margin adjustments for popups. |
93 mContainerArea = containerArea; |
99 mContainerArea = containerArea; |
94 mContainerArea.adjust(0.0, -HbContainerBorderMargin, 0.0, HbContainerBorderMargin); |
100 if (isPopupType) { |
|
101 mContainerArea.adjust(0.0, -HbContainerBorderMargin, 0.0, HbContainerBorderMargin); |
|
102 } |
95 mContainerArea.translate(QPointF(0, mAdjust)); |
103 mContainerArea.translate(QPointF(0, mAdjust)); |
96 |
104 |
97 // Find out the editor bounding box and add a small margin to height. |
105 // Find out the editor bounding box and add a small margin to height. |
98 mEditorArea = editorArea; |
106 mEditorArea = editorArea; |
99 mEditorArea.adjust(0.0, -HbCursorLineMargin, 0.0, HbCursorLineMargin); |
107 mEditorArea.adjust(0.0, -HbEditorExtraMargin, 0.0, HbEditorExtraMargin); |
100 mEditorArea.translate(QPointF(0, mAdjust)); |
108 mEditorArea.translate(QPointF(0, mAdjust)); |
101 |
109 |
102 // Finally, get cursor size and adjust it little bit |
110 // Finally, get cursor size and adjust it little bit |
103 mCursorArea = cursorArea; |
111 mCursorArea = cursorArea; |
104 mCursorArea.adjust(0.0, -HbEditorExtraMargin, 0.0, HbEditorExtraMargin); |
112 mCursorArea.adjust(0.0, -HbCursorLineMargin, 0.0, HbCursorLineMargin); |
105 mCursorArea.translate(QPointF(0, mAdjust)); |
113 mCursorArea.translate(QPointF(0, mAdjust)); |
106 } |
114 } |
107 |
115 |
|
116 |
108 /*! |
117 /*! |
109 \internal |
118 \internal |
110 \brief Check the source area fits inside target area. |
119 \brief Check the source area fits inside target area. |
111 */ |
120 */ |
|
121 bool HbVkbGeometryLogicPrivate::minimunMovement(QPointF& vector) const |
|
122 { |
|
123 vector.rx() = 0.0; |
|
124 vector.ry() = mAdjust; |
|
125 return false; |
|
126 } |
|
127 |
|
128 |
|
129 /*! |
|
130 \internal |
|
131 \brief Calculates vector to move given area to visible area. |
|
132 \param areaToMove contains rectangle, which needs to be moved to visible area. |
|
133 |
|
134 When moving editor to visible area, we need to consider situation, where |
|
135 margins of the editor border may make editor look like it is outside of the |
|
136 container. So every check we made, we need to compare against editor border |
|
137 and container border. |
|
138 |
|
139 \return Vector to visible area. |
|
140 */ |
|
141 bool HbVkbGeometryLogicPrivate::calculateVectorToVisibleArea(QPointF& vector, const QRectF& areaToMove) const |
|
142 { |
|
143 qreal aTop = areaToMove.top(); |
|
144 qreal vTop = mVisibleArea.top(); |
|
145 qreal cTop = mContainerArea.top(); |
|
146 |
|
147 qreal aBottom = areaToMove.bottom(); |
|
148 qreal vBottom = mVisibleArea.bottom(); |
|
149 qreal cBottom = mContainerArea.bottom(); |
|
150 |
|
151 QRectF areaOfInterest = areaToMove; |
|
152 |
|
153 // To simplify everything, first check, whether there is need to inspect |
|
154 // container movement issues or not. |
|
155 if ( !mContainerArea.contains(areaOfInterest) ) { |
|
156 // Now we know, that area we are supposed to move, cannot be used |
|
157 // in situations, when too close to borders and movement direction |
|
158 // tells us to move container. |
|
159 bool shouldMoveUp = aBottom > vBottom; |
|
160 bool areaBelowContainer = aBottom > cBottom; |
|
161 bool shouldMoveDown = aTop < vTop; |
|
162 bool areaAboveContainer = aTop < cTop; |
|
163 |
|
164 if ( ( areaBelowContainer && shouldMoveUp ) || |
|
165 ( areaAboveContainer && shouldMoveDown ) ) { |
|
166 areaOfInterest = mContainerArea; |
|
167 } |
|
168 } |
|
169 |
|
170 // Area is inside container. Before anything, check if we |
|
171 // can move the container at least little bit. But it cannot be moved |
|
172 // too low. |
|
173 if ( areaOfInterest != mContainerArea && aTop < vTop ) { |
|
174 qreal upward = aTop - mAdjust; |
|
175 |
|
176 if ( upward < 0 ) { |
|
177 vector.ry() -= upward; |
|
178 return true; |
|
179 } else { |
|
180 return false; |
|
181 } |
|
182 |
|
183 // Vector calculation is simple, just figure out direction. |
|
184 } else if ( aTop < vTop ) { |
|
185 vector = QPointF(0.0, -aTop); |
|
186 return true; |
|
187 |
|
188 } else { |
|
189 vector = QPointF(0.0, vBottom - areaOfInterest.bottom()); |
|
190 return true; |
|
191 } |
|
192 } |
|
193 |
|
194 |
|
195 /*! |
|
196 \internal |
|
197 \brief Check the source area fits inside target area. |
|
198 */ |
112 bool HbVkbGeometryLogicPrivate::fitsArea(const QRectF& target, const QRectF& source) const |
199 bool HbVkbGeometryLogicPrivate::fitsArea(const QRectF& target, const QRectF& source) const |
113 { |
200 { |
114 return source.width() <= target.width() && source.height() <= target.height(); |
201 return source.width() <= target.width() && source.height() <= target.height(); |
115 } |
202 } |
|
203 |
116 |
204 |
117 /*! |
205 /*! |
118 \internal |
206 \internal |
119 \brief Checks, whether the container fits into the visible area. |
207 \brief Checks, whether the container fits into the visible area. |
120 |
208 |
152 bool HbVkbGeometryLogicPrivate::isContainerVisible() const |
242 bool HbVkbGeometryLogicPrivate::isContainerVisible() const |
153 { |
243 { |
154 return mVisibleArea.contains(mContainerArea); |
244 return mVisibleArea.contains(mContainerArea); |
155 } |
245 } |
156 |
246 |
157 /*! |
247 |
158 \internal |
248 /*! |
159 \return True, when editor inside visible area |
249 \internal |
|
250 \return |
160 */ |
251 */ |
161 bool HbVkbGeometryLogicPrivate::isEditorVisible() const |
252 bool HbVkbGeometryLogicPrivate::isEditorVisible() const |
162 { |
253 { |
163 return mVisibleArea.contains(mEditorArea); |
254 return mVisibleArea.contains(mEditorArea); |
164 } |
255 } |
165 |
256 |
166 /*! |
257 |
167 \internal |
258 /*! |
168 \return True, when cursor inside visible area |
259 \internal |
|
260 \return |
169 */ |
261 */ |
170 bool HbVkbGeometryLogicPrivate::isCursorVisible() const |
262 bool HbVkbGeometryLogicPrivate::isCursorVisible() const |
171 { |
263 { |
172 // Check wheter cursor inside the visible area. |
264 // Check whether cursor inside the visible area. |
173 return mVisibleArea.contains(mCursorArea); |
265 return mVisibleArea.contains(mCursorArea); |
174 } |
266 } |
175 |
267 |
176 /*! |
268 |
177 \internal |
269 /*! |
178 \brief Calculates movement vector for viewport. |
270 \internal |
179 |
271 \return |
180 \return True, when container needs to be moved. |
|
181 */ |
272 */ |
182 bool HbVkbGeometryLogicPrivate::calculateContainerMovement(QPointF& vector) const |
273 bool HbVkbGeometryLogicPrivate::calculateContainerMovement(QPointF& vector) const |
183 { |
274 { |
|
275 // Clear any data away from the vector |
|
276 vector = QPointF(0, 0); |
|
277 |
|
278 // First check against invalid case. If cursor is not inside container, the |
|
279 // data provided is incorrect. |
|
280 if ( !mContainerArea.contains(mCursorArea) ) { |
|
281 return false; |
|
282 |
|
283 } else if ( containerFitsVisibleArea() ) { |
|
284 return calculateContainerVector(vector); |
|
285 |
|
286 } else if ( mIsPopupType ) { |
|
287 return calculatePopupVector(vector); |
|
288 |
184 // In case editor or cursor inside visible area, no extra movement needed. |
289 // In case editor or cursor inside visible area, no extra movement needed. |
185 if ( isCursorVisible() ) { |
290 } else if ( isCursorVisible() ) { |
186 vector.rx() = 0.0; |
291 return minimunMovement(vector); |
187 vector.ry() = mAdjust; |
|
188 return false; |
|
189 } |
|
190 |
292 |
191 // At this point we know, that cursor is not inside of visible area, |
293 // At this point we know, that cursor is not inside of visible area, |
192 // after VKB has been shown. To make it bit prettier, let's check, if we can |
294 // after VKB has been shown. To make it bit prettier, let's check, if we can |
193 // move and fit the whole editor into the screen at once. |
295 // move and fit the whole editor into the screen at once. |
194 if ( !isEditorVisible() && editorFitsVisibleArea() ) { |
296 } else if ( !isEditorVisible() && editorFitsVisibleArea() ) { |
195 // Editor is not in screen but fits there, so simply move the whole editor |
297 return calculateEditorVector(vector); |
196 // to screen. Only thing yet to check is, which direction the editor needs |
298 |
197 // to be moved. |
|
198 if ( mEditorArea.top() <= mVisibleArea.top() ) { |
|
199 vector = QPointF(0.0, -mEditorArea.top()); |
|
200 } else { |
|
201 // In case editor is not inside visible area, move editor until it is. |
|
202 vector = QPointF(0.0, mVisibleArea.bottom() - mEditorArea.bottom()); |
|
203 } |
|
204 |
|
205 vector.ry() += mAdjust; |
|
206 |
|
207 // Vector has been calculated, so finish the story and return. |
|
208 return true; |
|
209 } |
|
210 |
299 |
211 // At this point we know, that cursor is not visible and the editor does not fit |
300 // At this point we know, that cursor is not visible and the editor does not fit |
212 // into the visible area. Here we need to move editor, so that the cursor can be |
301 // into the visible area. Here we need to move editor, so that the cursor can be |
213 // seen in the visible area. There are two ways to do this. |
302 // seen in the visible area. There are two ways to do this. |
214 // 1) Move container, until bottom of editor is reached OR |
303 // 1) Move container, until bottom of editor is reached OR |
215 // 2) Move container, until cursor hits top of the screen |
304 // 2) Move container, until cursor hits top of the screen |
216 int cursorMove = (int)(mVisibleArea.top() - mCursorArea.top()); |
305 } else { |
217 int editorMove = (int)(mVisibleArea.bottom() - mEditorArea.bottom()); |
306 int cursorMove = static_cast<int>(mVisibleArea.top() - mCursorArea.top()); |
218 |
307 int editorMove = static_cast<int>(mVisibleArea.bottom() - mEditorArea.bottom()); |
219 // Choose smaller movement (notice usage of negative values) |
308 |
220 vector = QPointF(0.0, cursorMove >= editorMove ? cursorMove : editorMove); |
309 // Choose smaller movement (notice usage of negative values) |
221 |
310 vector = QPointF(0.0, cursorMove >= editorMove ? cursorMove : editorMove); |
|
311 |
|
312 vector.ry() += mAdjust; |
|
313 return true; |
|
314 } |
|
315 } |
|
316 |
|
317 |
|
318 /*! |
|
319 \internal |
|
320 \return |
|
321 */ |
|
322 bool HbVkbGeometryLogicPrivate::calculateContainerVector(QPointF& vector) const |
|
323 { |
|
324 if ( isContainerVisible() ) { |
|
325 return minimunMovement(vector); |
|
326 } |
|
327 |
|
328 bool result = calculateVectorToVisibleArea(vector, mContainerArea); |
222 vector.ry() += mAdjust; |
329 vector.ry() += mAdjust; |
|
330 return result; |
|
331 } |
|
332 |
|
333 |
|
334 /*! |
|
335 \internal |
|
336 \brief Calculate vector to adjust popup location properly. |
|
337 |
|
338 Goal of these calculations are to guarrantee, that the buttons are always |
|
339 visible for user, so that the popup can be closed without closing VKB first. |
|
340 This is achieved by trying to move popup bottom to edge of visible area, |
|
341 and then check, whether the editor is still seen or not. If not, then adjust |
|
342 the editor so, that it can be seen. |
|
343 |
|
344 \return True, when movement needed |
|
345 */ |
|
346 bool HbVkbGeometryLogicPrivate::calculatePopupVector(QPointF& vector) const |
|
347 { |
|
348 qreal mBottom = mContainerArea.bottom(); |
|
349 qreal vBottom = mVisibleArea.bottom(); |
|
350 vector.ry() += vBottom - mBottom; |
|
351 |
|
352 QRectF newEditorPos = mEditorArea.translated(vector); |
|
353 if (!mVisibleArea.contains(newEditorPos)) { |
|
354 QPointF temp(0,0); |
|
355 calculateVectorToVisibleArea(temp, newEditorPos); |
|
356 vector += temp; |
|
357 } |
|
358 |
|
359 vector.ry() += mAdjust; |
|
360 |
223 return true; |
361 return true; |
224 } |
362 } |
|
363 |
|
364 |
|
365 /*! |
|
366 \internal |
|
367 \return |
|
368 */ |
|
369 bool HbVkbGeometryLogicPrivate::calculateEditorVector(QPointF& vector) const |
|
370 { |
|
371 bool result = calculateVectorToVisibleArea(vector, mEditorArea); |
|
372 vector.ry() += mAdjust; |
|
373 return result; |
|
374 } |
|
375 |