|
1 /* |
|
2 * Copyright (c) 2003-2008 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 "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: Menu pane handling, common across all Displayables. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 // CEikonEnv API for iEkonEnv : |
|
21 // - to retrieving CEikAppUi |
|
22 // - to obtain device screen size |
|
23 #include <eikenv.h> |
|
24 // API for iAppUi |
|
25 #include <eikappui.h> |
|
26 // API for iMenuBar |
|
27 #include <eikmenub.h> |
|
28 #include <e32cmn.h> |
|
29 #include <AknUtils.h> |
|
30 // using constants for soft keys |
|
31 #include <avkon.hrh> |
|
32 // mocros for avkon resources |
|
33 #include <avkon.rsg> |
|
34 // macros for resources |
|
35 #include <lcdui.rsg> |
|
36 // API needed for iDisplayable and iDefaultDisplayable members |
|
37 #include "CMIDDisplayable.h" |
|
38 #include "CMIDCanvas.h" |
|
39 #include "CMIDMenuHandler.h" |
|
40 // CMIDTickerController API for iTickerController (stored in tls structure) |
|
41 #include "CMIDTicker.h" |
|
42 // for setting key decoder in tls |
|
43 #include "CMIDKeyDecoder.h" |
|
44 #include "lcdui.h" |
|
45 #include <j2me/jdebug.h> |
|
46 #include "CMIDUIManager.h" |
|
47 |
|
48 |
|
49 const TInt KResolutionStringLength = 4; |
|
50 |
|
51 // ============================ MEMBER FUNCTIONS =============================== |
|
52 |
|
53 |
|
54 // ----------------------------------------------------------------------------- |
|
55 // CMIDMenuHandler::NewL |
|
56 // Two-phased constructor. |
|
57 // ----------------------------------------------------------------------------- |
|
58 // |
|
59 CMIDMenuHandler* CMIDMenuHandler::NewL(MMIDEnv& aEnv) |
|
60 { |
|
61 CMIDMenuHandler* self = new(ELeave) CMIDMenuHandler(aEnv); |
|
62 CleanupStack::PushL(self); |
|
63 self->ConstructL(); |
|
64 CleanupStack::Pop(self); |
|
65 |
|
66 return self; |
|
67 } |
|
68 |
|
69 // ----------------------------------------------------------------------------- |
|
70 // CMIDMenuHandler::ConstructL |
|
71 // Symbian 2nd phase constructor can leave. |
|
72 // ----------------------------------------------------------------------------- |
|
73 // |
|
74 void CMIDMenuHandler::ConstructL() |
|
75 { |
|
76 iAppUi = iEikEnv.EikAppUi(); |
|
77 iMenuBar = new(ELeave) CEikMenuBar; |
|
78 iMenuBar->ConstructL(this, 0, R_MIDP_MENUBAR_DEFAULT); |
|
79 |
|
80 iCba = CEikButtonGroupContainer::NewL(CEikButtonGroupContainer::ECba, |
|
81 CEikButtonGroupContainer::EHorizontal, |
|
82 this, |
|
83 R_AVKON_SOFTKEYS_EMPTY); |
|
84 #ifdef RD_JAVA_S60_RELEASE_9_2 |
|
85 static_cast<CEikCba*>(iCba->ButtonGroup())->EnableItemSpecificSoftkey(EFalse); |
|
86 #endif |
|
87 const TSize screenSize = iEikEnv.ScreenDevice()->SizeInPixels(); |
|
88 iCba->SetBoundingRect(TRect(screenSize)); |
|
89 iViewRect = iAppUi->ClientRect(); |
|
90 iCba->ReduceRect(iViewRect); |
|
91 iAppUi->AddToStackL(iMenuBar,ECoeStackPriorityMenu,ECoeStackFlagRefusesFocus); |
|
92 SetScalingFactors(); |
|
93 } |
|
94 |
|
95 |
|
96 void CMIDMenuHandler::HideMenuIfVisible() |
|
97 { |
|
98 if (iMenuBar->IsDisplayed()) |
|
99 { |
|
100 iMenuBar->StopDisplayingMenuBar(); |
|
101 } |
|
102 } |
|
103 |
|
104 void CMIDMenuHandler::UpdateMenuIfVisibleL() |
|
105 { |
|
106 if (iMenuBar->IsDisplayed()) |
|
107 { // Menu is currently displayed |
|
108 |
|
109 iMenuBar->StopDisplayingMenuBar(); |
|
110 |
|
111 ShowMenuL(iMenuType); |
|
112 } |
|
113 } |
|
114 |
|
115 |
|
116 // C++ default constructor |
|
117 CMIDMenuHandler::CMIDMenuHandler(MMIDEnv& aEnv) |
|
118 : iEnv(aEnv) |
|
119 ,iEikEnv(*(CEikonEnv::Static())) |
|
120 { |
|
121 } |
|
122 |
|
123 // Destructor |
|
124 CMIDMenuHandler::~CMIDMenuHandler() |
|
125 { |
|
126 HideMenuIfVisible(); |
|
127 if (iAppUi) |
|
128 { |
|
129 iAppUi->RemoveFromStack(iMenuBar); |
|
130 } |
|
131 delete iMenuBar; |
|
132 delete iCba; |
|
133 iMenuItems.Reset(); |
|
134 } |
|
135 |
|
136 // ----------------------------------------------------------------------------- |
|
137 // CMIDMenuHandler::ShowMenuL |
|
138 // |
|
139 // @see DynInitMenuPaneL() |
|
140 // ----------------------------------------------------------------------------- |
|
141 // |
|
142 void CMIDMenuHandler::ShowMenuL(const TMenuType& aType) |
|
143 { |
|
144 if (iDisplayable && aType != ENoMenu && !iAttemptingToDisplayMenu) |
|
145 { |
|
146 iMenuType = aType; |
|
147 iDisplayable->CreateMenuItemsL(iMenuType, iMenuItems); |
|
148 |
|
149 // Set the CEikMenuBar type according to internal type |
|
150 if (aType == EOptionsMenu) |
|
151 { |
|
152 iMenuBar->SetMenuType(CEikMenuBar::EMenuOptions); |
|
153 } |
|
154 else if (aType == EOkMenu || aType == EHelpMenu || aType == EScreenAndHelpMenu) |
|
155 { |
|
156 iMenuBar->SetMenuType(CEikMenuBar::EMenuContext); |
|
157 } |
|
158 |
|
159 // If there is anything to show, open the menu |
|
160 if (iMenuItems.Count() > 0 && !iMenuBar->IsDisplayed()) |
|
161 { |
|
162 iAttemptingToDisplayMenu = ETrue; |
|
163 iMenuBar->TryDisplayMenuBarL(); |
|
164 } |
|
165 // Reset the menu type always to options menu just in case |
|
166 iMenuBar->SetMenuType(CEikMenuBar::EMenuOptions); |
|
167 } |
|
168 } |
|
169 |
|
170 // ----------------------------------------------------------------------------- |
|
171 // CMIDMenuHandler::MenuItemsCount |
|
172 // |
|
173 // |
|
174 // ----------------------------------------------------------------------------- |
|
175 // |
|
176 TUint CMIDMenuHandler::MenuItemsCount() const |
|
177 { |
|
178 return iMenuItems.Count(); |
|
179 } |
|
180 |
|
181 // ----------------------------------------------------------------------------- |
|
182 // CMIDMenuHandler::SetDisplayable |
|
183 // |
|
184 // |
|
185 // ----------------------------------------------------------------------------- |
|
186 // |
|
187 void CMIDMenuHandler::SetDisplayable(CMIDDisplayable* aDisplayable) |
|
188 { |
|
189 iDisplayable = aDisplayable; |
|
190 |
|
191 if (iDisplayable) |
|
192 { |
|
193 SendMultipleKeyPressedEvent(); |
|
194 } |
|
195 } |
|
196 // ----------------------------------------------------------------------------- |
|
197 // CMIDMenuHandler::SendMultipleKeyPressedEventL |
|
198 // |
|
199 // |
|
200 // ----------------------------------------------------------------------------- |
|
201 // |
|
202 void CMIDMenuHandler::SendMultipleKeyPressedEvent() |
|
203 { |
|
204 ASSERT(iDisplayable); |
|
205 |
|
206 RWsSession wsSession = CCoeEnv::Static()->WsSession(); |
|
207 TWsEvent event; |
|
208 |
|
209 // Check the current Display type if it is canvas enable the |
|
210 // multiple key events, other wise disable it. |
|
211 MMIDComponent* component = iDisplayable->Component(); |
|
212 MMIDComponent::TType type = component->Type(); |
|
213 |
|
214 if (type == MMIDComponent::ECanvas) |
|
215 event.SetType(EEnableMultipleKeyPressedEvent); // set event type enable multiple key pressed event |
|
216 else |
|
217 event.SetType(EDisableMultipleKeyPressedEvent); // set event type disable multiple key pressed event |
|
218 event.SetTimeNow(); // set the event time |
|
219 event.SetHandle(wsSession.WsHandle()); // set window server handle |
|
220 wsSession.SendEventToAllWindowGroups(event); |
|
221 } |
|
222 |
|
223 |
|
224 // ----------------------------------------------------------------------------- |
|
225 // CMIDMenuHandler::ProcessCommandL |
|
226 // |
|
227 // |
|
228 // ----------------------------------------------------------------------------- |
|
229 // |
|
230 void CMIDMenuHandler::ProcessCommandL(TInt aCommandId) |
|
231 { |
|
232 HideMenuIfVisible(); |
|
233 |
|
234 // |
|
235 if (aCommandId == EAknSoftkeyExit) |
|
236 { |
|
237 iAppUi->HandleCommandL(EEikCmdExit); |
|
238 return; |
|
239 } |
|
240 |
|
241 if (aCommandId == EEikCmdCanceled) |
|
242 { |
|
243 return; |
|
244 } |
|
245 |
|
246 if (aCommandId == EAknSoftkeyOptions) |
|
247 { |
|
248 ShowMenuL(EOptionsMenu); |
|
249 return; |
|
250 } |
|
251 |
|
252 if (aCommandId == EStdKeyDevice3) |
|
253 { |
|
254 ShowMenuL(EOkMenu); |
|
255 return; |
|
256 } |
|
257 |
|
258 if (iDisplayable) |
|
259 { |
|
260 iDisplayable->ProcessCommandL(aCommandId); |
|
261 } |
|
262 } |
|
263 |
|
264 // ----------------------------------------------------------------------------- |
|
265 // CMIDMenuHandler::SetEmphasis |
|
266 // |
|
267 // |
|
268 // ----------------------------------------------------------------------------- |
|
269 // |
|
270 void CMIDMenuHandler::SetEmphasis(CCoeControl* aMenuControl,TBool aEmphasis) |
|
271 { |
|
272 if (!iDisplayable) |
|
273 { |
|
274 return; |
|
275 } |
|
276 |
|
277 if (aEmphasis) |
|
278 { |
|
279 if (MMIDComponent::ECanvas == iDisplayable->Component()->Type()) |
|
280 { |
|
281 iEnv.PostMidletEvent(EBackground); |
|
282 } |
|
283 } |
|
284 else |
|
285 { |
|
286 if (MMIDComponent::ECanvas == iDisplayable->Component()->Type()) |
|
287 { |
|
288 iEnv.PostMidletEvent(EForeground); |
|
289 } |
|
290 } |
|
291 |
|
292 iAppUi->UpdateStackedControlFlags(aMenuControl, aEmphasis? 0: ECoeStackFlagRefusesFocus, |
|
293 ECoeStackFlagRefusesFocus); |
|
294 iAppUi->HandleStackChanged(); |
|
295 } |
|
296 |
|
297 // ----------------------------------------------------------------------------- |
|
298 // CMIDMenuHandler::DynInitMenuPaneL |
|
299 // |
|
300 // |
|
301 // ----------------------------------------------------------------------------- |
|
302 void CMIDMenuHandler::DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane) |
|
303 { |
|
304 if (aResourceId == R_MIDP_MENUPANE_DISPLAYABLE) |
|
305 { |
|
306 TInt numItems = iMenuItems.Count(); |
|
307 for (TInt i = 0; i < numItems; i++) |
|
308 { |
|
309 aMenuPane->AddMenuItemL(iMenuItems[i]); |
|
310 } |
|
311 |
|
312 iAttemptingToDisplayMenu = EFalse; |
|
313 } |
|
314 |
|
315 } |
|
316 |
|
317 |
|
318 /** SetScalingFactors |
|
319 |
|
320 Sets MIDlet's original size and target size resolutions if those are defined in JAD or manifest. |
|
321 If attribute is missing or it's not defined correctly, the value will be 0,0. |
|
322 This value is later used as an "error value". |
|
323 @param - |
|
324 @return - |
|
325 |
|
326 */ |
|
327 void CMIDMenuHandler::SetScalingFactors() |
|
328 { |
|
329 TPtrC orgSize; |
|
330 // If JAD attribute Nokia-MIDlet-Original-Display-Size is defined, it will be used to scale Canvas. |
|
331 if (iEnv.MidletAttribute(LcduiMidletAttributes::KAttribOrigDisplaySize, orgSize) == KErrNone) |
|
332 { |
|
333 iOrgMIDletScrSize = DesToTSize(orgSize); |
|
334 TPtrC targetSize; |
|
335 // If JAD attribute Nokia-MIDlet-Original-Display-Size and Nokia-MIDlet-Target-Display-Size are defined, |
|
336 // those will be used to scale Canvas. |
|
337 // If Nokia-MIDlet-Target-Display-Size is invalid, Canvas will still be scaled, |
|
338 // if Nokia-MIDlet-Original-Display-Size is correct. |
|
339 if (iOrgMIDletScrSize.iHeight != 0 && iOrgMIDletScrSize.iWidth != 0 && |
|
340 iEnv.MidletAttribute(LcduiMidletAttributes::KAttribTargetDisplaySize, |
|
341 targetSize) == KErrNone) |
|
342 { |
|
343 iTargetMIDletScrSize = DesToTSize(targetSize); |
|
344 } |
|
345 |
|
346 // Load Nokia-MIDlet-allow-scaling-on-orientation-switch attribute |
|
347 // setting. This attribute is valid only when original MIDlet size |
|
348 // is defined. |
|
349 if (iOrgMIDletScrSize.iHeight != 0 && iOrgMIDletScrSize.iWidth != 0) |
|
350 { |
|
351 iScaleMIDletOnOrientSwitch = iEnv.MidletAttributeIsSetToVal( |
|
352 LcduiMidletAttributes::KAttribAllowScalingOnOrientationSwitch, |
|
353 LcduiMidletAttributeValues::KTrueValue); |
|
354 } |
|
355 } |
|
356 } |
|
357 |
|
358 /** DesToTSize |
|
359 |
|
360 Utility to parse TPtrC to TSize. |
|
361 This util is made for graphics scaling feature. |
|
362 @param TPtrC |
|
363 @return TSize |
|
364 |
|
365 */ |
|
366 TSize CMIDMenuHandler::DesToTSize(TPtrC scrSize) |
|
367 { |
|
368 TSize newSize; |
|
369 TSize errorSize(0, 0); |
|
370 TInt newIntWidth; |
|
371 TInt newIntHeight; |
|
372 // Assumed max. 9999 pixels in width. |
|
373 TBuf<KResolutionStringLength> newWidth; |
|
374 // Assumed max. 9999 pixels in height. |
|
375 TBuf<KResolutionStringLength> newHeight; |
|
376 TChar tmpChar; |
|
377 _LIT(lComma, ","); |
|
378 TChar comma(','); |
|
379 |
|
380 // The digits of width and height must be divided by comma |
|
381 if (scrSize.Find(lComma) != KErrNotFound) |
|
382 { |
|
383 TLex16 lex(scrSize); |
|
384 while (lex.Peek() != comma) |
|
385 { |
|
386 tmpChar = lex.Get(); |
|
387 if (tmpChar.IsDigit() && newWidth.Length() < KResolutionStringLength) |
|
388 { |
|
389 newWidth.Append(tmpChar); |
|
390 } |
|
391 else if (!tmpChar.IsSpace()) |
|
392 { |
|
393 // If character is not digit or space |
|
394 return errorSize; |
|
395 } |
|
396 } |
|
397 lex.Get(); |
|
398 while (!lex.Eos()) |
|
399 { |
|
400 tmpChar = lex.Get(); |
|
401 if (tmpChar.IsDigit() && newHeight.Length() < KResolutionStringLength) |
|
402 { |
|
403 newHeight.Append(tmpChar); |
|
404 } |
|
405 else if (!tmpChar.IsSpace()) |
|
406 { |
|
407 // If character is not digit or space |
|
408 return errorSize; |
|
409 } |
|
410 } |
|
411 |
|
412 // Width and height must have at least one digit each |
|
413 if (newWidth.Length() > 0 && newHeight.Length() > 0) |
|
414 { |
|
415 TLex16 widthLex(newWidth); |
|
416 widthLex.Val(newIntWidth); |
|
417 TLex16 heightLex(newHeight); |
|
418 heightLex.Val(newIntHeight); |
|
419 newSize.SetSize(TInt(newIntWidth), TInt(newIntHeight)); |
|
420 return newSize; |
|
421 } |
|
422 } |
|
423 // If there is no comma between the digits or there is no digits in width or height |
|
424 return errorSize; |
|
425 } |
|
426 |
|
427 TSize CMIDMenuHandler::GetScreenSize() const |
|
428 { |
|
429 // It get size of screen from iEikEnv's screen device. |
|
430 const CEikonEnv* env = &iEikEnv; |
|
431 return env->ScreenDevice()->SizeInPixels(); |
|
432 } |
|
433 |
|
434 TBool CMIDMenuHandler::IsScalingEnabled() const |
|
435 { |
|
436 //If iOrgMIDletScrSize has been initialized then scaling is on. |
|
437 //It's enough to check either height or width only. |
|
438 return (iOrgMIDletScrSize.iHeight != 0); |
|
439 } |
|
440 |
|
441 TBool CMIDMenuHandler::IsScalingEffectiveInCurrentScreen() const |
|
442 { |
|
443 if (IsScalingEnabled()) |
|
444 { |
|
445 TRect screen; |
|
446 AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, screen); |
|
447 TSize screenSize = screen.Size(); |
|
448 |
|
449 TSize origResolution = iOrgMIDletScrSize; |
|
450 if (iScaleMIDletOnOrientSwitch) |
|
451 { |
|
452 // ensure that origResolution and screenSize are in portrait |
|
453 origResolution = TSize(Min(iOrgMIDletScrSize.iHeight, iOrgMIDletScrSize.iWidth), |
|
454 Max(iOrgMIDletScrSize.iHeight, iOrgMIDletScrSize.iWidth)); |
|
455 screenSize = TSize(Min(screen.Height(), screen.Width()), |
|
456 Max(screen.Height(), screen.Width())); |
|
457 } |
|
458 |
|
459 // If origResolution and screenSize are different, then |
|
460 // scaling is effective. |
|
461 return (screenSize.iHeight != origResolution.iHeight || |
|
462 screenSize.iWidth != origResolution.iWidth); |
|
463 } |
|
464 else |
|
465 { |
|
466 return EFalse; |
|
467 } |
|
468 } |
|
469 // End of File |