|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 include("../containers/containerLibrary.js") |
|
20 include("../renderLibrary.js") |
|
21 include("../srcgenLibrary.js") |
|
22 |
|
23 function NaviTabsVisual() { |
|
24 } |
|
25 |
|
26 function getNaviSize(instance, laf) { |
|
27 var properties = instance.properties; |
|
28 return new Point(properties.size.width, properties.size.height); |
|
29 } |
|
30 |
|
31 function isLongTabs(instance) { |
|
32 var property = instance.properties.tabWidth; |
|
33 return ((property == "EAknTabWidthWithTwoLongTabs") || |
|
34 (property == "EAknTabWidthWithThreeLongTabs")); |
|
35 } |
|
36 |
|
37 function isOneTab(property) { |
|
38 return (property == "EAknTabWidthWithOneTab"); |
|
39 } |
|
40 |
|
41 function getNumVisualTabs(property) { |
|
42 if ((property == "EAknTabWidthWithTwoTabs") || |
|
43 (property == "EAknTabWidthWithTwoLongTabs")) |
|
44 return 2; |
|
45 else if ((property == "EAknTabWidthWithThreeTabs") || |
|
46 (property == "EAknTabWidthWithThreeLongTabs")) |
|
47 return 3; |
|
48 else if (isOneTab(property)) |
|
49 return 1; |
|
50 |
|
51 return 4; |
|
52 } |
|
53 |
|
54 function getHorizontalInset(laf) { |
|
55 return laf.getDimension("navi.indicator.size").x; |
|
56 } |
|
57 |
|
58 function getTabOffset(totalWidth, longTabs, numVisualTabs, laf) { |
|
59 if (longTabs) |
|
60 return totalWidth / 18; |
|
61 |
|
62 var width = totalWidth - (2 * getHorizontalInset(laf)); |
|
63 return (width / numVisualTabs) - (2 * laf.getInteger("tab.corner", 3)); |
|
64 } |
|
65 |
|
66 function getTabWidth(totalWidth, numVisualTabs, longTabs, laf) { |
|
67 var sideInset = getHorizontalInset(laf); |
|
68 return totalWidth - (2 * sideInset) - ((numVisualTabs - 1) * getTabOffset(totalWidth, longTabs, numVisualTabs, laf)); |
|
69 } |
|
70 |
|
71 function getNumTabs(instance) { |
|
72 var appUi = instance.parent.parent; |
|
73 var numTabs = 0; |
|
74 for (var i in appUi.children) { |
|
75 if (appUi.children[i].isInstanceOf("com.nokia.sdt.series60.AvkonViewReference")) { |
|
76 if (appUi.children[i].properties.inTabGroup) |
|
77 numTabs++; |
|
78 } |
|
79 } |
|
80 |
|
81 return numTabs; |
|
82 } |
|
83 |
|
84 function drawTab(r, laf, graphics, isActive) { |
|
85 var offset = laf.getInteger("tab.corner", 3); |
|
86 |
|
87 var intArray = [ |
|
88 r.x, |
|
89 r.y + r.height, |
|
90 r.x + offset, |
|
91 r.y + r.height - offset, |
|
92 r.x + (4 * offset), |
|
93 r.y + offset, |
|
94 r.x + (5 * offset), |
|
95 r.y, |
|
96 r.x + r.width - (5 * offset), |
|
97 r.y, |
|
98 r.x + r.width - (4 * offset), |
|
99 r.y + offset, |
|
100 r.x + r.width - offset, |
|
101 r.y + r.height - offset, |
|
102 r.x + r.width, |
|
103 r.y + r.height, |
|
104 ]; |
|
105 |
|
106 if (laf.getBoolean("is.landscape", false)) { |
|
107 for (var i = 0; i < intArray.length; i++) { |
|
108 if ((i % 2) != 0) { |
|
109 var yval = intArray[i]; |
|
110 intArray[i] = r.height - yval; |
|
111 } |
|
112 } |
|
113 } |
|
114 |
|
115 var faceColor = isActive ? laf.getColor("navi.tab.face") : laf.getColor("navi.tab.back"); |
|
116 graphics.setBackground(faceColor); |
|
117 graphics.fillPolygon(intArray); |
|
118 graphics.setForeground(laf.getColor("navi.tab.shade")); |
|
119 graphics.drawPolyline(intArray); |
|
120 } |
|
121 |
|
122 function getViewRefFromIndex(instance, index) { |
|
123 var appUiChildren = instance.parent.parent.children; |
|
124 var tabIndex = -1; |
|
125 for (var i in appUiChildren) { |
|
126 var child = appUiChildren[i]; |
|
127 if ((child.componentId == "com.nokia.sdt.series60.AvkonViewReference") && child.properties.inTabGroup) |
|
128 tabIndex++; |
|
129 if (tabIndex == index) |
|
130 return child; |
|
131 } |
|
132 |
|
133 return null; |
|
134 } |
|
135 |
|
136 function getText(instance, index) { |
|
137 var viewRef = getViewRefFromIndex(instance, index); |
|
138 if (viewRef != null) |
|
139 return viewRef.properties.tabText; |
|
140 |
|
141 return ""; |
|
142 } |
|
143 |
|
144 function hasTabText(instance, index) { |
|
145 return getText(instance, index).length > 0; |
|
146 } |
|
147 |
|
148 function drawText(instance, rect, font, graphics, index) { |
|
149 var text = getText(instance, index); |
|
150 text = chooseScalableText(text, font, rect.width); |
|
151 var extent = font.stringExtent(text); |
|
152 var newrect = new Rectangle(rect.x, (rect.height - extent.y) / 2, rect.width, rect.height) |
|
153 graphics.drawFormattedString(text, newrect, Font.ALIGN_CENTER | Font.ANTIALIAS_OFF | Font.OVERFLOW_ELLIPSIS, 0); |
|
154 } |
|
155 |
|
156 function hasTabImage(instance, index) { |
|
157 var viewRef = getViewRefFromIndex(instance, index); |
|
158 if (viewRef != null) { |
|
159 return isImagePropertySet(viewRef.properties.tabImage); |
|
160 } |
|
161 |
|
162 return false; |
|
163 } |
|
164 |
|
165 function getUnmaskedFillColor(isOneTab, isActiveMulti, laf) { |
|
166 if (isOneTab) |
|
167 return laf.getColor("navi.pane.text"); |
|
168 else if (isActiveMulti) |
|
169 return laf.getColor("navi.tab.face") |
|
170 else |
|
171 return laf.getColor("navi.tab.backText"); |
|
172 } |
|
173 |
|
174 function renderTabImage(viewRef, isOneTab, isActiveMulti, laf, graphics, rect, color) { |
|
175 |
|
176 var imagePropertyRendering = createImagePropertyRendering(); |
|
177 imagePropertyRendering.setImageProperty(viewRef, "tabImage", laf); |
|
178 |
|
179 var imageProperty = viewRef.properties.tabImage.editableValue; |
|
180 |
|
181 // Different behavior for masked and unmasked images, in terms of the size |
|
182 // of renderable area, the way the bitmap and mask are treated, etc. |
|
183 |
|
184 if (imageProperty.isMasked()) { |
|
185 // set the color used for monochrome rendering |
|
186 graphics.setForeground(color); |
|
187 } |
|
188 else { |
|
189 graphics.setBackground(getUnmaskedFillColor(isOneTab, isActiveMulti, laf)); |
|
190 var fillRect = new Rectangle(rect.x, rect.y, rect.width, rect.height); |
|
191 var hShrink = 0; |
|
192 if (isOneTab) |
|
193 hShrink = rect.width / 3; |
|
194 else |
|
195 hShrink = 4 * laf.getInteger("tab.corner", 3); |
|
196 shrinkRect(fillRect, hShrink, 0); |
|
197 graphics.fillRectangle(fillRect.x, fillRect.y, fillRect.width, fillRect.height); |
|
198 } |
|
199 |
|
200 imagePropertyRendering.setViewableSize(new Point(rect.width, rect.height)); |
|
201 imagePropertyRendering.setAlignmentWeights(new Point(ImageUtils.ALIGN_CENTER, ImageUtils.ALIGN_CENTER_OR_TOP)); |
|
202 imagePropertyRendering.setScaling(isScalingIcons()); |
|
203 imagePropertyRendering.setPreservingAspectRatio(true); |
|
204 |
|
205 imagePropertyRendering.setTransparencyHandling(imagePropertyRendering.TRANSPARENCY_FLATTEN); |
|
206 |
|
207 // use this model in S60ImagePropertyRendering to handle the weird (mis-)use of |
|
208 // bitmap and mask in the navi pane |
|
209 imagePropertyRendering.setRenderingModel(imagePropertyRendering.MODEL_NAVI_PANE_TABS); |
|
210 |
|
211 imagePropertyRendering.render(graphics.getWrappedGC(), rect.x, rect.y); |
|
212 |
|
213 } |
|
214 |
|
215 function shrinkRect(rect, h, v) { |
|
216 rect.x += h; |
|
217 rect.width -= (2 * h); |
|
218 rect.y += v; |
|
219 rect.height -= (2 * v); |
|
220 } |
|
221 |
|
222 function drawTabImage(isOneTab, isActiveMulti, rect, instance, laf, graphics, index) { |
|
223 var viewRef = getViewRefFromIndex(instance, index); |
|
224 var color = getTextColor(isOneTab, isActiveMulti, laf); |
|
225 var shrinkage = laf.getInteger("tab.corner", 3); |
|
226 var drawRect = new Rectangle(rect.x, rect.y, rect.width, rect.height); |
|
227 shrinkRect(drawRect, shrinkage, shrinkage); |
|
228 renderTabImage(viewRef, isOneTab, isActiveMulti, laf, graphics, drawRect, color); |
|
229 } |
|
230 |
|
231 function drawOneTabContents(instance, rect, font, laf, graphics, index) { |
|
232 var hasImage = hasTabImage(instance, index); |
|
233 var hasText = hasTabText(instance, index); |
|
234 /* |
|
235 NOT TRYING TO RENDER IMAGE AND TEXT, BECAUSE EXCEPT FOR VERY FEW CASES, IT LOOKS HOORIBLE ON THE EMULATOR! |
|
236 if (hasImage && hasText) { |
|
237 var imageRect = new Rectangle(rect.x, rect.y, rect.width / 2, rect.height); |
|
238 drawTabImage(true, false, imageRect, instance, laf, graphics, index); |
|
239 var text = getText(instance, index); |
|
240 var textRect = new Rectangle(rect.x + (rect.width / 2), rect.y, rect.width / 2, rect.height); |
|
241 drawText(instance, textRect, font, graphics, index); |
|
242 } |
|
243 */ |
|
244 if (hasText) { |
|
245 var text = getText(instance, index); |
|
246 drawText(instance, rect, font, graphics, index); |
|
247 } |
|
248 else if (hasImage) { |
|
249 drawTabImage(true, false, rect, instance, laf, graphics, index); |
|
250 } |
|
251 } |
|
252 |
|
253 function drawOneTab(instance, rect, laf, graphics, index) { |
|
254 var color = getTextColor(true, false, laf); |
|
255 |
|
256 var font = laf.getFont("navi.text.font"); |
|
257 graphics.setFont(font); |
|
258 graphics.setForeground(color); |
|
259 |
|
260 drawOneTabContents(instance, rect, font, laf, graphics, index); |
|
261 } |
|
262 |
|
263 function getTextColor(isOneTab, isActiveMulti, laf) { |
|
264 if (isOneTab) |
|
265 return laf.getColor("navi.pane.text"); |
|
266 else if (isActiveMulti) |
|
267 return laf.getColor("navi.tab.text") |
|
268 else |
|
269 return laf.getColor("navi.tab.backText"); |
|
270 } |
|
271 |
|
272 function drawTabText(instance, rect, laf, graphics, isActive, index) { |
|
273 var color = getTextColor(false, isActive, laf); |
|
274 var font = laf.getFont("navi.tab.font"); |
|
275 graphics.setFont(font); |
|
276 graphics.setForeground(color); |
|
277 |
|
278 drawText(instance, rect, font, graphics, index); |
|
279 } |
|
280 |
|
281 function drawTabContents(instance, rect, laf, graphics, isActive, index) { |
|
282 var hasImage = hasTabImage(instance, index); |
|
283 var hasText = hasTabText(instance, index); |
|
284 /* |
|
285 NOT TRYING TO RENDER IMAGE AND TEXT, BECAUSE EXCEPT FOR VERY FEW CASES, IT LOOKS HOORIBLE ON THE EMULATOR! |
|
286 if (hasImage && hasText) { |
|
287 var text = getText(instance, index); |
|
288 var textRect = new Rectangle(rect.x, rect.y, rect.width / 2, rect.height);new Rectangle(rect.x, rect.y, rect.width / 2, rect.height); |
|
289 drawTabText(instance, textRect, laf, graphics, isActive, index); |
|
290 var imageRect = new Rectangle(rect.x + (rect.width / 2), rect.y, rect.width / 2, rect.height); |
|
291 drawTabImage(false, isActive, imageRect, instance, laf, graphics, index); |
|
292 } |
|
293 */ |
|
294 if (hasText) { |
|
295 var text = getText(instance, index); |
|
296 drawTabText(instance, rect, laf, graphics, isActive, index); |
|
297 } |
|
298 else if (hasImage) { |
|
299 drawTabImage(false, isActive, rect, instance, laf, graphics, index); |
|
300 } |
|
301 } |
|
302 |
|
303 function drawMultipleTabs(instance, rect, laf, graphics, active) { |
|
304 var numVisualTabs = getNumVisualTabs(instance.properties.tabWidth); |
|
305 var longTabs = isLongTabs(instance); |
|
306 var hInset = getHorizontalInset(laf); |
|
307 var tabOffset = getTabOffset(rect.width, longTabs, numVisualTabs, laf); |
|
308 var tabWidth = getTabWidth(rect.width, numVisualTabs, longTabs, laf); |
|
309 |
|
310 var firstTab = 0; |
|
311 var numTabs = getNumTabs(instance); |
|
312 if (active >= numVisualTabs) |
|
313 firstTab = active; |
|
314 if (firstTab + numVisualTabs >= numTabs) |
|
315 firstTab = numTabs - numVisualTabs; |
|
316 if (firstTab < 0) |
|
317 firstTab = 0; |
|
318 |
|
319 // first draw the inactive tabs |
|
320 for (var i = firstTab + numVisualTabs - 1; i > active; i--) { |
|
321 var left = rect.x + hInset + ((i - firstTab) * tabOffset); |
|
322 var drawRect = new Rectangle(left, rect.y, tabWidth, rect.height); |
|
323 drawTab(drawRect, laf, graphics, false); |
|
324 if (!longTabs) { |
|
325 drawTabContents(instance, drawRect, laf, graphics, false, i); |
|
326 } |
|
327 } |
|
328 for (var i = firstTab; i < active; i++) { |
|
329 var left = rect.x + hInset + ((i - firstTab) * tabOffset); |
|
330 var drawRect = new Rectangle(left, rect.y, tabWidth, rect.height); |
|
331 drawTab(drawRect, laf, graphics, false); |
|
332 if (!longTabs) { |
|
333 drawTabContents(instance, drawRect, laf, graphics, false, i); |
|
334 } |
|
335 } |
|
336 |
|
337 // then draw the active tab |
|
338 { |
|
339 var left = rect.x + hInset + ((active - firstTab) * tabOffset); |
|
340 var drawRect = new Rectangle(left, rect.y, tabWidth, rect.height); |
|
341 drawTab(drawRect, laf, graphics, true); |
|
342 drawTabContents(instance, drawRect, laf, graphics, true, active); |
|
343 } |
|
344 } |
|
345 |
|
346 function drawArrow(onRight, rect, laf, graphics) { |
|
347 var arrowHeight = rect.height / 3; |
|
348 graphics.setForeground(laf.getColor("navi.tab.arrow")); |
|
349 var arrowTop = (rect.height - arrowHeight) / 2; |
|
350 var hInset = getHorizontalInset(laf); |
|
351 var arrowWidth = ((arrowHeight % 2) == 0) ? arrowHeight / 2 + 1 : arrowHeight / 2; |
|
352 |
|
353 for (var i = 0; i < arrowWidth; i++) { |
|
354 var x; |
|
355 if (onRight) |
|
356 x = rect.x + rect.width - hInset + i; |
|
357 else |
|
358 x = rect.x + hInset - i; |
|
359 var y0 = arrowTop + i; |
|
360 var y1 = arrowTop + arrowHeight - i; |
|
361 graphics.drawLine(x, y0, x, y1); |
|
362 } |
|
363 } |
|
364 |
|
365 NaviTabsVisual.prototype.draw = function(instance, laf, graphics) { |
|
366 var properties = instance.properties; |
|
367 var active = instance.properties.active; |
|
368 var numTabs = getNumTabs(instance); |
|
369 |
|
370 if (active > (numTabs - 1)) |
|
371 active = numTabs - 1; |
|
372 |
|
373 if (active < 0) |
|
374 active = 0; |
|
375 |
|
376 var size = getNaviSize(instance, laf); |
|
377 var rect = new Rectangle(0, 0, size.x, size.y); |
|
378 if (!isOneTab(properties.tabWidth)) { |
|
379 drawMultipleTabs(instance, rect, laf, graphics, active); |
|
380 } |
|
381 else { |
|
382 drawOneTab(instance, rect, laf, graphics, active); |
|
383 } |
|
384 |
|
385 if (active > 0) |
|
386 drawArrow(false, rect, laf, graphics); |
|
387 |
|
388 if (active < (numTabs - 1)) |
|
389 drawArrow(true, rect, laf, graphics); |
|
390 } |
|
391 |
|
392 NaviTabsVisual.prototype.getPreferredSize = function(instance, laf, wHint, hHint) { |
|
393 return null; // needs implementation |
|
394 } |
|
395 |