|
1 /* |
|
2 * Copyright (c) 2003-2007 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: ?Description |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <eiklabel.h> |
|
20 // AknsUtils used for label and content colors settings |
|
21 #include <AknsDrawUtils.h> |
|
22 // skins for drawing |
|
23 #include <skinlayout.cdl.h> |
|
24 #include <AknUtils.h> |
|
25 #include <applayout.cdl.h> |
|
26 // LAF |
|
27 #include <aknlayoutscalable_avkon.cdl.h> |
|
28 #include <aknconsts.h> |
|
29 #include <avkon.mbg> |
|
30 |
|
31 #include "CMIDStringItem.h" |
|
32 // API for iCommandList |
|
33 #include "CMIDCommandList.h" |
|
34 // some API for text formating before label settings |
|
35 #include "CMIDUtils.h" |
|
36 // CMIDItemLabel* iContentControl |
|
37 #include "CMIDItemLabel.h" |
|
38 |
|
39 #include <j2me/jdebug.h> |
|
40 |
|
41 |
|
42 /** This constant determines the maximum number |
|
43 of lines for button labels and content */ |
|
44 const TInt KMaxNumLinesForButtons = 10; |
|
45 |
|
46 /** Content can have unlimited lines */ |
|
47 const TInt KMaxNumLinesForContent = -1; |
|
48 |
|
49 // --------------------------------------------------------------------------- |
|
50 // |
|
51 // --------------------------------------------------------------------------- |
|
52 // |
|
53 MMIDStringItem* CMIDStringItem::NewL( |
|
54 const TDesC& aLabel, const TDesC& aText, TAppearance aAppearance, CMIDUIManager* aUIManager) |
|
55 { |
|
56 CMIDStringItem* item=new(ELeave) CMIDStringItem(aAppearance, aUIManager); |
|
57 CleanupStack::PushL(item); |
|
58 item->ConstructL(aLabel,aText); |
|
59 CleanupStack::Pop(item); |
|
60 return item; |
|
61 } |
|
62 |
|
63 /** |
|
64 * Assumes label has been set before in order to work out if a prefix is |
|
65 * required |
|
66 */ |
|
67 void CMIDStringItem::SetTextL(const TDesC& aText) |
|
68 { |
|
69 DEBUG("CMIDStringItem::SetTextL - begin"); |
|
70 |
|
71 delete iText; |
|
72 iText = NULL; |
|
73 |
|
74 // count the newlines at the beginning and the end of the content |
|
75 CountNewlinesBeforeAndAfter(aText); |
|
76 |
|
77 // create a TPtrC of the string without the beginning and training newlines |
|
78 TPtrC ptr; |
|
79 if (iNumNewlinesBefore < aText.Length()) |
|
80 { |
|
81 ptr.Set(aText.Mid(iNumNewlinesBefore, aText.Length() - |
|
82 (iNumNewlinesBefore + iNumNewlinesAfter))); |
|
83 } |
|
84 |
|
85 iText = ptr.AllocL(); |
|
86 if (iText->Length() != 0) |
|
87 { |
|
88 CMIDUtils::MapJavaToETextChars(iText); |
|
89 } |
|
90 |
|
91 iContentControl->SetTextL(*iText); |
|
92 if (iAppearance == MMIDItem::EButton) |
|
93 { |
|
94 // leave only text before line separator, if any |
|
95 TInt i = 0; |
|
96 while ((i < iText->Length()) && (!CMIDUtils::IsLineSeparator((*iText)[i]))) |
|
97 { |
|
98 i++; |
|
99 } |
|
100 ptr.Set(iText->Mid(0, i)); |
|
101 |
|
102 // if there was line separator add ellipis in the end |
|
103 HBufC* textWithEllipsis = HBufC::NewLC(i + 1); |
|
104 textWithEllipsis->Des().Append(ptr); // text without line separators |
|
105 if (i < iText->Length()) |
|
106 { |
|
107 // if there was line separator add ellipsis in the end |
|
108 textWithEllipsis->Des().Append(KEllipsis); |
|
109 } |
|
110 |
|
111 iButton->State()->SetTextL(textWithEllipsis->Des()); |
|
112 |
|
113 CleanupStack::PopAndDestroy(textWithEllipsis); |
|
114 } |
|
115 |
|
116 if (iForm) |
|
117 { |
|
118 iForm->RequestLayoutL(); |
|
119 } |
|
120 DEBUG("CMIDStringItem::SetTextL - end"); |
|
121 } |
|
122 |
|
123 // --------------------------------------------------------------------------- |
|
124 // |
|
125 // --------------------------------------------------------------------------- |
|
126 // |
|
127 CMIDStringItem::CMIDStringItem(TAppearance aAppearance, CMIDUIManager* aUIManager) |
|
128 : CMIDControlItem(EDefault, aUIManager), |
|
129 iAppearance(aAppearance), |
|
130 iIsDivided(EFalse) |
|
131 { |
|
132 iMMidItem = this; |
|
133 } |
|
134 |
|
135 void CMIDStringItem::ConstructL(const TDesC& aLabel,const TDesC& aText) |
|
136 { |
|
137 DEBUG("CMIDStringItem::ConstructL - begin"); |
|
138 // Initializes the label control |
|
139 CMIDControlItem::ConstructL(); |
|
140 |
|
141 if (iAppearance == MMIDItem::EButton) |
|
142 { //buttons can only have one line |
|
143 |
|
144 iButton = CAknButton::NewL(NULL, // aIcon |
|
145 NULL, // aDimmedIcon |
|
146 NULL, // aPressedIcon |
|
147 NULL, // aHoverIcon |
|
148 aText, |
|
149 KNullDesC, |
|
150 KAknButtonSizeFitText, // iFlags set to respect text width |
|
151 0); |
|
152 iLabelControl->SetMaxNumLines(KMaxNumLinesForButtons); |
|
153 } |
|
154 // iContentControl is always created because RenderedAppearance() can be PLAIN |
|
155 iContentControl = CMIDItemLabel::NewL(FormClientAreaWidth(), ETrue, |
|
156 KMaxNumLinesForContent, CMIDFont::EDefaultTextId, ETrue); |
|
157 |
|
158 |
|
159 SetLabelL(aLabel); |
|
160 SetTextL(aText); // Sets CMIDStringitem::iText |
|
161 iContentControl->SetFont(Font()); |
|
162 if (iAppearance != MMIDItem::EButton) |
|
163 { |
|
164 MMIDFont* font = Font(); |
|
165 if (font) |
|
166 { |
|
167 iButton->SetTextFont(font->Font()); |
|
168 } |
|
169 } |
|
170 SetColorL(); |
|
171 |
|
172 if (iAppearance == MMIDItem::EButton) |
|
173 { |
|
174 CalculateButtonEllipsedSizeL(); |
|
175 } |
|
176 ResetPreferredSize(); |
|
177 |
|
178 #ifdef RD_TACTILE_FEEDBACK |
|
179 iFeedback = MTouchFeedback::Instance(); |
|
180 #endif |
|
181 |
|
182 DEBUG("CMIDStringItem::ConstructL - end"); |
|
183 } |
|
184 |
|
185 CMIDStringItem::~CMIDStringItem() |
|
186 { |
|
187 delete iText; |
|
188 delete iContentControl; |
|
189 delete iButton; |
|
190 } |
|
191 |
|
192 void CMIDStringItem::SetContainerWindowL(const CCoeControl& aContainer) |
|
193 { |
|
194 CMIDControlItem::SetContainerWindowL(aContainer); |
|
195 iContentControl->SetContainerWindowL(*this); |
|
196 if (iAppearance == MMIDItem::EButton) |
|
197 { |
|
198 iButton->SetContainerWindowL(*this); |
|
199 } |
|
200 ActivateL(); |
|
201 } |
|
202 |
|
203 void CMIDStringItem::CountNewlinesBeforeAndAfter(const TDesC& aText) |
|
204 { |
|
205 TInt i = 0; |
|
206 |
|
207 iNumNewlinesBefore = 0; |
|
208 iNumNewlinesAfter = 0; |
|
209 while ((i < aText.Length()) && (aText[i] == '\n')) |
|
210 { |
|
211 iNumNewlinesBefore++; |
|
212 i++; |
|
213 } |
|
214 |
|
215 if (iNumNewlinesBefore == aText.Length()) |
|
216 { |
|
217 return; |
|
218 } |
|
219 |
|
220 // we get here if the string isn't all newlines |
|
221 i = aText.Length() - 1; |
|
222 while ((i >= 0) && (aText[i] == '\n')) |
|
223 { |
|
224 iNumNewlinesAfter++; |
|
225 i--; |
|
226 } |
|
227 } |
|
228 |
|
229 TBool CMIDStringItem::IsSelectable() const |
|
230 { |
|
231 return (iCommandList->Count() > 0); |
|
232 } |
|
233 |
|
234 /** |
|
235 * Sets the preferred width and height for this Item. If the width is between zero and |
|
236 * the minimum width, inclusive, the minimum width is used. If the height is between |
|
237 * zero and the minimum height, inclusive, the minimum height is used. |
|
238 * By default, the preferred width and height are based entirely on the Item's contents. |
|
239 * If both width and height parameters are -1, the default values for width and height |
|
240 * are established. If neither width nor height is -1, the values specified become the |
|
241 * Item's preferred size. |
|
242 * |
|
243 * If width is -1 and height is a legal value, the width will be computed based on the |
|
244 * item's contents and the given height. If height is -1 and width is a legal value, |
|
245 * the height will be computed based on the item's contents and the given width. |
|
246 * |
|
247 * If a StringItem has been assigned a preferred width or height by |
|
248 * the application, it is wrapped to fit that width and height and |
|
249 * is treated as a rectangle whose minimum and preferred width and height |
|
250 * are the width and height of this rectangle |
|
251 * |
|
252 * iPreferredSize includes margins. Margins are added in CMIDItemLabel class. |
|
253 */ |
|
254 void CMIDStringItem::SetPreferredSizeL(const TSize& aSize) |
|
255 { |
|
256 |
|
257 iRequestedPreferredSize = CheckRequestedSize(aSize); |
|
258 iPreferredSize = iRequestedPreferredSize; |
|
259 |
|
260 if (iPreferredSize.iWidth < 0) |
|
261 { // width is not specified |
|
262 if (RenderedAppearance() != MMIDItem::EButton) |
|
263 { |
|
264 iPreferredSize.iWidth = Max(iLabelControl->PreferredWidth(), |
|
265 iContentControl->PreferredWidth()); |
|
266 } |
|
267 else |
|
268 { |
|
269 iPreferredSize.iWidth = Max(iLabelControl->PreferredWidth(), |
|
270 iButton->MinimumSize().iWidth); |
|
271 // add margins |
|
272 TAknWindowLineLayout layout = |
|
273 AknLayoutScalable_Avkon::form2_midp_label_pane_cp(0).LayoutLine(); |
|
274 TInt leftMargin = layout.il; |
|
275 TInt rightMargin = layout.ir; |
|
276 iPreferredSize.iWidth += leftMargin + rightMargin; // add left and right margins |
|
277 } |
|
278 } |
|
279 |
|
280 TSize minimumSize = MinimumSize(); |
|
281 |
|
282 // make sure the width doesn't get bigger than the form width |
|
283 iPreferredSize.iWidth = Min(iPreferredSize.iWidth, FormClientAreaWidth()); |
|
284 |
|
285 // make sure the width doesn't get smaller than the minimum width |
|
286 iPreferredSize.iWidth = Max(iPreferredSize.iWidth, minimumSize.iWidth); |
|
287 |
|
288 // preferred width is set to label and content |
|
289 if (iLabelControl && iLabelControl->Text()->Length() > 0) |
|
290 { |
|
291 iLabelControl->SetWidthL(iPreferredSize.iWidth); |
|
292 } |
|
293 if (RenderedAppearance() != MMIDItem::EButton) |
|
294 { |
|
295 iContentControl->SetWidthL(iPreferredSize.iWidth); |
|
296 } |
|
297 else |
|
298 { |
|
299 SetButtonWidth(iPreferredSize.iWidth); |
|
300 } |
|
301 |
|
302 if (iPreferredSize.iHeight < 0) |
|
303 { // height is not specified, do text wrapping (call SetWidthL) |
|
304 // so that we can then calculate the height |
|
305 iPreferredSize.iHeight = LabelHeight() + ItemPreferredHeightWithoutLabel(); |
|
306 } |
|
307 |
|
308 //make sure the preferred size is not smaller than the minimum size |
|
309 iPreferredSize.iHeight = Max(iPreferredSize.iHeight, minimumSize.iHeight); |
|
310 |
|
311 if ((minimumSize.iWidth == 0) && (minimumSize.iHeight == 0)) |
|
312 { //it means there is no control and no label, so set our size to null |
|
313 iPreferredSize.iWidth = 0; |
|
314 iPreferredSize.iHeight = 0; |
|
315 } |
|
316 |
|
317 AdjustToSizeL(iPreferredSize); |
|
318 } |
|
319 |
|
320 TSize CMIDStringItem::MinimumSize() const |
|
321 { |
|
322 TInt numNewLines = iNumNewlinesBefore + iNumNewlinesAfter; |
|
323 TBool labelNotEmpty = (iLabelControl->Text()->Length() > 0); |
|
324 |
|
325 TInt width; |
|
326 TInt height; |
|
327 if (RenderedAppearance() != MMIDItem::EButton) |
|
328 { |
|
329 // if no label and no content then size is zero |
|
330 if (!labelNotEmpty && |
|
331 ((iContentControl->Text()->Length() == 0)) && (numNewLines == 0)) |
|
332 { |
|
333 return TSize(0, 0); |
|
334 } |
|
335 |
|
336 width = Max(iLabelControl->MinimumSize().iWidth, iContentControl->MinimumSize().iWidth); |
|
337 height = ( |
|
338 (iLabelControl && iLabelControl->Text()->Length() > 0) ? |
|
339 OneLineLabelHeight() : 0) + |
|
340 (iContentControl ? |
|
341 iContentControl->LineHeight() + iContentControl->ItemLabelMargin() : 0) + |
|
342 ItemContentBottomMargin(); |
|
343 |
|
344 if (width > FormClientAreaWidth()) |
|
345 { |
|
346 width = FormClientAreaWidth(); |
|
347 } |
|
348 } |
|
349 else |
|
350 { |
|
351 // if no label and no content then size is zero |
|
352 if (!labelNotEmpty |
|
353 &&((iButton->State()->Text().Length() == 0)) |
|
354 && (numNewLines == 0)) |
|
355 { |
|
356 return TSize(0, 0); |
|
357 } |
|
358 |
|
359 TInt width = iEllipsedButtonSize.iWidth; |
|
360 TInt height = iEllipsedButtonSize.iHeight; |
|
361 |
|
362 // add margins |
|
363 TAknWindowLineLayout layout = |
|
364 AknLayoutScalable_Avkon::form2_midp_label_pane_cp(0).LayoutLine(); |
|
365 TInt leftMargin = layout.il; |
|
366 TInt rightMargin = layout.ir; |
|
367 |
|
368 width = Max(iLabelControl->MinimumSize().iWidth, width); |
|
369 width += leftMargin + rightMargin; // add left and right margins |
|
370 |
|
371 if (labelNotEmpty) |
|
372 { |
|
373 height += OneLineLabelHeight() + ItemContentBottomMargin(); // add label and bottom margin |
|
374 } |
|
375 else |
|
376 { |
|
377 height += ItemContentBottomMargin(); // use the value for top margin |
|
378 } |
|
379 |
|
380 if (width > FormClientAreaWidth()) |
|
381 { |
|
382 width = FormClientAreaWidth(); |
|
383 } |
|
384 return TSize(width, height); |
|
385 } |
|
386 return TSize(width, height); |
|
387 } |
|
388 |
|
389 #ifdef RD_SCALABLE_UI_V2 |
|
390 void CMIDStringItem::HandlePointerEventL(const TPointerEvent &aPointerEvent) |
|
391 { |
|
392 if (AknLayoutUtils::PenEnabled()) |
|
393 { |
|
394 // check if string item is a hyperlink and colour the link according to activation/deactivation with pointer |
|
395 // note that want to colour the link and have tactile feedback even though have long tap |
|
396 if (RenderedAppearance() == EHyperLink) |
|
397 { |
|
398 if (aPointerEvent.iType == TPointerEvent::EButton1Down) |
|
399 { |
|
400 if (!HasLabel() || TappingActionRect().Contains(aPointerEvent.iPosition) || |
|
401 iForm->StringItemContainsPoint(this, aPointerEvent.iPosition)) |
|
402 { |
|
403 iHyperLinkActivated = ETrue; |
|
404 #ifdef RD_TACTILE_FEEDBACK |
|
405 // RenderedAppearance returns EHyperlink for initially hyperlink-created StringItem, |
|
406 // or for plain-created StringItem with commands added later. |
|
407 // if focus is changing, tactile feedback is given already in Form |
|
408 if (!iForm->IsFocusChangingWithPen()) |
|
409 { |
|
410 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK |
|
411 //Feedback for HYPERLINK only on touch down |
|
412 iFeedback->InstantFeedback(ETouchFeedbackSensitiveButton); |
|
413 #else |
|
414 iFeedback->InstantFeedback(ETouchFeedbackBasic); |
|
415 #endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK |
|
416 } |
|
417 #endif // RD_TACTILE_FEEDBACK |
|
418 } |
|
419 else // tap on label |
|
420 { |
|
421 iHyperLinkActivated = EFalse; |
|
422 } |
|
423 FocusChanged(EDrawNow); |
|
424 } |
|
425 } |
|
426 |
|
427 if (aPointerEvent.iType == TPointerEvent::EButton1Down) |
|
428 { |
|
429 iPointerDownOnContentArea = iForm->StringItemContainsPoint( |
|
430 this, aPointerEvent.iPosition); |
|
431 } |
|
432 |
|
433 // pass the event to the button |
|
434 if (iButton) |
|
435 { |
|
436 |
|
437 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK |
|
438 if (aPointerEvent.iType == TPointerEvent::EButton1Down && |
|
439 iForm->IsFocusChangingWithPen() && |
|
440 !(!HasLabel() || TappingActionRect().Contains(aPointerEvent.iPosition) || |
|
441 iForm->StringItemContainsPoint(this, aPointerEvent.iPosition))) |
|
442 { |
|
443 //On touch down, when focus is changing to this item and user |
|
444 //tapped to label (if exists), it should give sesitive list feedback |
|
445 iFeedback->InstantFeedback(ETouchFeedbackSensitiveList); |
|
446 } |
|
447 #endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK |
|
448 |
|
449 CCoeControl::HandlePointerEventL(aPointerEvent); |
|
450 } |
|
451 |
|
452 TBool consumed = iForm->TryDetectLongTapL(aPointerEvent); |
|
453 if (aPointerEvent.iType == TPointerEvent::EButton1Up) |
|
454 { |
|
455 // always remove hyperlink activated colour |
|
456 iHyperLinkActivated = EFalse; |
|
457 if (!consumed) |
|
458 { |
|
459 if (!iButton) |
|
460 { |
|
461 CMIDControlItem::HandlePointerEventL(aPointerEvent); |
|
462 } |
|
463 // check if the pen was dragged out of button and that pointer down has happened on content area, |
|
464 // i.e. dragging pointer from label to content area should not invoke any action. |
|
465 if (!iForm->PhysicsScrolling() && (iForm->StringItemContainsPoint(this, aPointerEvent.iPosition) && |
|
466 iPointerDownOnContentArea)) |
|
467 { |
|
468 iForm->HandleTouchControlEventL(this, MCoeControlObserver::EEventStateChanged); |
|
469 } |
|
470 } |
|
471 FocusChanged(EDrawNow); |
|
472 } |
|
473 } |
|
474 } |
|
475 #endif // RD_SCALABLE_UI_V2 |
|
476 |
|
477 /** Recalculate the preferred size.*/ |
|
478 TSize CMIDStringItem::ResetPreferredSize() const |
|
479 { |
|
480 CMIDStringItem* self = const_cast<CMIDStringItem*>(this); |
|
481 TRAP_IGNORE(self->SetPreferredSizeL(iRequestedPreferredSize)); |
|
482 return iPreferredSize; |
|
483 } |
|
484 |
|
485 /** @see CMIDControlItem::AdjustToNewWidthL() |
|
486 * Margins are added in CMIDItemLabel class */ |
|
487 void CMIDStringItem::AdjustToNewWidthL(TInt aWidth) |
|
488 { |
|
489 ASSERT(aWidth >= 0); |
|
490 |
|
491 if (aWidth != iPreferredSize.iWidth) |
|
492 { |
|
493 if (RenderedAppearance() != MMIDItem::EButton) |
|
494 { |
|
495 iContentControl->SetWidthL(aWidth); |
|
496 } |
|
497 else |
|
498 { |
|
499 SetButtonWidth(aWidth); |
|
500 } |
|
501 } |
|
502 CMIDControlItem::AdjustToNewWidthL(aWidth); |
|
503 } |
|
504 |
|
505 |
|
506 /** This method is never called by C++ side, only java side. CMIDItem::PreferredSize() is |
|
507 called instead, which returns the minimum between iPreferredSize and the minimum size. |
|
508 */ |
|
509 TSize CMIDStringItem::PreferredSize() const |
|
510 { |
|
511 return iPreferredSize; |
|
512 } |
|
513 |
|
514 // return Item appearance |
|
515 MMIDItem::TAppearance CMIDStringItem::Appearance() const |
|
516 { |
|
517 return iAppearance; |
|
518 } |
|
519 |
|
520 /** This method is never called by C++ side, only java side. CMIDItem::PreferredSize() is |
|
521 called instead, which returns the minimum between iPreferredSize and the minimum size. |
|
522 */ |
|
523 TSize CMIDStringItem::PreferredSize() |
|
524 { |
|
525 return iPreferredSize; |
|
526 } |
|
527 |
|
528 // We display a string as a hyperlink or a button depending on both its appearance and if it has any commands |
|
529 void CMIDStringItem::AddCommandL(MMIDCommand* aCommand) |
|
530 { |
|
531 DEBUG("CMIDStringItem::AddCommandL - begin"); |
|
532 CMIDItem::AddCommandL(aCommand); |
|
533 |
|
534 TBool underlined = (iFont ? iFont->IsUnderlined() : EFalse) || |
|
535 (RenderedAppearance() == EHyperLink); |
|
536 |
|
537 iContentControl->SetUnderlined(underlined); |
|
538 if (iForm) |
|
539 { |
|
540 iForm->RequestLayoutL(); |
|
541 } |
|
542 if (RenderedAppearance() == MMIDItem::EButton) |
|
543 { |
|
544 iButton->SetTextUnderlineStyle((underlined?EUnderlineOn:EUnderlineOff)); |
|
545 } |
|
546 DEBUG("CMIDStringItem::AddCommandL - end"); |
|
547 } |
|
548 |
|
549 // We display a string as a hyperlink or a button depending on both its appearance and if it has any commands |
|
550 void CMIDStringItem::RemoveCommand(MMIDCommand* aCommand) |
|
551 { |
|
552 DEBUG("CMIDStringItem::RemoveCommand - begin"); |
|
553 |
|
554 CMIDItem::RemoveCommand(aCommand); |
|
555 |
|
556 TBool underlined = (iFont ? iFont->IsUnderlined() : EFalse) || |
|
557 (RenderedAppearance() == EHyperLink); |
|
558 |
|
559 iContentControl->SetUnderlined(underlined); |
|
560 if (iForm) |
|
561 { |
|
562 TRAP_IGNORE(iForm->RequestLayoutL()); |
|
563 } |
|
564 if (RenderedAppearance() == MMIDItem::EButton) |
|
565 { |
|
566 iButton->SetTextUnderlineStyle((underlined?EUnderlineOn:EUnderlineOff)); |
|
567 } |
|
568 DEBUG("CMIDStringItem::RemoveCommand - end"); |
|
569 } |
|
570 |
|
571 void CMIDStringItem::SetDefaultCommand(MMIDCommand* aCommand) |
|
572 { |
|
573 DEBUG("CMIDStringItem::SetDefaultCommand - begin"); |
|
574 CMIDItem::SetDefaultCommand(aCommand); |
|
575 DEBUG("CMIDStringItem::SetDefaultCommand - end"); |
|
576 } |
|
577 |
|
578 void CMIDStringItem::SetFontL(MMIDFont* aFont) |
|
579 { |
|
580 iFont = aFont; |
|
581 |
|
582 iContentControl->SetFont(iFont); |
|
583 |
|
584 TBool underlined = (iFont ? iFont->IsUnderlined() : EFalse) || |
|
585 (RenderedAppearance() == EHyperLink); |
|
586 |
|
587 iContentControl->SetUnderlined(underlined); |
|
588 |
|
589 if (iAppearance == MMIDItem::EButton) |
|
590 { |
|
591 iButton->SetTextFont(aFont->Font()); |
|
592 iButton->SetTextUnderlineStyle((underlined?EUnderlineOn:EUnderlineOff)); |
|
593 CalculateButtonEllipsedSizeL(); |
|
594 } |
|
595 ResetPreferredSize(); |
|
596 } |
|
597 |
|
598 /** |
|
599 * Returns the label WITH the prefix if it's not a control, and WITHOUT if it is. |
|
600 */ |
|
601 TPtrC CMIDStringItem::Label() const |
|
602 { |
|
603 return *iLabel; |
|
604 } |
|
605 |
|
606 const TDesC& CMIDStringItem::Text() const |
|
607 { |
|
608 return *iText; |
|
609 } |
|
610 |
|
611 /** |
|
612 Because MMIDItem declares a pure virtual const method called MinimumSize() |
|
613 whilst CCoeControl has a virtual non const method called MinimumSize() |
|
614 we are forced to make sure these two methods behave in the same way |
|
615 in every item and hence the non cost method calls the const method. |
|
616 |
|
617 We cannot do this once and for all in CMIDControlItem because only |
|
618 concrete items inherit from the MMID LCDUI framework classes: |
|
619 |
|
620 CCoeControl MMIDItem |
|
621 | | |
|
622 CMIDItem MMIDStringItem |
|
623 | | |
|
624 CMIDControlItem | |
|
625 | | |
|
626 CMISStringItem-------------------- |
|
627 |
|
628 This is true for every other item. |
|
629 */ |
|
630 TSize CMIDStringItem::MinimumSize() |
|
631 { |
|
632 const CMIDStringItem* self = const_cast<const CMIDStringItem*>(this); |
|
633 |
|
634 return self->MinimumSize(); |
|
635 } |
|
636 |
|
637 TInt CMIDStringItem::CountComponentControls() const |
|
638 { |
|
639 return 2; |
|
640 } |
|
641 |
|
642 CCoeControl* CMIDStringItem::ComponentControl(TInt aIndex) const |
|
643 { |
|
644 switch (aIndex) |
|
645 { |
|
646 case 0: |
|
647 return iLabelControl; |
|
648 case 1: |
|
649 if (RenderedAppearance() != MMIDItem::EButton) |
|
650 { |
|
651 return iContentControl; |
|
652 } |
|
653 else |
|
654 { |
|
655 return iButton; |
|
656 } |
|
657 } |
|
658 return NULL; |
|
659 } |
|
660 |
|
661 /** |
|
662 * Sets label and content colors according to the appearance mode and focusing info |
|
663 */ |
|
664 void CMIDStringItem::SetColorL() |
|
665 { |
|
666 DEBUG("CMIDStringItem::SetColorL - begin"); |
|
667 // Create & initialize a color variable according to the focus & appearance info |
|
668 TBool focused = IsFocused(); |
|
669 TRgb labelColor; |
|
670 TRgb contentColor; |
|
671 TRgb color; |
|
672 // Set colors in case of plain |
|
673 // NOTE: All items (e.g hyperlinks) are rendered as plain if there are no commands. |
|
674 if (RenderedAppearance() == MMIDItem::EPlain) |
|
675 { |
|
676 // The appearance mode is the EPlain. |
|
677 DEBUG("CMIDStringItem::SetColorL - EPlain"); |
|
678 // Same color - no matter if focused or not |
|
679 AknsUtils::GetCachedColor( |
|
680 AknsUtils::SkinInstance(), color, |
|
681 KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG8); |
|
682 labelColor = color; |
|
683 contentColor = color; |
|
684 } |
|
685 else |
|
686 { |
|
687 // The appearance mode is EHyperLink or EButton |
|
688 DEBUG("CMIDStringItem::SetColorL - not EPlain"); |
|
689 if (focused) |
|
690 { |
|
691 // Item is focused |
|
692 // If item is focused, label is always focused, |
|
693 AknsUtils::GetCachedColor( |
|
694 AknsUtils::SkinInstance(), labelColor, |
|
695 KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG10); |
|
696 |
|
697 if (RenderedAppearance() == MMIDItem::EHyperLink) |
|
698 { |
|
699 if (iHyperLinkActivated) |
|
700 // link was activated |
|
701 { |
|
702 AknsUtils::GetCachedColor( |
|
703 AknsUtils::SkinInstance(), contentColor, |
|
704 KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG10); |
|
705 } |
|
706 else |
|
707 // link was not activated |
|
708 { |
|
709 AknsUtils::GetCachedColor( |
|
710 AknsUtils::SkinInstance(), contentColor, |
|
711 KAknsIIDQsnTextColors, EAknsCIQsnHighlightColorsCG3); |
|
712 } |
|
713 } |
|
714 } |
|
715 else |
|
716 { |
|
717 // Item is not focused |
|
718 AknsUtils::GetCachedColor( |
|
719 AknsUtils::SkinInstance(), labelColor, |
|
720 KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG8); |
|
721 AknsUtils::GetCachedColor( |
|
722 AknsUtils::SkinInstance(), contentColor, |
|
723 KAknsIIDQsnHighlightColors, EAknsCIQsnHighlightColorsCG3); |
|
724 } |
|
725 |
|
726 if (RenderedAppearance() == MMIDItem::EButton) |
|
727 { |
|
728 // Note: BorderColor() is the color of the border internal background, not the outline |
|
729 ColorUtils::GetRgbDerivedBorderColors( |
|
730 iBorderColors, BorderColor(), iEikonEnv->DefaultDisplayMode()); |
|
731 } |
|
732 } |
|
733 // Set content & label colors |
|
734 if (RenderedAppearance() != MMIDItem::EButton) |
|
735 { |
|
736 iContentControl->SetColorL(contentColor); |
|
737 } |
|
738 iLabelControl->SetColorL(labelColor); |
|
739 |
|
740 // Text color for CAknButton has to be set |
|
741 if (RenderedAppearance() == MMIDItem::EButton) |
|
742 { |
|
743 if (iButton) |
|
744 { |
|
745 iButton->SetTextColorIds( |
|
746 KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG8); |
|
747 } |
|
748 } |
|
749 |
|
750 DEBUG("CMIDStringItem::SetColorL - end"); |
|
751 } |
|
752 |
|
753 |
|
754 /** The color for the border background in buttons. |
|
755 */ |
|
756 TRgb CMIDStringItem::BorderColor() const |
|
757 { |
|
758 DEBUG("CMIDStringItem::BorderColor - begin"); |
|
759 |
|
760 TRgb color; |
|
761 AknsUtils::GetCachedColor( |
|
762 AknsUtils::SkinInstance(), color, |
|
763 KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG12); |
|
764 DEBUG("CMIDStringItem::BorderColor - end"); |
|
765 return color; |
|
766 } |
|
767 |
|
768 /** Draw a frame (border) for buttons and then draw the grid highlight frame if |
|
769 we have focus. Note: only hyperlinks and buttons can have focus. */ |
|
770 void CMIDStringItem::Draw(const TRect& aRect) const |
|
771 { |
|
772 DEBUG("CMIDStringItem::Draw - begin"); |
|
773 |
|
774 if (RenderedAppearance() == MMIDItem::EButton) |
|
775 { |
|
776 // To avoid clipping button's border to the form's client area |
|
777 // we pass entire button's rectangle - Rect() - as parameter |
|
778 Border().Draw(SystemGc(), Rect(), iBorderColors); |
|
779 } |
|
780 |
|
781 if (IsFocused()) |
|
782 { //only buttons or hyperlinks |
|
783 DEBUG("CMIDStringItem::Draw - focused"); |
|
784 |
|
785 // A focused item e.g. hyperlink |
|
786 TAknLayoutRect topLeft; |
|
787 topLeft.LayoutRect(aRect, |
|
788 SkinLayout::List_highlight_skin_placing__apps_specific__Line_2()); |
|
789 |
|
790 TAknLayoutRect bottomRight; |
|
791 bottomRight.LayoutRect(aRect, |
|
792 SkinLayout::List_highlight_skin_placing__apps_specific__Line_5()); |
|
793 |
|
794 TRect outerRect = TRect(topLeft.Rect().iTl, bottomRight.Rect().iBr); |
|
795 TRect innerRect = TRect(topLeft.Rect().iBr, bottomRight.Rect().iTl); |
|
796 |
|
797 AknsDrawUtils::DrawFrame(AknsUtils::SkinInstance(), SystemGc(), |
|
798 outerRect, innerRect, |
|
799 KAknsIIDQsnFrList, KAknsIIDQsnFrListCenter); |
|
800 } |
|
801 DEBUG("CMIDStringItem::Draw - end"); |
|
802 } |
|
803 |
|
804 void CMIDStringItem::SizeChanged() |
|
805 { |
|
806 /* Margins are added in CMIDItemLabel class */ |
|
807 // If rects of label and content are layouted according to parent rect |
|
808 // their width should be the same as parent. So text within labels is |
|
809 // placed to proper side: to left in left-to right and to right in |
|
810 // right-to-left variants. |
|
811 iLabelControl->SetExtent(Position(), |
|
812 TSize(Size().iWidth, iLabelControl->Size().iHeight)); |
|
813 iContentControl->SetExtent(Position() + TPoint(0, LabelHeight()), |
|
814 TSize(Size().iWidth, iContentControl->Size().iHeight)); |
|
815 |
|
816 if (RenderedAppearance() == MMIDItem::EButton) |
|
817 { |
|
818 TBool labelEmpty = (iLabelControl->Text()->Length() == 0); |
|
819 |
|
820 TAknWindowLineLayout layout = |
|
821 AknLayoutScalable_Avkon::form2_midp_label_pane_cp(0).LayoutLine(); |
|
822 |
|
823 TInt leftMargin = layout.il; |
|
824 TInt rightMargin = layout.ir; |
|
825 TInt topMargin = ItemContentBottomMargin(); |
|
826 |
|
827 TPoint buttonPos = Position() + TPoint(0, LabelHeight()); |
|
828 TSize buttonSize = iSavedButtonSize; |
|
829 |
|
830 buttonPos += TPoint(leftMargin, 0); |
|
831 buttonSize -= TSize(leftMargin + rightMargin, 0); // these margins were added in MinimumSize() |
|
832 |
|
833 if (labelEmpty) |
|
834 { |
|
835 buttonPos += TPoint(0, topMargin); // shift down, we need some space above |
|
836 } |
|
837 |
|
838 iButton->SetExtent(buttonPos, buttonSize); |
|
839 } |
|
840 |
|
841 CMIDControlItem::SizeChanged(); |
|
842 } |
|
843 |
|
844 TKeyResponse CMIDStringItem::OfferKeyEventL(const TKeyEvent& /*aKeyEvent*/, TEventCode /*aType*/) |
|
845 { |
|
846 return EKeyWasNotConsumed; |
|
847 } |
|
848 |
|
849 // this assumes that the item has been formatted by the form |
|
850 TInt CMIDStringItem::ItemPreferredHeightWithoutLabel() |
|
851 { |
|
852 if (iAppearance != MMIDItem::EButton) |
|
853 { |
|
854 return iContentControl->Size().iHeight + ItemContentBottomMargin(); |
|
855 } |
|
856 else |
|
857 { |
|
858 TInt height = iButton->Size().iHeight + ItemContentBottomMargin(); |
|
859 TBool labelEmpty = (iLabelControl->Text()->Length() == 0); |
|
860 if (labelEmpty) |
|
861 { |
|
862 height += ItemContentBottomMargin(); // add top margin |
|
863 } |
|
864 return height; |
|
865 } |
|
866 } |
|
867 |
|
868 TRect CMIDStringItem::FocusableRect() |
|
869 { |
|
870 TRect rect = Rect(); |
|
871 |
|
872 if (rect.iTl.iY > rect.iBr.iY) |
|
873 { |
|
874 TInt tmp = rect.iBr.iY; |
|
875 rect.iBr.iY = rect.iTl.iY; |
|
876 rect.iTl.iY = tmp; |
|
877 } |
|
878 |
|
879 return rect; |
|
880 } |
|
881 |
|
882 |
|
883 |
|
884 /** Set text colors according to the focus: label color stays |
|
885 the same as all other items (currently text entry), see CMIDControlItem::SetLabelColor(). |
|
886 Content colors is either NormalColor() or HighlightColor() according to focus. |
|
887 Note: only hyperlinks and buttons can have focus. Currently NormalColor() is text |
|
888 entry color (same as labels) whilst HighlightColor() is grid highlight text color. */ |
|
889 void CMIDStringItem::FocusChanged(TDrawNow aDrawNow) |
|
890 { |
|
891 DEBUG("CMIDStringItem::FocusChanged - begin"); |
|
892 |
|
893 TRAP_IGNORE(SetColorL()); |
|
894 |
|
895 if (EDrawNow == aDrawNow && DrawableWindow()) |
|
896 { |
|
897 if (!HasLabel() && RenderedAppearance() == EHyperLink) |
|
898 { |
|
899 // Have to do a call back to Form to draw a hyperlink without label correctly. |
|
900 // Note: a hyperlink without label is a CMIDLabelContainerItem and not a CMIDStringItem |
|
901 // Hyperlink without label is created by Form and this string item has no knowledge of it. |
|
902 // CMIDStringItem FocusChanged() is called when focus changes for drawing all kinds of string items even though |
|
903 // they are not necessarily drawn here. See CMIDLabelContainerItem too. |
|
904 iForm->DrawNow(); |
|
905 } |
|
906 else |
|
907 { |
|
908 if (iIsDivided) |
|
909 { |
|
910 // For correct drawing of StringItem with label which is divided |
|
911 // to CMIDLabelContainerItem objects due to concatenation of contents contained |
|
912 // in adjacent string items. |
|
913 iForm->DrawNow(); |
|
914 } |
|
915 else |
|
916 { |
|
917 DrawNow(); |
|
918 } |
|
919 } |
|
920 } |
|
921 DEBUG("CMIDStringItem::FocusChanged - end"); |
|
922 } |
|
923 |
|
924 MMIDItem::TAppearance CMIDStringItem::RenderedAppearance() const |
|
925 { |
|
926 TBool hasCommands(CommandList()->Count() > 0); |
|
927 if (hasCommands) |
|
928 { |
|
929 return (iAppearance == EButton) ? EButton : EHyperLink; |
|
930 } |
|
931 return EPlain; |
|
932 } |
|
933 |
|
934 CMIDItemLabel* CMIDStringItem::StringContentControl() const |
|
935 { |
|
936 return iContentControl; |
|
937 } |
|
938 |
|
939 TBool CMIDStringItem::IsUnconstrainedStringItem() |
|
940 { |
|
941 return !(WidthOrHeightSpecified() || (RenderedAppearance() == EButton)); |
|
942 } |
|
943 |
|
944 TBool CMIDStringItem::WidthOrHeightSpecified() const |
|
945 { |
|
946 return WidthSpecified() || HeightSpecified(); |
|
947 } |
|
948 |
|
949 TBool CMIDStringItem::WidthSpecified() const |
|
950 { |
|
951 return (iRequestedPreferredSize.iWidth != -1); |
|
952 } |
|
953 |
|
954 TBool CMIDStringItem::HeightSpecified() const |
|
955 { |
|
956 return (iRequestedPreferredSize.iHeight != -1); |
|
957 } |
|
958 |
|
959 /** |
|
960 Make sure label and content do not go beyond the available size. This method |
|
961 is called after setting the preferred size and when the row needs to size |
|
962 the items. If the item height (available height) cannot fit label and content |
|
963 then fit the label as much as possible and fit the control with the |
|
964 remaining height. However, reserve to the control at least one line. Because |
|
965 the minimumsize is one line for label (if available) and one line for control |
|
966 then there should always be space at least for one label line and for one control line. |
|
967 */ |
|
968 void CMIDStringItem::AdjustToSizeL(const TSize& aSize) |
|
969 { |
|
970 if (iAppearance != MMIDItem::EButton) |
|
971 { |
|
972 TInt availableHeight = aSize.iHeight; |
|
973 TInt requestedHeight = iContentControl->Size().iHeight; |
|
974 |
|
975 if (iLabelControl && iLabelControl->Text()->Length() > 0) |
|
976 { |
|
977 requestedHeight += LabelHeight(); |
|
978 } |
|
979 |
|
980 if (requestedHeight > availableHeight) |
|
981 {// label + control do not fit |
|
982 if (iLabelControl && iLabelControl->Text()->Length() > 0) |
|
983 { |
|
984 //reserve one line to the control |
|
985 TInt heightForLabel = iContentControl->Text()->Length() > 0 ? |
|
986 availableHeight - iContentControl->LineHeight() - iContentControl->ItemLabelMargin() : |
|
987 availableHeight; |
|
988 |
|
989 if (iLabelControl->Size().iHeight > heightForLabel) |
|
990 { //label does not fit |
|
991 |
|
992 //By setting a temporary max number of lines and then calling |
|
993 //SetWidthL() we limit the number of lines to the temporary max number |
|
994 //However then the max number must be resetted |
|
995 TInt oldMaxNumLabelLines = iLabelControl->MaxNumLines(); |
|
996 iLabelControl->SetMaxNumLines( |
|
997 (heightForLabel - iLabelControl->ItemLabelMargin())/ iLabelControl->LineHeight()); |
|
998 iLabelControl->SetWidthL(aSize.iWidth); |
|
999 iLabelControl->SetMaxNumLines(oldMaxNumLabelLines); |
|
1000 } |
|
1001 |
|
1002 //height available for the control |
|
1003 availableHeight -= iLabelControl->Size().iHeight; |
|
1004 } |
|
1005 |
|
1006 TInt oldMaxNumContentLines = iContentControl->MaxNumLines(); |
|
1007 iContentControl->SetMaxNumLines( |
|
1008 (availableHeight - iLabelControl->ItemLabelMargin()) / iContentControl->LineHeight()); |
|
1009 iContentControl->SetWidthL(aSize.iWidth); |
|
1010 iContentControl->SetMaxNumLines(oldMaxNumContentLines); |
|
1011 } |
|
1012 } |
|
1013 else |
|
1014 { |
|
1015 TInt availableHeight = aSize.iHeight; |
|
1016 TInt requestedHeight = iButton->Size().iHeight; |
|
1017 |
|
1018 if (iLabelControl && iLabelControl->Text()->Length() > 0) |
|
1019 { |
|
1020 requestedHeight += LabelHeight(); |
|
1021 } |
|
1022 |
|
1023 if (requestedHeight > availableHeight) |
|
1024 {// label + control do not fit |
|
1025 if (iLabelControl && iLabelControl->Text()->Length() > 0) |
|
1026 { |
|
1027 //reserve one line to the control |
|
1028 TInt heightForLabel = iButton->Size().iHeight; |
|
1029 |
|
1030 if (iLabelControl->Size().iHeight > heightForLabel) |
|
1031 { //label does not fit |
|
1032 |
|
1033 //By setting a temporary max number of lines and then calling |
|
1034 //SetWidthL() we limit the number of lines to the temporary max number |
|
1035 //However then the max number must be resetted |
|
1036 TInt oldMaxNumLabelLines = iLabelControl->MaxNumLines(); |
|
1037 iLabelControl->SetMaxNumLines( |
|
1038 (heightForLabel - iLabelControl->ItemLabelMargin())/ iLabelControl->LineHeight()); |
|
1039 iLabelControl->SetWidthL(aSize.iWidth); |
|
1040 iLabelControl->SetMaxNumLines(oldMaxNumLabelLines); |
|
1041 } |
|
1042 } |
|
1043 |
|
1044 SetButtonWidth(aSize.iWidth); |
|
1045 } |
|
1046 } |
|
1047 } |
|
1048 |
|
1049 |
|
1050 void CMIDStringItem::SetLabelL(const TDesC& aLabel) |
|
1051 { |
|
1052 CMIDControlItem::SetLabelL(aLabel); |
|
1053 } |
|
1054 |
|
1055 void CMIDStringItem::SetLayoutL(TLayout aLayout) |
|
1056 { |
|
1057 CMIDItem::SetLayoutL(aLayout); |
|
1058 } |
|
1059 |
|
1060 void CMIDStringItem::Dispose() |
|
1061 { |
|
1062 delete this; |
|
1063 } |
|
1064 |
|
1065 MMIDFont* CMIDStringItem::Font() const |
|
1066 { |
|
1067 return iFont; |
|
1068 } |
|
1069 |
|
1070 TInt CMIDStringItem::NumNewlinesBefore() |
|
1071 { |
|
1072 return iNumNewlinesBefore; |
|
1073 } |
|
1074 |
|
1075 TInt CMIDStringItem::NumNewlinesAfter() |
|
1076 { |
|
1077 return iNumNewlinesAfter; |
|
1078 } |
|
1079 |
|
1080 void CMIDStringItem::SetButtonWidth(TInt aNewWidth) |
|
1081 { |
|
1082 TSize buttonSize = iButton->Size(); |
|
1083 if (!buttonSize.iWidth || !buttonSize.iHeight) |
|
1084 { |
|
1085 buttonSize = iButton->MinimumSize(); |
|
1086 } |
|
1087 buttonSize.iWidth = aNewWidth; |
|
1088 iButton->SetSize(buttonSize); |
|
1089 iSavedButtonSize = buttonSize; |
|
1090 } |
|
1091 |
|
1092 // |
|
1093 // The area sensitive to actions is contentControl label for hyperlink and button for button appearance |
|
1094 // |
|
1095 TRect CMIDStringItem::TappingActionRect() |
|
1096 { |
|
1097 if (iAppearance != MMIDItem::EButton) |
|
1098 { |
|
1099 return iContentControl->Rect(); |
|
1100 } |
|
1101 else |
|
1102 { |
|
1103 return iButton->Rect(); |
|
1104 } |
|
1105 } |
|
1106 |
|
1107 void CMIDStringItem::ResolutionChange(TInt /*aType*/) |
|
1108 { |
|
1109 iContentControl->SetMaxWidth(FormClientAreaWidth()); |
|
1110 iLabelControl->SetMaxWidth(FormClientAreaWidth()); |
|
1111 } |
|
1112 |
|
1113 void CMIDStringItem::CalculateButtonEllipsedSizeL() |
|
1114 { |
|
1115 ASSERT(iAppearance == MMIDItem::EButton); |
|
1116 |
|
1117 TBuf<1> ellipsis; |
|
1118 ellipsis.Append(KEllipsis); |
|
1119 |
|
1120 CAknButton* tempButton = CAknButton::NewLC(NULL, // aIcon |
|
1121 NULL, // aDimmedIcon |
|
1122 NULL, // aPressedIcon |
|
1123 NULL, // aHoverIcon |
|
1124 ellipsis, |
|
1125 KNullDesC, |
|
1126 KAknButtonSizeFitText, // iFlags set to respect text width |
|
1127 0); |
|
1128 |
|
1129 iEllipsedButtonSize = tempButton->MinimumSize(); |
|
1130 CleanupStack::PopAndDestroy(tempButton); |
|
1131 } |
|
1132 |
|
1133 TBool CMIDStringItem::IsDivided() |
|
1134 { |
|
1135 return iIsDivided; |
|
1136 } |
|
1137 |
|
1138 void CMIDStringItem::SetIsDivided(TBool aIsDivided) |
|
1139 { |
|
1140 iIsDivided = aIsDivided; |
|
1141 } |
|
1142 |