1 /* |
|
2 * Copyright (c) 2009 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 * |
|
15 * Description: |
|
16 * Export help related files. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 // INCLUDE FILES |
|
24 #include "cimcvapprichtextcontainer.h" |
|
25 #include "cimcvappmessagewrapper.h" |
|
26 #include "mimcvapptextview.h" |
|
27 #include "cimcvappui.h" |
|
28 #include "mimcvenginemessage.h" |
|
29 #include "cimcvappmessageextensionshandler.h" |
|
30 |
|
31 #include <AknIconUtils.h> |
|
32 #include <txtrich.h> // CRichtText |
|
33 #include <AknSettingCache.h> |
|
34 #include <aknenv.h> |
|
35 #include <aknconsts.h> |
|
36 #include <finditemengine.h> |
|
37 #include <barsread.h> // resourcereader |
|
38 #include <StringLoader.h> |
|
39 |
|
40 #include <AknsDrawUtils.h> |
|
41 #include <AknsUtils.h> |
|
42 #include <AknUtils.h> |
|
43 #include "imcvlogger.h" |
|
44 #include "cimcvapppicture.h" |
|
45 #include <imcvuiapp.mbg> |
|
46 #include "cimcvappsmileiconutility.h" |
|
47 #include <imcvuiapp.rsg> |
|
48 |
|
49 // CONSTANTS |
|
50 const TInt KIMCVHighlightColor = 244; |
|
51 const TInt KTimeStampMaxLength = 15; // max length of timestamp text |
|
52 const TInt KUnicodeRLM = 0x200F; // Right-to-Left Mark |
|
53 const TInt KUnicodeLRM = 0x200E; // Left-to-Right Mark |
|
54 //Received message maximum length is 400 character, |
|
55 //this must always be in sync with imconnectionprovider KReceiveMsgMaxLength |
|
56 const TInt KReceiveMsgMaxLength = 400; |
|
57 const TInt KMsgMaxLength = 450; //Received message maximum length is 400 character + truncation message |
|
58 _LIT( KSeparator, ": " ); |
|
59 _LIT(KSpace, " "); |
|
60 |
|
61 |
|
62 // ============================ MEMBER FUNCTIONS =============================== |
|
63 |
|
64 // ----------------------------------------------------------------------------- |
|
65 // CIMCVAppRichTextContainer::CIMCVAppRichTextContainer |
|
66 // C++ default constructor can NOT contain any code, that |
|
67 // might leave. |
|
68 // ----------------------------------------------------------------------------- |
|
69 // |
|
70 CIMCVAppRichTextContainer::CIMCVAppRichTextContainer(MIMCVAppUi* aAppUi, |
|
71 MIMCVAppTextView* aTextView, |
|
72 CIMCVAppMessageExtensionsHandler* aExtensionsHandler, |
|
73 CGulIcon* aFromMe, |
|
74 CGulIcon* aToMe, |
|
75 MGraphicsDeviceMap* aMap, |
|
76 TInt aServiceId, |
|
77 TBool aScrollOver /*= ETrue*/): |
|
78 iAppUi(aAppUi), |
|
79 iTextView( aTextView ), |
|
80 iItemHighlight( ETrue ), |
|
81 iHighlightState( ENoHighlight ), |
|
82 iExtensionsHandler( aExtensionsHandler ), |
|
83 iScrollOver( aScrollOver ), |
|
84 iFromMe( aFromMe ), |
|
85 iToMe( aToMe ), |
|
86 iMap(aMap), |
|
87 iServiceId( aServiceId ) |
|
88 { |
|
89 } |
|
90 |
|
91 // ----------------------------------------------------------------------------- |
|
92 // CIMCVAppRichTextContainer::Initialize |
|
93 // Initializes iTextView |
|
94 // ----------------------------------------------------------------------------- |
|
95 // |
|
96 void CIMCVAppRichTextContainer::Initialize( MIMCVAppUi* aAppUi, |
|
97 MIMCVAppTextView* aTextView, |
|
98 CIMCVAppMessageExtensionsHandler* aExtensionsHandler, |
|
99 CGulIcon* aFromMe, |
|
100 CGulIcon* aToMe, |
|
101 MGraphicsDeviceMap* aMap, |
|
102 TBool aScrollOver /*= ETrue*/ ) |
|
103 { |
|
104 iAppUi = aAppUi; |
|
105 iTextView = aTextView; |
|
106 iExtensionsHandler = aExtensionsHandler; |
|
107 iFromMe = aFromMe; |
|
108 iToMe = aToMe; |
|
109 iMap = aMap; |
|
110 iScrollOver = aScrollOver; |
|
111 } |
|
112 |
|
113 // ----------------------------------------------------------------------------- |
|
114 // CIMCVAppRichTextContainer::ConstructL |
|
115 // Symbian 2nd phase constructor can leave. |
|
116 // ----------------------------------------------------------------------------- |
|
117 // |
|
118 void CIMCVAppRichTextContainer::ConstructL(const TDesC& aPrimaryKey) |
|
119 { |
|
120 |
|
121 iPrimaryKey = aPrimaryKey.AllocL(); |
|
122 |
|
123 iAppUi->AddLayoutChangeObserver( this ); |
|
124 iAppUi->AddResourceChangeObserver( this ); |
|
125 // setup layout |
|
126 TAknLayoutId layoutId; |
|
127 CAknEnv::Static()->GetCurrentLayoutId( layoutId ); |
|
128 |
|
129 |
|
130 iPrimaryFont = AknLayoutUtils::FontFromId( EAknLogicalFontPrimaryFont, |
|
131 NULL ); |
|
132 iSecondaryFont = AknLayoutUtils::FontFromId( EAknLogicalFontPrimarySmallFont, |
|
133 NULL ); |
|
134 |
|
135 CParaFormat paraFormat; |
|
136 TParaFormatMask paraFormatMask; |
|
137 paraFormat.iLanguage = CAknEnv::Static()->SettingCache().InputLanguage(); |
|
138 paraFormatMask.SetAttrib( EAttParaLanguage ); |
|
139 |
|
140 paraFormat.iFillColor = KRgbWhite; |
|
141 paraFormatMask.SetAttrib( EAttFillColor ); |
|
142 |
|
143 paraFormat.iLeftMarginInTwips = 100; |
|
144 paraFormat.iIndentInTwips = -100; |
|
145 paraFormatMask.SetAttrib( EAttLeftMargin ); |
|
146 paraFormatMask.SetAttrib( EAttIndent ); |
|
147 |
|
148 TCharFormat charFormat; |
|
149 TCharFormatMask charFormatMask; |
|
150 charFormat.iFontSpec = iSecondaryFont->FontSpecInTwips(); |
|
151 charFormatMask.SetAttrib( EAttFontTypeface ); |
|
152 charFormatMask.SetAttrib( EAttFontHeight ); |
|
153 |
|
154 // Text color |
|
155 TRgb defaultSkinTextColor( KRgbBlack ); |
|
156 AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), |
|
157 defaultSkinTextColor, |
|
158 KAknsIIDQsnTextColors, |
|
159 EAknsCIQsnTextColorsCG6 ); |
|
160 charFormat.iFontPresentation.iTextColor = defaultSkinTextColor; |
|
161 charFormatMask.SetAttrib( EAttColor ); |
|
162 |
|
163 charFormat.iFontPresentation.iPictureAlignment = |
|
164 TFontPresentation::EAlignTop; |
|
165 charFormatMask.SetAttrib( EAttFontPictureAlignment ); |
|
166 |
|
167 charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightNormal ); |
|
168 charFormatMask.SetAttrib( EAttFontStrokeWeight ); |
|
169 |
|
170 |
|
171 iParaFormatLayer = CParaFormatLayer::NewL( ¶Format, paraFormatMask ); |
|
172 iCharFormatLayer = CCharFormatLayer::NewL( charFormat, charFormatMask ); |
|
173 |
|
174 iRichText = CRichText::NewL( iParaFormatLayer, iCharFormatLayer ); |
|
175 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ConstructL() end" )); |
|
176 } |
|
177 |
|
178 // ----------------------------------------------------------------------------- |
|
179 // CIMCVAppRichTextContainer::NewL |
|
180 // Two-phased constructor. |
|
181 // ----------------------------------------------------------------------------- |
|
182 // |
|
183 CIMCVAppRichTextContainer* CIMCVAppRichTextContainer::NewL( MIMCVAppUi* aAppUi, |
|
184 MIMCVAppTextView* aTextView, |
|
185 CIMCVAppMessageExtensionsHandler* aExtensionsHandler, |
|
186 CGulIcon* aFromMe, |
|
187 CGulIcon* aToMe, |
|
188 MGraphicsDeviceMap* aMap, |
|
189 const TDesC& aPrimaryKey, |
|
190 TInt aServiceId, |
|
191 TBool aScrollOver /*= ETrue*/) |
|
192 { |
|
193 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::NewL() start" )); |
|
194 CIMCVAppRichTextContainer* self = new( ELeave ) CIMCVAppRichTextContainer(aAppUi, |
|
195 aTextView, |
|
196 aExtensionsHandler, aFromMe, aToMe, aMap,aServiceId, |
|
197 aScrollOver ); |
|
198 |
|
199 CleanupStack::PushL( self ); |
|
200 self->ConstructL(aPrimaryKey); |
|
201 CleanupStack::Pop( self ); |
|
202 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::NewL() end" )); |
|
203 return self; |
|
204 } |
|
205 |
|
206 |
|
207 // Destructor |
|
208 CIMCVAppRichTextContainer::~CIMCVAppRichTextContainer() |
|
209 { |
|
210 if(iPrimaryKey) |
|
211 { |
|
212 delete iPrimaryKey; |
|
213 iPrimaryKey = NULL; |
|
214 } |
|
215 delete iParaFormatLayer; |
|
216 delete iCharFormatLayer; |
|
217 delete iRichText; |
|
218 iMessages.ResetAndDestroy(); |
|
219 if(iAppUi) |
|
220 { |
|
221 iAppUi->RemoveLayoutChangeObserver( this ); |
|
222 iAppUi->RemoveResourceChangeObserver( this ); |
|
223 } |
|
224 } |
|
225 |
|
226 |
|
227 // ----------------------------------------------------------------------------- |
|
228 // CIMCVAppRichTextContainer::SelectedItem |
|
229 // (other items were commented in a header). |
|
230 // ----------------------------------------------------------------------------- |
|
231 // |
|
232 HBufC* CIMCVAppRichTextContainer::SelectedItemL() |
|
233 { |
|
234 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemL() start" )); |
|
235 if( iHighlightState == EItemSelected ) |
|
236 { |
|
237 TCursorSelection curSel( iMessages[iSelected]->Selection() ); |
|
238 |
|
239 // calculate item highlight position |
|
240 TCursorSelection itemSel( |
|
241 iMessages[iSelected]->Highlights()[iSelectedItem] ); |
|
242 |
|
243 TInt messageStart( curSel.LowerPos() ); |
|
244 curSel.iAnchorPos = itemSel.iAnchorPos + messageStart; |
|
245 curSel.iCursorPos = itemSel.iCursorPos + messageStart; |
|
246 |
|
247 HBufC* text = HBufC::NewMaxL( curSel.Length() ); |
|
248 TPtr ptr( text->Des() ); |
|
249 iRichText->Extract( ptr, curSel.LowerPos(), curSel.Length() ); |
|
250 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemL() end" )); |
|
251 return text; |
|
252 } |
|
253 else |
|
254 { |
|
255 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemL() end" )); |
|
256 return KNullDesC().AllocL(); |
|
257 } |
|
258 } |
|
259 |
|
260 // ----------------------------------------------------------------------------- |
|
261 // CIMCVAppRichTextContainer::SelectedItemType |
|
262 // (other items were commented in a header). |
|
263 // ----------------------------------------------------------------------------- |
|
264 // |
|
265 TInt CIMCVAppRichTextContainer::SelectedItemType() |
|
266 { |
|
267 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemType() start" )); |
|
268 if( (iHighlightState == EItemSelected) && ( iMessages.Count() >0 ) |
|
269 && (iSelected >= 0 ) ) |
|
270 { |
|
271 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemType() end" )); |
|
272 |
|
273 return iMessages[iSelected]->HighlightTypes()[iSelectedItem]; |
|
274 } |
|
275 else |
|
276 { |
|
277 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemType() end" )); |
|
278 return KErrNotFound; |
|
279 } |
|
280 } |
|
281 |
|
282 // ----------------------------------------------------------------------------- |
|
283 // CIMCVAppRichTextContainer::RichText |
|
284 // (other items were commented in a header). |
|
285 // ----------------------------------------------------------------------------- |
|
286 // |
|
287 MLayDoc* CIMCVAppRichTextContainer::TextLayout() |
|
288 { |
|
289 return iRichText; |
|
290 } |
|
291 // ----------------------------------------------------------------------------- |
|
292 // CIMCVAppRichTextContainer::RichText |
|
293 // (other items were commented in a header). |
|
294 // ----------------------------------------------------------------------------- |
|
295 // |
|
296 TInt CIMCVAppRichTextContainer::ServiceId() const |
|
297 { |
|
298 return iServiceId; |
|
299 } |
|
300 // ----------------------------------------------------------------------------- |
|
301 // CIMCVAppRichTextContainer::SetItemHighlight |
|
302 // (other items were commented in a header). |
|
303 // ----------------------------------------------------------------------------- |
|
304 // |
|
305 void CIMCVAppRichTextContainer::SetItemHighlight( TBool aItemHighlight ) |
|
306 { |
|
307 iItemHighlight = aItemHighlight; |
|
308 TInt richTextDocumentLength = iRichText->DocumentLength(); |
|
309 if (!richTextDocumentLength) |
|
310 return; |
|
311 |
|
312 if (aItemHighlight) |
|
313 { |
|
314 HBufC* text = HBufC::NewMaxLC( richTextDocumentLength ); |
|
315 TPtr txt( text->Des() ); |
|
316 |
|
317 iRichText->Extract( txt); |
|
318 CFindItemEngine* findItem = CFindItemEngine::NewL( txt, |
|
319 CFindItemEngine::TFindItemSearchCase( |
|
320 CFindItemEngine::EFindItemSearchPhoneNumberBin | |
|
321 CFindItemEngine::EFindItemSearchMailAddressBin | |
|
322 CFindItemEngine::EFindItemSearchURLBin/* | |
|
323 CFindItemEngine::EFindItemSearchScheme*/ ) |
|
324 ); |
|
325 |
|
326 CleanupStack::PushL( findItem ); |
|
327 const CArrayFixFlat<CFindItemEngine::SFoundItem>* items = findItem->ItemArray(); |
|
328 TInt count( items->Count() ); |
|
329 |
|
330 for( TInt i(0); i<count; ++i ) |
|
331 { |
|
332 const CFindItemEngine::SFoundItem item = items->At(i); |
|
333 |
|
334 // selection in rich text |
|
335 TCursorSelection realSel( item.iStartPos + item.iLength, item.iStartPos ); |
|
336 |
|
337 HighLightItemL( realSel ); |
|
338 } |
|
339 |
|
340 CleanupStack::PopAndDestroy( findItem ); |
|
341 CleanupStack::PopAndDestroy( text); |
|
342 |
|
343 } |
|
344 else |
|
345 { |
|
346 TCharFormat charFormat; |
|
347 TCharFormatMask charFormatMask; |
|
348 charFormatMask.SetAttrib( EAttFontUnderline ); |
|
349 |
|
350 charFormat.iFontPresentation.iUnderline = EUnderlineOff; |
|
351 |
|
352 iRichText->ApplyCharFormatL ( charFormat, charFormatMask, 0, richTextDocumentLength); |
|
353 } |
|
354 } |
|
355 // ----------------------------------------------------------------------------- |
|
356 // CIMCVAppRichTextContainer::MoveHighlightL |
|
357 // (other items were commented in a header). |
|
358 // ----------------------------------------------------------------------------- |
|
359 // |
|
360 TInt CIMCVAppRichTextContainer::MoveHighlightL( THighlightMovement aDirection ) |
|
361 { |
|
362 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::MoveHighlightL() start" )); |
|
363 TBool up( aDirection == EPrevious ); |
|
364 TInt messageCount( iMessages.Count() ); |
|
365 if( messageCount == 0 ) |
|
366 { |
|
367 // no messages, nothing to highlight |
|
368 //but make highlight state as EMessageBottom |
|
369 //so that tabs can be switched when there is no conversation in text container. |
|
370 if(iHighlightState == EMessageBottom) |
|
371 { |
|
372 iHighlightState = ENoHighlight; |
|
373 } |
|
374 else |
|
375 { |
|
376 iHighlightState = EMessageBottom; |
|
377 } |
|
378 return KErrNone; |
|
379 } |
|
380 |
|
381 |
|
382 TInt highlightCount( iMessages[iSelected]->Highlights().Count() ); |
|
383 |
|
384 if( !iItemHighlight ) |
|
385 { |
|
386 // if item highlighting is not on, clear the item count |
|
387 highlightCount = 0; |
|
388 } |
|
389 |
|
390 // if message is highlighted, but it doesn't fit to screen |
|
391 // scroll it line by line |
|
392 if( iHighlightState == EMessageTop || iHighlightState == EMessageBottom ) |
|
393 { |
|
394 TCursorSelection& sel = iMessages[iSelected]->Selection(); |
|
395 if( up ) |
|
396 { |
|
397 // up |
|
398 if( !iTextView->IsVisible( sel.LowerPos() ) ) |
|
399 { |
|
400 // we're scrolling up and top line is not shown, |
|
401 // so scroll messages down by one line |
|
402 iTextView->ScrollLinesL( 1 ); |
|
403 return KErrNone; |
|
404 } |
|
405 } |
|
406 else if( !iTextView->IsVisible( sel.HigherPos() ) ) |
|
407 { |
|
408 // we're scrolling down and bottom line is not shown, |
|
409 // so scroll messages up by one line |
|
410 iTextView->ScrollLinesL( -1 ); |
|
411 return KErrNone; |
|
412 } |
|
413 } |
|
414 |
|
415 // update highlight position |
|
416 switch( iHighlightState ) |
|
417 { |
|
418 case ENoHighlight: // no highlight, select last or first message |
|
419 { |
|
420 if( up ) |
|
421 { |
|
422 iSelected = messageCount - 1; |
|
423 |
|
424 // Get highlight count of prev message |
|
425 // if item highlighting is on |
|
426 if ( iItemHighlight ) |
|
427 { |
|
428 highlightCount = iMessages[iSelected]->Highlights().Count(); |
|
429 } |
|
430 |
|
431 if ( highlightCount > 0 ) |
|
432 { |
|
433 // highlight items inside last message (if any) |
|
434 iHighlightState = EItemSelected; |
|
435 iSelectedItem = highlightCount - 1; |
|
436 } |
|
437 else |
|
438 { |
|
439 // bottom of last message |
|
440 iHighlightState = EMessageBottom; |
|
441 } |
|
442 } |
|
443 else |
|
444 { |
|
445 // top of first message |
|
446 iHighlightState = EMessageTop; |
|
447 iSelected = 0; |
|
448 } |
|
449 break; |
|
450 } |
|
451 case EItemSelected: // highlighting items |
|
452 { |
|
453 if( up ) |
|
454 { |
|
455 // up, previous item |
|
456 --iSelectedItem; |
|
457 if( iSelectedItem < 0 ) |
|
458 { |
|
459 // end of highlights, focus message |
|
460 iHighlightState = EMessageTop; |
|
461 } |
|
462 } |
|
463 else |
|
464 { |
|
465 // down, next item |
|
466 ++iSelectedItem; |
|
467 if( iSelectedItem >= highlightCount ) |
|
468 { |
|
469 // end of highlights |
|
470 if ( iSelected < messageCount - 1 ) |
|
471 { |
|
472 // focus next message |
|
473 ++iSelected; |
|
474 iHighlightState = EMessageTop; |
|
475 } |
|
476 else if ( iScrollOver ) |
|
477 { |
|
478 // going down from last message, |
|
479 // disable highlight so editor can take the focus |
|
480 DisableHighlightL(); |
|
481 return KErrNone; |
|
482 } |
|
483 else |
|
484 { |
|
485 // Loop back to beginning |
|
486 iSelected = 0; |
|
487 iSelectedItem = 0; |
|
488 iHighlightState = EMessageTop; |
|
489 } |
|
490 |
|
491 } |
|
492 } |
|
493 break; |
|
494 } |
|
495 case EMessageTop: // highlighting message ("top" of it) |
|
496 { |
|
497 if( up ) |
|
498 { |
|
499 // up, highlighting previous message |
|
500 if( iSelected > 0 ) |
|
501 { |
|
502 // prev |
|
503 --iSelected; |
|
504 |
|
505 // get highlight count of prev message |
|
506 // if item highlighting is on |
|
507 if ( iItemHighlight ) |
|
508 { |
|
509 highlightCount = iMessages[iSelected]->Highlights().Count(); |
|
510 } |
|
511 |
|
512 if ( highlightCount > 0 ) |
|
513 { |
|
514 // highlight items inside prev message (if any) |
|
515 iHighlightState = EItemSelected; |
|
516 iSelectedItem = highlightCount - 1; |
|
517 } |
|
518 else |
|
519 { |
|
520 // highlight whole prev message |
|
521 iHighlightState = EMessageBottom; |
|
522 } |
|
523 } |
|
524 else if ( iScrollOver ) |
|
525 { |
|
526 // going up from first message, |
|
527 // disable highlight, so editor can take the focus |
|
528 DisableHighlightL(); |
|
529 return KErrNone; |
|
530 } |
|
531 else |
|
532 { |
|
533 // Loop to last message |
|
534 iSelected = messageCount-1; |
|
535 highlightCount = 0; |
|
536 |
|
537 // Get highlight count of last message |
|
538 // if item highlighting is on |
|
539 if ( iItemHighlight ) |
|
540 { |
|
541 highlightCount = |
|
542 iMessages[iSelected]->Highlights().Count(); |
|
543 } |
|
544 |
|
545 if ( highlightCount > 0 ) |
|
546 { |
|
547 // Highlight items inside last message (if any) |
|
548 iHighlightState = EItemSelected; |
|
549 iSelectedItem = highlightCount - 1; |
|
550 } |
|
551 else |
|
552 { |
|
553 // Highlight whole last message |
|
554 iHighlightState = EMessageBottom; |
|
555 } |
|
556 } |
|
557 } |
|
558 else |
|
559 { |
|
560 // down, highlight items inside this message (if any) |
|
561 if( highlightCount > 0 ) |
|
562 { |
|
563 iSelectedItem = 0; |
|
564 iHighlightState = EItemSelected; |
|
565 } |
|
566 else if( iSelected < messageCount-1 ) |
|
567 { |
|
568 // next |
|
569 ++iSelected; |
|
570 iHighlightState = EMessageTop; |
|
571 } |
|
572 else if( iScrollOver ) |
|
573 { |
|
574 // going down from last message, |
|
575 // disable highlight, so editor can take the focus |
|
576 DisableHighlightL(); |
|
577 return KErrNone; |
|
578 } |
|
579 else |
|
580 { |
|
581 // Loop back to beginning |
|
582 iSelected = 0; |
|
583 iSelectedItem = 0; |
|
584 iHighlightState = EMessageTop; |
|
585 } |
|
586 } |
|
587 break; |
|
588 } |
|
589 case EMessageBottom: // highlighting message ("bottom" of it) |
|
590 { |
|
591 if( up ) |
|
592 { |
|
593 // up, highlight items inside this message (if any) |
|
594 if( highlightCount > 0 ) |
|
595 { |
|
596 iSelectedItem = highlightCount-1; |
|
597 iHighlightState = EItemSelected; |
|
598 } |
|
599 else if( iSelected > 0 ) |
|
600 { |
|
601 // prev |
|
602 --iSelected; |
|
603 |
|
604 // get highlight count of prev message |
|
605 // if item highlighting is on |
|
606 if ( iItemHighlight ) |
|
607 { |
|
608 highlightCount = iMessages[iSelected]->Highlights().Count(); |
|
609 } |
|
610 |
|
611 if ( highlightCount > 0 ) |
|
612 { |
|
613 // highlight items inside prev message (if any) |
|
614 iHighlightState = EItemSelected; |
|
615 iSelectedItem = highlightCount - 1; |
|
616 } |
|
617 else |
|
618 { |
|
619 iHighlightState = EMessageBottom; |
|
620 } |
|
621 } |
|
622 else if( iScrollOver ) |
|
623 { |
|
624 // going up from first message, |
|
625 // disable highlight, so editor can take the focus |
|
626 DisableHighlightL(); |
|
627 return KErrNone; |
|
628 } |
|
629 else |
|
630 { |
|
631 // Loop to last message |
|
632 iSelected = messageCount-1; |
|
633 highlightCount = 0; |
|
634 |
|
635 // Get highlight count of last message |
|
636 // if item highlighting is on |
|
637 if ( iItemHighlight ) |
|
638 { |
|
639 highlightCount = |
|
640 iMessages[iSelected]->Highlights().Count(); |
|
641 } |
|
642 |
|
643 if ( highlightCount > 0 ) |
|
644 { |
|
645 // Highlight items inside last message (if any) |
|
646 iHighlightState = EItemSelected; |
|
647 iSelectedItem = highlightCount - 1; |
|
648 } |
|
649 else |
|
650 { |
|
651 // Highlight whole last message |
|
652 iHighlightState = EMessageBottom; |
|
653 } |
|
654 } |
|
655 } |
|
656 else |
|
657 { |
|
658 // down, highlighting next message |
|
659 if( iSelected < messageCount-1 ) |
|
660 { |
|
661 // next |
|
662 ++iSelected; |
|
663 iHighlightState = EMessageTop; |
|
664 } |
|
665 else if( iScrollOver ) |
|
666 { |
|
667 // going down from last message, |
|
668 // disable highlight, so editor can take the focus |
|
669 DisableHighlightL(); |
|
670 return KErrNone; |
|
671 } |
|
672 else |
|
673 { |
|
674 // Loop back to beginning |
|
675 iSelected = 0; |
|
676 iSelectedItem = 0; |
|
677 iHighlightState = EMessageTop; |
|
678 } |
|
679 } |
|
680 break; |
|
681 } |
|
682 default: |
|
683 { |
|
684 |
|
685 break; |
|
686 } |
|
687 } |
|
688 |
|
689 // get the selection |
|
690 TCursorSelection curSel( CurrentSelection() ); |
|
691 |
|
692 // remove colors from old highlight |
|
693 TInt textLen( iRichText->DocumentLength() ); |
|
694 if( iPrevious.iAnchorPos < textLen && |
|
695 iPrevious.iCursorPos <= textLen ) |
|
696 { |
|
697 BackColorL( iPrevious, KRgbWhite ); |
|
698 TextBackColorL( iPrevious, KRgbWhite ); |
|
699 } |
|
700 |
|
701 // and set new one |
|
702 if ( iHighlightState == EItemSelected ) |
|
703 { |
|
704 MAknsSkinInstance* skin = AknsUtils::SkinInstance(); |
|
705 TRgb color; |
|
706 |
|
707 TInt error = AknsUtils::GetCachedColor( skin, |
|
708 color, |
|
709 KAknsIIDQsnHighlightColors, |
|
710 EAknsCIQsnHighlightColorsCG2 ); |
|
711 |
|
712 if ( !error ) |
|
713 { |
|
714 // No error, use skinned background color |
|
715 TextBackColorL( curSel, color ); |
|
716 } |
|
717 else |
|
718 { |
|
719 TextBackColorL( curSel, AKN_LAF_COLOR_STATIC( KIMCVHighlightColor ) ); |
|
720 } |
|
721 } |
|
722 else |
|
723 { |
|
724 MAknsSkinInstance* skin = AknsUtils::SkinInstance(); |
|
725 TRgb color; |
|
726 |
|
727 TInt error = AknsUtils::GetCachedColor( skin, |
|
728 color, |
|
729 KAknsIIDQsnHighlightColors, |
|
730 EAknsCIQsnHighlightColorsCG2 ); |
|
731 |
|
732 if ( !error ) |
|
733 { |
|
734 // No error, use skinned background color |
|
735 BackColorL( curSel, color ); |
|
736 } |
|
737 else |
|
738 { |
|
739 BackColorL( curSel, AKN_LAF_COLOR_STATIC( KIMCVHighlightColor ) ); |
|
740 } |
|
741 } |
|
742 |
|
743 // handle changed format |
|
744 TCursorSelection changed( Union( iPrevious, curSel ) ); |
|
745 |
|
746 |
|
747 iTextView->HandleFormatChangedL( changed, ETrue ); |
|
748 |
|
749 iTextView->ScrollVisibleL( curSel, ETrue ); |
|
750 |
|
751 iPrevious = curSel; |
|
752 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::MoveHighlightL() end" )); |
|
753 return KErrNone; |
|
754 } |
|
755 |
|
756 |
|
757 // ----------------------------------------------------------------------------- |
|
758 // CIMCVAppRichTextContainer::DisableHighlightL |
|
759 // (other items were commented in a header). |
|
760 // ----------------------------------------------------------------------------- |
|
761 // |
|
762 void CIMCVAppRichTextContainer::DisableHighlightL() |
|
763 { |
|
764 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::DisableHighlightL() start" )); |
|
765 iHighlightState = ENoHighlight; |
|
766 |
|
767 TCursorSelection sel( 0,0 ); |
|
768 TInt count( iMessages.Count() ); |
|
769 if( count > 0 ) |
|
770 { |
|
771 sel = iMessages[count-1]->Selection(); |
|
772 } |
|
773 |
|
774 // remove colors from old highlight (if any) |
|
775 TInt textLen( iRichText->DocumentLength() ); |
|
776 if( iPrevious.iAnchorPos < textLen && |
|
777 iPrevious.iCursorPos <= textLen ) |
|
778 { |
|
779 BackColorL( iPrevious, KRgbWhite ); |
|
780 TextBackColorL( iPrevious, KRgbWhite ); |
|
781 iTextView->HandleFormatChangedL( iPrevious ); |
|
782 } |
|
783 |
|
784 // set focus to last message |
|
785 iTextView->ScrollVisibleL( sel, EFalse ); |
|
786 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::DisableHighlightL() end" )); |
|
787 } |
|
788 |
|
789 |
|
790 // ----------------------------------------------------------------------------- |
|
791 // CIMCVAppRichTextContainer::Highlighted |
|
792 // (other items were commented in a header). |
|
793 // ----------------------------------------------------------------------------- |
|
794 // |
|
795 TBool CIMCVAppRichTextContainer::Highlighted() |
|
796 { |
|
797 return iHighlightState != ENoHighlight; |
|
798 } |
|
799 |
|
800 // ----------------------------------------------------------------------------- |
|
801 // CIMCVAppRichTextContainer::Highlighted |
|
802 // (other items were commented in a header). |
|
803 // ----------------------------------------------------------------------------- |
|
804 // |
|
805 TInt CIMCVAppRichTextContainer::HighlightItemAtPosL( TInt aPos ) |
|
806 { |
|
807 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::HighlightItemAtPosL() start" )); |
|
808 TInt messagecount = iMessages.Count(); |
|
809 if( messagecount == 0 ) |
|
810 { |
|
811 // no messages |
|
812 return KErrNotFound; |
|
813 } |
|
814 |
|
815 // Store old values |
|
816 TInt oldSelectedMessage = iSelected; |
|
817 TInt oldSelectedItem = iSelectedItem; |
|
818 THighlightState oldHighlight = iHighlightState; |
|
819 |
|
820 // Find message in position aPos |
|
821 TBool found = EFalse; |
|
822 for( TInt i = 0; i < messagecount; ++i ) |
|
823 { |
|
824 TCursorSelection sel = iMessages[ i ]->WholeSelection(); |
|
825 if( aPos >= sel.LowerPos() && |
|
826 aPos <= sel.HigherPos() ) |
|
827 { |
|
828 // Found the message |
|
829 iSelected = i; |
|
830 iHighlightState = EMessageTop; |
|
831 found = ETrue; |
|
832 // stop searching |
|
833 break; |
|
834 } |
|
835 } |
|
836 |
|
837 if( !found ) |
|
838 { |
|
839 // not found |
|
840 return KErrNotFound; |
|
841 } |
|
842 |
|
843 // Check if there are items inside the message that can be highlighted. |
|
844 if( iItemHighlight ) |
|
845 { |
|
846 TInt hlCount = iMessages[ iSelected ]->Highlights().Count(); |
|
847 TInt relativePos = |
|
848 aPos - iMessages[ iSelected ]->WholeSelection().LowerPos(); |
|
849 |
|
850 for( TInt i = 0; i < hlCount; ++i ) |
|
851 { |
|
852 TCursorSelection sel = iMessages[ iSelected ]->Highlights()[ i ]; |
|
853 |
|
854 // Highlight's selection is relative to message |
|
855 if( relativePos >= sel.LowerPos() && |
|
856 relativePos <= sel.HigherPos() ) |
|
857 { |
|
858 // Found an item |
|
859 iHighlightState = EItemSelected; |
|
860 iSelectedItem = i; |
|
861 // stop searching |
|
862 break; |
|
863 } |
|
864 } |
|
865 } |
|
866 |
|
867 // Update UI only if selection has changed |
|
868 if( iSelected != oldSelectedMessage || |
|
869 iSelectedItem != oldSelectedItem || |
|
870 oldHighlight != iHighlightState ) |
|
871 { |
|
872 UpdateSelectionL(); |
|
873 return KErrNone; |
|
874 } |
|
875 // Already highlighted |
|
876 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::HighlightItemAtPosL() end" )); |
|
877 return KErrAlreadyExists; |
|
878 } |
|
879 |
|
880 // ----------------------------------------------------------------------------- |
|
881 // CIMCVAppRichTextContainer::UpdateSelection |
|
882 // (other items were commented in a header). |
|
883 // ----------------------------------------------------------------------------- |
|
884 // |
|
885 void CIMCVAppRichTextContainer::UpdateSelectionL() |
|
886 { |
|
887 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateSelectionL() start" )); |
|
888 // get the selection |
|
889 TCursorSelection curSel( CurrentSelection() ); |
|
890 |
|
891 // remove colors from old highlight |
|
892 TInt textLen( iRichText->DocumentLength() ); |
|
893 if( iPrevious.iAnchorPos < textLen && |
|
894 iPrevious.iCursorPos <= textLen ) |
|
895 { |
|
896 BackColorL( iPrevious, KRgbWhite ); |
|
897 TextBackColorL( iPrevious, KRgbWhite ); |
|
898 } |
|
899 |
|
900 // and set new one |
|
901 if ( iHighlightState == EItemSelected ) |
|
902 { |
|
903 MAknsSkinInstance* skin = AknsUtils::SkinInstance(); |
|
904 TRgb color; |
|
905 |
|
906 TInt error = AknsUtils::GetCachedColor( skin, |
|
907 color, |
|
908 KAknsIIDQsnHighlightColors, |
|
909 EAknsCIQsnHighlightColorsCG2 ); |
|
910 |
|
911 if ( !error ) |
|
912 { |
|
913 // No error, use skinned background color |
|
914 TextBackColorL( curSel, color ); |
|
915 } |
|
916 else |
|
917 { |
|
918 TextBackColorL( curSel, AKN_LAF_COLOR_STATIC( KIMCVHighlightColor ) ); |
|
919 } |
|
920 } |
|
921 else |
|
922 { |
|
923 MAknsSkinInstance* skin = AknsUtils::SkinInstance(); |
|
924 TRgb color; |
|
925 |
|
926 TInt error = AknsUtils::GetCachedColor( skin, |
|
927 color, |
|
928 KAknsIIDQsnHighlightColors, |
|
929 EAknsCIQsnHighlightColorsCG2 ); |
|
930 |
|
931 if ( !error ) |
|
932 { |
|
933 // No error, use skinned background color |
|
934 BackColorL( curSel, color ); |
|
935 } |
|
936 else |
|
937 { |
|
938 BackColorL( curSel, AKN_LAF_COLOR_STATIC( KIMCVHighlightColor ) ); |
|
939 } |
|
940 } |
|
941 |
|
942 // handle changed format |
|
943 TCursorSelection changed( Union( iPrevious, curSel ) ); |
|
944 |
|
945 iTextView->HandleFormatChangedL( changed ); |
|
946 iTextView->ScrollVisibleL( curSel, ETrue ); |
|
947 |
|
948 |
|
949 iPrevious = curSel; |
|
950 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateSelectionL() end" )); |
|
951 } |
|
952 |
|
953 // ----------------------------------------------------------------------------- |
|
954 // CIMCVAppRichTextContainer::InsertTimeStampL |
|
955 // (other items were commented in a header). |
|
956 // ----------------------------------------------------------------------------- |
|
957 // |
|
958 TCursorSelection CIMCVAppRichTextContainer::InsertTimeStampL( |
|
959 CIMCVAppMessageWrapper& aMessageWrapper ) |
|
960 { |
|
961 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertTimeStampL() start" )); |
|
962 TInt start = 0; |
|
963 TCursorSelection timeSel( start, start ); |
|
964 |
|
965 |
|
966 // format time |
|
967 HBufC* timeStamp = HBufC::NewLC( KTimeStampMaxLength + KSpace().Length() ); |
|
968 TPtr timePtr( timeStamp->Des() ); |
|
969 |
|
970 HBufC* timeStampFormat = NULL; |
|
971 timeStampFormat = StringLoader::LoadLC( R_QTN_TIME_USUAL_WITH_ZERO ); |
|
972 |
|
973 TTime time = aMessageWrapper.Message().TimeStamp(); |
|
974 TRAPD( err, time.FormatL( timePtr, *timeStampFormat ) ); |
|
975 if ( err == KErrOverflow ) |
|
976 { |
|
977 // Reserved text space was not enough. |
|
978 // Adjust the KTimeStampMaxLength! |
|
979 |
|
980 |
|
981 // in release builds return without timestamp |
|
982 CleanupStack::PopAndDestroy( 2, timeStamp ); // timeStamp, timeStampFormat |
|
983 return timeSel; |
|
984 } |
|
985 |
|
986 // Convert numbers to local language |
|
987 AknTextUtils::LanguageSpecificNumberConversion( timePtr ); |
|
988 |
|
989 // Set Alignment of Pm/Am from local setting |
|
990 // This keeps the am/pm text close to the time. |
|
991 timePtr.Append( AknLayoutUtils::LayoutMirrored() ? |
|
992 KUnicodeRLM : KUnicodeLRM ); |
|
993 // append time to rich text |
|
994 timePtr.Append( KSpace ); |
|
995 iRichText->InsertL( start, timePtr ); |
|
996 |
|
997 CleanupStack::PopAndDestroy( 2, timeStamp ); // timeStamp, timeStampFormat |
|
998 timeSel.SetSelection( start, timePtr.Length() - 1 ); |
|
999 |
|
1000 // bold the time |
|
1001 if ( timeSel.Length() > 0 ) |
|
1002 { |
|
1003 BoldL( timeSel ); |
|
1004 } |
|
1005 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertTimeStampL() end" )); |
|
1006 return timeSel; |
|
1007 } |
|
1008 |
|
1009 // ----------------------------------------------------------------------------- |
|
1010 // CIMCVAppRichTextContainer::InsertContentL |
|
1011 // (other items were commented in a header). |
|
1012 // ----------------------------------------------------------------------------- |
|
1013 // |
|
1014 TInt CIMCVAppRichTextContainer::InsertContentL( CIMCVAppMessageWrapper& aMessageWrapper ) |
|
1015 { |
|
1016 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertContentL() start" )); |
|
1017 MIMCVEngineMessage& message = aMessageWrapper.Message(); |
|
1018 |
|
1019 MIMCVEngineMessage::TContentType type( message.ContentType() ); |
|
1020 switch( type ) |
|
1021 { |
|
1022 case MIMCVEngineMessage::EContentText: |
|
1023 { |
|
1024 TInt oldLen = iRichText->DocumentLength(); |
|
1025 |
|
1026 // Insert text |
|
1027 TPtrC msg( message.Text() ); |
|
1028 |
|
1029 HBufC* tempMsg = NULL; |
|
1030 |
|
1031 TInt paraBreak = msg.Locate( CEditableText::EParagraphDelimiter ); |
|
1032 // Replace all paragraph delimiters with line breaks |
|
1033 // to keep alingment consistent |
|
1034 if ( paraBreak != KErrNotFound ) |
|
1035 { |
|
1036 tempMsg = msg.AllocLC(); |
|
1037 TPtr ptr( tempMsg->Des() ); |
|
1038 ptr.Zero(); |
|
1039 |
|
1040 ReplaceParaDelimsWithLineBreaks( msg, ptr ); |
|
1041 msg.Set( ptr ); |
|
1042 } |
|
1043 |
|
1044 HBufC* numberConv = NULL; |
|
1045 |
|
1046 // Convert numerals to local language |
|
1047 // 1) date item |
|
1048 if ( aMessageWrapper.Message().SystemMessageType() == |
|
1049 MIMCVEngineMessage::ESystemMessageDateChange ) |
|
1050 { |
|
1051 // Don't touch the original message |
|
1052 numberConv = msg.AllocLC(); |
|
1053 TPtr ptr( numberConv->Des() ); |
|
1054 AknTextUtils::LanguageSpecificNumberConversion( ptr ); |
|
1055 msg.Set( ptr ); |
|
1056 } |
|
1057 |
|
1058 iRichText->InsertL( 0, msg ); |
|
1059 |
|
1060 TInt textEnd = msg.Length(); |
|
1061 |
|
1062 // Check for extensions (smileys) |
|
1063 TCursorSelection selection( 0, textEnd ); |
|
1064 TInt bfrConv = iRichText->DocumentLength(); |
|
1065 iExtensionsHandler->ConvertSelectionToExtensionL( *iRichText, |
|
1066 selection, |
|
1067 iServiceId ); |
|
1068 |
|
1069 // Move textEnd index if extensions were found |
|
1070 textEnd -= ( bfrConv - iRichText->DocumentLength() ); |
|
1071 |
|
1072 // Add nbs to preserve formatting |
|
1073 iRichText->InsertL( textEnd, |
|
1074 CEditableText::EZeroWidthNoBreakSpace ); |
|
1075 |
|
1076 // If this is system message, it should be bold |
|
1077 if( message.MessageType() == MIMCVEngineMessage::EMessageSystem ) |
|
1078 { |
|
1079 TCursorSelection sel( 0, textEnd ); |
|
1080 BoldL( sel ); |
|
1081 // System messages need different kind of alignment |
|
1082 CParaFormat paraFormat; |
|
1083 TParaFormatMask paraFormatMask; |
|
1084 paraFormat.iLeftMarginInTwips = 0; |
|
1085 paraFormatMask.SetAttrib( EAttLeftMargin ); |
|
1086 iRichText->ApplyParaFormatL( ¶Format, paraFormatMask, |
|
1087 0, textEnd + 1 ); |
|
1088 } |
|
1089 else |
|
1090 { |
|
1091 // Apply alignment for "normal" messages |
|
1092 CParaFormat paraFormat; |
|
1093 TParaFormatMask paraFormatMask; |
|
1094 paraFormat.iLeftMarginInTwips = 100; |
|
1095 paraFormatMask.SetAttrib( EAttLeftMargin ); |
|
1096 iRichText->ApplyParaFormatL( ¶Format, paraFormatMask, |
|
1097 0, textEnd + 1 ); |
|
1098 |
|
1099 // Remove bolding from message content |
|
1100 TCharFormat charFormat; |
|
1101 TCharFormatMask charFormatMask; |
|
1102 charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightNormal ); |
|
1103 charFormatMask.SetAttrib( EAttFontStrokeWeight ); |
|
1104 iRichText->ApplyCharFormatL( charFormat, charFormatMask, |
|
1105 0, textEnd + 1 ); |
|
1106 } |
|
1107 |
|
1108 // Cleanup |
|
1109 if ( numberConv ) |
|
1110 { |
|
1111 CleanupStack::PopAndDestroy( numberConv ); |
|
1112 } |
|
1113 if ( tempMsg ) |
|
1114 { |
|
1115 CleanupStack::PopAndDestroy( tempMsg ); |
|
1116 } |
|
1117 |
|
1118 return iRichText->DocumentLength() - oldLen; |
|
1119 } |
|
1120 default: |
|
1121 { |
|
1122 // Unsupported type |
|
1123 |
|
1124 break; |
|
1125 } |
|
1126 } |
|
1127 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertContentL() end" )); |
|
1128 return 0; |
|
1129 } |
|
1130 |
|
1131 // ----------------------------------------------------------------------------- |
|
1132 // CIMCVAppRichTextContainer::InsertNickL |
|
1133 // (other items were commented in a header). |
|
1134 // ----------------------------------------------------------------------------- |
|
1135 // |
|
1136 TCursorSelection CIMCVAppRichTextContainer::InsertNickL( |
|
1137 CIMCVAppMessageWrapper& aMessageWrapper ) |
|
1138 { |
|
1139 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertNickL() start" )); |
|
1140 // insert nick |
|
1141 MIMCVEngineMessage& message = aMessageWrapper.Message(); |
|
1142 TPtrC sender; |
|
1143 TPtrC recipient; |
|
1144 if ( message.MessageType() == MIMCVEngineMessage::EMessageGroup || |
|
1145 message.MessageType() == MIMCVEngineMessage::EMessageWhisper ) |
|
1146 { |
|
1147 sender.Set( message.Sender() ); |
|
1148 recipient.Set( message.Recipient() ); |
|
1149 } |
|
1150 |
|
1151 TCursorSelection nickSel( 0,0 ); |
|
1152 |
|
1153 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertNickL() end" )); |
|
1154 return nickSel; |
|
1155 } |
|
1156 |
|
1157 // ----------------------------------------------------------------------------- |
|
1158 // CIMCVAppRichTextContainer::LayoutChangedL |
|
1159 // (other items were commented in a header). |
|
1160 // ----------------------------------------------------------------------------- |
|
1161 // |
|
1162 void CIMCVAppRichTextContainer::LayoutChangedL( TInt aType) |
|
1163 { |
|
1164 #if 0 |
|
1165 //if layout change.. then dont update skin text color. |
|
1166 if (aType == KAknsMessageSkinChange) |
|
1167 { |
|
1168 UpdateSkinnedTextColourL(); |
|
1169 } |
|
1170 #endif |
|
1171 } |
|
1172 |
|
1173 // ----------------------------------------------------------------------------- |
|
1174 // CCARichTextContainer::ResourceChangedL |
|
1175 // (other items were commented in a header). |
|
1176 // ----------------------------------------------------------------------------- |
|
1177 // |
|
1178 void CIMCVAppRichTextContainer::ResourceChangedL() |
|
1179 { |
|
1180 // When resource changes (branding): |
|
1181 // clear content, so that old pictures don't cause any problems. |
|
1182 // we are reloaded anyway. |
|
1183 iRichText->DeleteL( 0, iRichText->DocumentLength() ); |
|
1184 iTextView->HandleGlobalChangeNoRedrawL(); |
|
1185 } |
|
1186 // CIMCVAppRichTextContainer::AddMessageL |
|
1187 // (other items were commented in a header). |
|
1188 // ----------------------------------------------------------------------------- |
|
1189 // |
|
1190 void CIMCVAppRichTextContainer::AddMessageL( MIMCVEngineMessage& aMessage ) |
|
1191 { |
|
1192 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddMessageL() start" )); |
|
1193 if( !iShowTimeStamps && |
|
1194 aMessage.SystemMessageType() == MIMCVEngineMessage::ESystemMessageDateChange ) |
|
1195 { |
|
1196 // if timestamp setting is OFF we don't show day change items |
|
1197 return; |
|
1198 } |
|
1199 |
|
1200 TInt oldCount = iMessages.Count(); |
|
1201 |
|
1202 // create wrapper |
|
1203 CIMCVAppMessageWrapper* wrapper = CIMCVAppMessageWrapper::NewL( aMessage ); |
|
1204 |
|
1205 CleanupStack::PushL( wrapper ); |
|
1206 iMessages.AppendL( wrapper ); // takes the ownership |
|
1207 CleanupStack::Pop( wrapper ); |
|
1208 |
|
1209 |
|
1210 // start new paragraph |
|
1211 TInt lineStart = iRichText->DocumentLength(); |
|
1212 if( lineStart != 0 ) |
|
1213 { |
|
1214 iRichText->InsertL( lineStart, CEditableText::EParagraphDelimiter ); |
|
1215 } |
|
1216 |
|
1217 // Set Alignment from local layout |
|
1218 iRichText->InsertL( iRichText->DocumentLength(), |
|
1219 AknLayoutUtils::LayoutMirrored() ? KUnicodeRLM : KUnicodeLRM ); |
|
1220 |
|
1221 // add message to rich text |
|
1222 TInt startPos( iRichText->DocumentLength() ); |
|
1223 TCursorSelection timeSel = AddTimeStampL( *wrapper ); |
|
1224 TCursorSelection nickSel = AddNickL( *wrapper ); |
|
1225 AddContentL( startPos, *wrapper ); |
|
1226 TInt endPos( iRichText->DocumentLength() ); |
|
1227 |
|
1228 // set selection for highlight and the whole selection |
|
1229 // (so that this can be removed) |
|
1230 // append deletioncount to new messages |
|
1231 wrapper->Selection().SetSelection( endPos - 1, startPos ); |
|
1232 wrapper->WholeSelection().SetSelection( endPos, lineStart ); |
|
1233 wrapper->MessageSelection().SetSelection( endPos - 1, nickSel.HigherPos() ); |
|
1234 |
|
1235 |
|
1236 // append coloring |
|
1237 TCursorSelection& sel = iColorWholeMessage ? wrapper->Selection() : nickSel; |
|
1238 TInt len( sel.Length() ); |
|
1239 |
|
1240 |
|
1241 // Make sure the background (highlight) is not copied from |
|
1242 // previous message. |
|
1243 BackColorL( sel, KRgbWhite ); |
|
1244 TextBackColorL( sel, KRgbWhite ); |
|
1245 |
|
1246 if( len > 0 && |
|
1247 aMessage.MessageType() != MIMCVEngineMessage::EMessageSystem ) |
|
1248 { |
|
1249 // custom colors |
|
1250 if( aMessage.MessagerType() == MIMCVEngineMessage::EMessageSent ) |
|
1251 { |
|
1252 // own msg |
|
1253 if( iOwnMsgColorInUse ) |
|
1254 { |
|
1255 TextColorL( sel, iOwnMsgColor ); |
|
1256 } |
|
1257 } |
|
1258 else if( aMessage.MessagerType() == MIMCVEngineMessage::EMessageReceived ) |
|
1259 { |
|
1260 // other msg |
|
1261 if( iMsgColorInUse ) |
|
1262 { |
|
1263 TextColorL( sel, iMsgColor ); |
|
1264 } |
|
1265 } |
|
1266 } |
|
1267 |
|
1268 #ifdef RD_30_COMPATIBILITY_MODE |
|
1269 if( lineStart == 0 ) |
|
1270 { |
|
1271 // This is needed only in 3.0 backport so that the alignment |
|
1272 // character doesn't cause a virtual linebreak. |
|
1273 TRAP_IGNORE( iTextView->HandleFormatChangedL( |
|
1274 wrapper->WholeSelection() ) ); |
|
1275 } |
|
1276 #endif // RD_30_COMPATIBILITY_MODE |
|
1277 |
|
1278 // inform of inserted rich text |
|
1279 TCursorSelection curSel( CurrentSelection() ); |
|
1280 TRAPD( error, iTextView->HandleAdditionL( lineStart == 0, curSel, EFalse ) ); |
|
1281 if( error != KErrNone ) |
|
1282 { |
|
1283 |
|
1284 // Remove failed text |
|
1285 TCursorSelection del = wrapper->WholeSelection(); |
|
1286 iRichText->DeleteL( del.LowerPos(), del.Length() ); |
|
1287 |
|
1288 // Remove the failed wrapper and leave |
|
1289 TInt index = iMessages.Find( wrapper ); |
|
1290 if( index != KErrNotFound ) |
|
1291 { |
|
1292 delete wrapper; |
|
1293 iMessages.Remove( index ); |
|
1294 } |
|
1295 |
|
1296 // Try to handle changes once more |
|
1297 TRAPD( updateErr, iTextView->HandleGlobalChangeNoRedrawL() ); |
|
1298 if( !updateErr ) |
|
1299 { |
|
1300 TCursorSelection curSel( CurrentSelection() ); |
|
1301 TRAP_IGNORE( iTextView->ScrollVisibleL( curSel, EFalse ) ); |
|
1302 } |
|
1303 User::Leave( error ); |
|
1304 } |
|
1305 |
|
1306 // and scroll (unless in highlight-mode) |
|
1307 if( iHighlightState == ENoHighlight ) |
|
1308 { |
|
1309 TCursorSelection curSel( CurrentSelection() ); |
|
1310 iTextView->ScrollVisibleL( curSel, EFalse ); |
|
1311 |
|
1312 // If this is recorded chat container (iScrollOver == EFalse) |
|
1313 // and added message was first move highlight |
|
1314 // so we have focus on the topmost item. |
|
1315 if ( oldCount == 0 && !iScrollOver ) |
|
1316 { |
|
1317 MoveHighlightL( ENext ); |
|
1318 } |
|
1319 } |
|
1320 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddMessageL() end" )); |
|
1321 } |
|
1322 |
|
1323 |
|
1324 |
|
1325 // ----------------------------------------------------------------------------- |
|
1326 // CIMCVAppRichTextContainer::InsertMessageL |
|
1327 // (other items were commented in a header). |
|
1328 // ----------------------------------------------------------------------------- |
|
1329 // |
|
1330 void CIMCVAppRichTextContainer::InsertMessageL( MIMCVEngineMessage& aMessage ) |
|
1331 { |
|
1332 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertMessageL() start" )); |
|
1333 if ( !iShowTimeStamps && |
|
1334 aMessage.SystemMessageType() == MIMCVEngineMessage::ESystemMessageDateChange ) |
|
1335 { |
|
1336 // if timestamp setting is OFF we don't show day change items |
|
1337 return; |
|
1338 } |
|
1339 |
|
1340 // create wrapper |
|
1341 CIMCVAppMessageWrapper* wrapper = CIMCVAppMessageWrapper::NewL( aMessage ); |
|
1342 |
|
1343 CleanupStack::PushL( wrapper ); |
|
1344 iMessages.InsertL( wrapper, 0 ); // takes the ownership |
|
1345 CleanupStack::Pop( wrapper ); |
|
1346 |
|
1347 |
|
1348 TInt oldLen = iRichText->DocumentLength(); |
|
1349 |
|
1350 // Insert paragraph break if this is not the last message |
|
1351 TInt paraBreak = 0; |
|
1352 if ( iMessages.Count() > 1 ) |
|
1353 { |
|
1354 iRichText->InsertL( 0, CEditableText::EParagraphDelimiter ); |
|
1355 paraBreak = 1; |
|
1356 } |
|
1357 |
|
1358 // Insert message to rich text in reverse order compared to adding |
|
1359 TInt contentLen = InsertContentL( *wrapper ); |
|
1360 TCursorSelection nickSel = InsertNickL( *wrapper ); |
|
1361 TCursorSelection timeSel = InsertTimeStampL( *wrapper ); |
|
1362 |
|
1363 // Set Alignment from local layout |
|
1364 TInt dirChrLen = iRichText->DocumentLength(); |
|
1365 iRichText->InsertL( 0, AknLayoutUtils::LayoutMirrored() ? |
|
1366 KUnicodeRLM : KUnicodeLRM ); |
|
1367 dirChrLen = iRichText->DocumentLength() - dirChrLen; |
|
1368 |
|
1369 wrapper->SetInserted( ETrue ); |
|
1370 |
|
1371 // Update timestamp selection |
|
1372 timeSel.iAnchorPos += dirChrLen; |
|
1373 timeSel.iCursorPos += dirChrLen; |
|
1374 // Update nick selection |
|
1375 nickSel.iAnchorPos += timeSel.HigherPos(); |
|
1376 nickSel.iCursorPos += timeSel.HigherPos(); |
|
1377 // Update thumb pos |
|
1378 TCursorSelection& thumbPos = wrapper->ThumbPos(); |
|
1379 thumbPos.iAnchorPos += nickSel.HigherPos() + KSeparator().Length(); |
|
1380 thumbPos.iCursorPos += nickSel.HigherPos() + KSeparator().Length(); |
|
1381 |
|
1382 TInt addedLen = iRichText->DocumentLength() - oldLen; |
|
1383 |
|
1384 // parse text for highlights and store positions to messagewrapper |
|
1385 HBufC* text = HBufC::NewMaxLC( contentLen ); |
|
1386 TPtr txt( text->Des() ); |
|
1387 iRichText->Extract( txt, |
|
1388 nickSel.HigherPos() + KSeparator().Length() + 1, // Don't extract separator and space |
|
1389 contentLen ); |
|
1390 ParseTextL( txt, nickSel.HigherPos() + KSeparator().Length() + 1, |
|
1391 nickSel.HigherPos() + KSeparator().Length() + 1, *wrapper ); |
|
1392 CleanupStack::PopAndDestroy( text ); |
|
1393 |
|
1394 // Set selection for highlight and the whole selection |
|
1395 // so that this message can be removed |
|
1396 wrapper->Selection().SetSelection( addedLen - 1 - paraBreak, 0 ); |
|
1397 wrapper->WholeSelection().SetSelection( addedLen - 1, 0 ); |
|
1398 wrapper->MessageSelection().SetSelection( addedLen - 1, |
|
1399 nickSel.HigherPos() + 1 ); |
|
1400 |
|
1401 if ( iHighlightState != ENoHighlight ) |
|
1402 { |
|
1403 BackColorL( wrapper->WholeSelection(), KRgbWhite ); |
|
1404 TextBackColorL( wrapper->WholeSelection(), KRgbWhite ); |
|
1405 } |
|
1406 |
|
1407 // Update wrappers after this if there is any |
|
1408 if ( iMessages.Count() > 1 ) |
|
1409 { |
|
1410 UpdateWrappers( 1, addedLen ); |
|
1411 } |
|
1412 |
|
1413 // Append coloring |
|
1414 TCursorSelection& sel = iColorWholeMessage ? wrapper->Selection() : nickSel; |
|
1415 TInt len( sel.Length() ); |
|
1416 |
|
1417 if ( len > 0 && |
|
1418 aMessage.MessageType() != MIMCVEngineMessage::EMessageSystem ) |
|
1419 { |
|
1420 // Custom colors |
|
1421 if ( aMessage.MessagerType() == MIMCVEngineMessage::EMessageSent ) |
|
1422 { |
|
1423 // Own msg |
|
1424 if( iOwnMsgColorInUse ) |
|
1425 { |
|
1426 TextColorL( sel, iOwnMsgColor ); |
|
1427 } |
|
1428 } |
|
1429 else if ( aMessage.MessagerType() == MIMCVEngineMessage::EMessageReceived ) |
|
1430 { |
|
1431 // Other msg |
|
1432 if( iMsgColorInUse ) |
|
1433 { |
|
1434 TextColorL( sel, iMsgColor ); |
|
1435 } |
|
1436 } |
|
1437 } |
|
1438 |
|
1439 // Inform of inserted rich text |
|
1440 TInt error = KErrNone; |
|
1441 if ( oldLen == 0 ) |
|
1442 { |
|
1443 TCursorSelection curSel( CurrentSelection() ); |
|
1444 // First message inserted, format the whole text |
|
1445 TRAP( error, iTextView->HandleAdditionL( ETrue, curSel, EFalse ) ); |
|
1446 } |
|
1447 else |
|
1448 { |
|
1449 TCursorSelection curSel( CurrentSelection() ); |
|
1450 // There might be a faster method to handle text addition, but |
|
1451 // this works for now. |
|
1452 TRAP( error, iTextView->HandleAdditionL( ETrue, curSel, EFalse) ); |
|
1453 } |
|
1454 // And scroll (unless in highlight-mode) |
|
1455 if ( iHighlightState == ENoHighlight ) |
|
1456 { |
|
1457 TCursorSelection curSel( CurrentSelection() ); |
|
1458 iTextView->ScrollVisibleL( curSel, EFalse ); |
|
1459 } |
|
1460 else |
|
1461 { |
|
1462 // In highlight mode, message inserted -> increase selected |
|
1463 // message index and previous selection indexes |
|
1464 iSelected++; |
|
1465 iPrevious.iAnchorPos += addedLen; |
|
1466 iPrevious.iCursorPos += addedLen; |
|
1467 |
|
1468 TCursorSelection curSel( CurrentSelection() ); |
|
1469 iTextView->ScrollVisibleL( curSel, EFalse ); |
|
1470 } |
|
1471 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertMessageL() end" )); |
|
1472 } |
|
1473 |
|
1474 // ----------------------------------------------------------------------------- |
|
1475 // CIMCVAppRichTextContainer::UpdateWrappers |
|
1476 // (other items were commented in a header). |
|
1477 // ----------------------------------------------------------------------------- |
|
1478 // |
|
1479 void CIMCVAppRichTextContainer::UpdateWrappers( TInt aFirstIndex, TInt aChange ) |
|
1480 { |
|
1481 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateWrappers() start" )); |
|
1482 TInt count( iMessages.Count() ); |
|
1483 for( TInt i( aFirstIndex ); i<count; ++i ) |
|
1484 { |
|
1485 CIMCVAppMessageWrapper* wrapper = iMessages[i]; |
|
1486 TCursorSelection& selection = wrapper->Selection(); |
|
1487 TCursorSelection& wholeSelection = wrapper->WholeSelection(); |
|
1488 TCursorSelection& thumbPos = wrapper->ThumbPos(); |
|
1489 selection.iAnchorPos += aChange; |
|
1490 selection.iCursorPos += aChange; |
|
1491 wholeSelection.iAnchorPos += aChange; |
|
1492 wholeSelection.iCursorPos += aChange; |
|
1493 thumbPos.iAnchorPos += aChange; |
|
1494 thumbPos.iCursorPos += aChange; |
|
1495 } |
|
1496 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateWrappers() end" )); |
|
1497 } |
|
1498 |
|
1499 // ----------------------------------------------------------------------------- |
|
1500 // CIMCVAppRichTextContainer::Union |
|
1501 // (other items were commented in a header). |
|
1502 // ----------------------------------------------------------------------------- |
|
1503 // |
|
1504 TCursorSelection CIMCVAppRichTextContainer::Union( const TCursorSelection& aSel1, |
|
1505 const TCursorSelection& aSel2 ) |
|
1506 { |
|
1507 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::Union() start" )); |
|
1508 // make union of selections |
|
1509 TCursorSelection changed; |
|
1510 changed.iAnchorPos = aSel1.LowerPos(); |
|
1511 changed.iCursorPos = aSel1.HigherPos(); |
|
1512 |
|
1513 TInt low( aSel2.LowerPos() ); |
|
1514 TInt high( aSel2.HigherPos() ); |
|
1515 if( low < changed.iAnchorPos ) |
|
1516 { |
|
1517 changed.iAnchorPos = low; |
|
1518 } |
|
1519 if( high > changed.iCursorPos ) |
|
1520 { |
|
1521 changed.iCursorPos = high; |
|
1522 } |
|
1523 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::Union() end" )); |
|
1524 return changed; |
|
1525 } |
|
1526 |
|
1527 // ----------------------------------------------------------------------------- |
|
1528 // CIMCVAppRichTextContainer::CurrentSelection |
|
1529 // (other items were commented in a header). |
|
1530 // ----------------------------------------------------------------------------- |
|
1531 // |
|
1532 TCursorSelection CIMCVAppRichTextContainer::CurrentSelection() const |
|
1533 { |
|
1534 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::CurrentSelection() start" )); |
|
1535 TCursorSelection sel( 0,0 ); |
|
1536 if( iHighlightState == ENoHighlight ) |
|
1537 { |
|
1538 // if nothing highlighted, return last message |
|
1539 TInt count( iMessages.Count() ); |
|
1540 if( count > 0 ) |
|
1541 { |
|
1542 sel = iMessages[count-1]->Selection(); |
|
1543 } |
|
1544 } |
|
1545 else |
|
1546 { |
|
1547 // something highlighted, start with current message |
|
1548 sel = iMessages[iSelected]->Selection(); |
|
1549 |
|
1550 // check if the highlighted selection is item inside message |
|
1551 if( iHighlightState == EItemSelected ) |
|
1552 { |
|
1553 // calculate item highlight position |
|
1554 TCursorSelection itemSel( |
|
1555 iMessages[iSelected]->Highlights()[iSelectedItem] ); |
|
1556 |
|
1557 TInt messageStart( sel.LowerPos() ); |
|
1558 sel.iAnchorPos = itemSel.iAnchorPos + messageStart; |
|
1559 sel.iCursorPos = itemSel.iCursorPos + messageStart; |
|
1560 } |
|
1561 } |
|
1562 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::CurrentSelection() end" )); |
|
1563 return sel; |
|
1564 } |
|
1565 |
|
1566 |
|
1567 // ----------------------------------------------------------------------------- |
|
1568 // CIMCVAppRichTextContainer::TextBackColorL |
|
1569 // (other items were commented in a header). |
|
1570 // ----------------------------------------------------------------------------- |
|
1571 // |
|
1572 void CIMCVAppRichTextContainer::TextBackColorL( const TCursorSelection& aSel, |
|
1573 const TRgb& aColor ) |
|
1574 { |
|
1575 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::TextBackColorL() start" )); |
|
1576 TCharFormat charFormat; |
|
1577 TCharFormatMask charFormatMask; |
|
1578 charFormatMask.SetAttrib( EAttFontHighlightColor ); |
|
1579 charFormatMask.SetAttrib( EAttFontHighlightStyle ); |
|
1580 |
|
1581 charFormat.iFontPresentation.iHighlightColor = aColor; |
|
1582 charFormat.iFontPresentation.iHighlightStyle = aColor == KRgbWhite ? |
|
1583 TFontPresentation::EFontHighlightNone : |
|
1584 TFontPresentation::EFontHighlightNormal; |
|
1585 |
|
1586 iRichText->ApplyCharFormatL( charFormat, charFormatMask, |
|
1587 aSel.LowerPos(), |
|
1588 aSel.Length() ); |
|
1589 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::TextBackColorL() end" )); |
|
1590 } |
|
1591 |
|
1592 // ----------------------------------------------------------------------------- |
|
1593 // CIMCVAppRichTextContainer::TextColorL |
|
1594 // (other items were commented in a header). |
|
1595 // ----------------------------------------------------------------------------- |
|
1596 // |
|
1597 void CIMCVAppRichTextContainer::TextColorL( const TCursorSelection& aSel, |
|
1598 const TRgb& aColor ) |
|
1599 { |
|
1600 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::TextColorL() start" )); |
|
1601 TCharFormat charFormat; |
|
1602 TCharFormatMask charFormatMask; |
|
1603 charFormatMask.SetAttrib( EAttColor ); |
|
1604 charFormat.iFontPresentation.iTextColor = aColor; |
|
1605 |
|
1606 iRichText->ApplyCharFormatL( charFormat, charFormatMask, |
|
1607 aSel.LowerPos(), |
|
1608 aSel.Length() ); |
|
1609 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::TextColorL() end" )); |
|
1610 } |
|
1611 |
|
1612 // ----------------------------------------------------------------------------- |
|
1613 // CIMCVAppRichTextContainer::BackColorL |
|
1614 // (other items were commented in a header). |
|
1615 // ----------------------------------------------------------------------------- |
|
1616 // |
|
1617 void CIMCVAppRichTextContainer::BackColorL( const TCursorSelection& aSel, |
|
1618 const TRgb& aColor ) |
|
1619 { |
|
1620 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::BackColorL() start" )); |
|
1621 CParaFormat paraFormat; |
|
1622 TParaFormatMask paraFormatMask; |
|
1623 paraFormatMask.SetAttrib( EAttFillColor ); |
|
1624 |
|
1625 paraFormat.iFillColor = aColor; |
|
1626 iRichText->ApplyParaFormatL( ¶Format, paraFormatMask, |
|
1627 aSel.LowerPos(), |
|
1628 aSel.Length() ); |
|
1629 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::BackColorL() end" )); |
|
1630 } |
|
1631 |
|
1632 // ----------------------------------------------------------------------------- |
|
1633 // CIMCVAppRichTextContainer::HighLightItemL |
|
1634 // (other items were commented in a header). |
|
1635 // ----------------------------------------------------------------------------- |
|
1636 // |
|
1637 void CIMCVAppRichTextContainer::HighLightItemL( const TCursorSelection& aSel ) |
|
1638 { |
|
1639 |
|
1640 TCharFormat charFormat; |
|
1641 TCharFormatMask charFormatMask; |
|
1642 charFormatMask.SetAttrib( EAttFontUnderline ); |
|
1643 |
|
1644 charFormat.iFontPresentation.iUnderline = EUnderlineOn; |
|
1645 |
|
1646 iRichText->ApplyCharFormatL( charFormat, charFormatMask, |
|
1647 aSel.LowerPos(), |
|
1648 aSel.Length() ); |
|
1649 } |
|
1650 |
|
1651 |
|
1652 // ----------------------------------------------------------------------------- |
|
1653 // CIMCVAppRichTextContainer::GetMessageCount |
|
1654 // (other items were commented in a header). |
|
1655 // ----------------------------------------------------------------------------- |
|
1656 // |
|
1657 TInt CIMCVAppRichTextContainer::GetMessageCount() |
|
1658 { |
|
1659 return iMessages.Count(); |
|
1660 } |
|
1661 |
|
1662 // ----------------------------------------------------------------------------- |
|
1663 // CIMCVAppRichTextContainer::BoldL |
|
1664 // (other items were commented in a header). |
|
1665 // ----------------------------------------------------------------------------- |
|
1666 // |
|
1667 void CIMCVAppRichTextContainer::BoldL( const TCursorSelection& aSel ) |
|
1668 { |
|
1669 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::BoldL() start" )); |
|
1670 #ifdef _DEBUG |
|
1671 TInt len( iRichText->DocumentLength() ); |
|
1672 |
|
1673 #endif //_DEBUG |
|
1674 |
|
1675 TCharFormat charFormat; |
|
1676 TCharFormatMask charFormatMask; |
|
1677 |
|
1678 charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightBold ); |
|
1679 charFormatMask.SetAttrib( EAttFontStrokeWeight ); |
|
1680 |
|
1681 iRichText->ApplyCharFormatL( charFormat, charFormatMask, |
|
1682 aSel.LowerPos(), |
|
1683 aSel.Length() ); |
|
1684 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::BoldL() end" )); |
|
1685 } |
|
1686 |
|
1687 // ----------------------------------------------------------------------------- |
|
1688 // CIMCVAppRichTextContainer::ParseTextL |
|
1689 // (other items were commented in a header). |
|
1690 // ----------------------------------------------------------------------------- |
|
1691 // |
|
1692 void CIMCVAppRichTextContainer::ParseTextL( const TDesC& aText, TInt aStartPos, |
|
1693 TInt aRelativePos, CIMCVAppMessageWrapper& aMessageWrapper ) |
|
1694 { |
|
1695 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ParseTextL() start" )); |
|
1696 CFindItemEngine* findItem = CFindItemEngine::NewL( aText, |
|
1697 CFindItemEngine::TFindItemSearchCase( |
|
1698 CFindItemEngine::EFindItemSearchPhoneNumberBin | |
|
1699 CFindItemEngine::EFindItemSearchMailAddressBin | |
|
1700 CFindItemEngine::EFindItemSearchURLBin/* | |
|
1701 CFindItemEngine::EFindItemSearchScheme*/ ) |
|
1702 ); |
|
1703 |
|
1704 CleanupStack::PushL( findItem ); |
|
1705 |
|
1706 // reset array |
|
1707 RArray<TCursorSelection>& highlights = aMessageWrapper.Highlights(); |
|
1708 RArray<TInt>& types = aMessageWrapper.HighlightTypes(); |
|
1709 highlights.Reset(); |
|
1710 types.Reset(); |
|
1711 |
|
1712 // get found items |
|
1713 const CArrayFixFlat<CFindItemEngine::SFoundItem>* items = |
|
1714 findItem->ItemArray(); |
|
1715 TInt count( items->Count() ); |
|
1716 |
|
1717 for( TInt i(0); i<count; ++i ) |
|
1718 { |
|
1719 const CFindItemEngine::SFoundItem item = items->At(i); |
|
1720 |
|
1721 // selection in rich text |
|
1722 TCursorSelection realSel( aStartPos + item.iStartPos + item.iLength, |
|
1723 aStartPos + item.iStartPos ); |
|
1724 |
|
1725 // relative selection inside one message |
|
1726 TCursorSelection relativeSel( aRelativePos + item.iStartPos + |
|
1727 item.iLength, |
|
1728 aRelativePos + item.iStartPos ); |
|
1729 |
|
1730 highlights.AppendL( relativeSel ); |
|
1731 types.AppendL( item.iItemType ); |
|
1732 |
|
1733 // apply highlight item formatting |
|
1734 if( iItemHighlight ) |
|
1735 { |
|
1736 HighLightItemL( realSel ); |
|
1737 } |
|
1738 } |
|
1739 |
|
1740 CleanupStack::PopAndDestroy( findItem ); |
|
1741 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ParseTextL() end" )); |
|
1742 } |
|
1743 |
|
1744 // ----------------------------------------------------------------------------- |
|
1745 // CIMCVAppRichTextContainer::AddNickL |
|
1746 // (other items were commented in a header). |
|
1747 // ----------------------------------------------------------------------------- |
|
1748 // |
|
1749 TCursorSelection CIMCVAppRichTextContainer::AddNickL( |
|
1750 CIMCVAppMessageWrapper& aMessageWrapper ) |
|
1751 { |
|
1752 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddNickL() start" )); |
|
1753 // insert nick |
|
1754 MIMCVEngineMessage& message = aMessageWrapper.Message(); |
|
1755 TPtrC sender; |
|
1756 TPtrC recipient; |
|
1757 if( message.MessageType() == MIMCVEngineMessage::EMessageGroup || |
|
1758 message.MessageType() == MIMCVEngineMessage::EMessageWhisper ) |
|
1759 { |
|
1760 sender.Set( message.Sender() ); |
|
1761 recipient.Set( message.Recipient() ); |
|
1762 } |
|
1763 // need to implements todo |
|
1764 TCursorSelection nickSel( 0,0 ); |
|
1765 //============================================================================ |
|
1766 if( message.MessagerType() == MIMCVEngineMessage::EMessageSent && |
|
1767 message.MessageType() == MIMCVEngineMessage::EMessagePTOP) |
|
1768 { |
|
1769 CIMCVAppPicture* pic = new( ELeave )CIMCVAppPicture( *iMap, iFromMe ); |
|
1770 TPictureHeader header; |
|
1771 header.iPicture = TSwizzle<CPicture>(pic ); |
|
1772 iRichText->InsertL( iRichText->DocumentLength(), header );// takes ownership |
|
1773 iRichText->InsertL( iRichText->DocumentLength(), KSeparator ); |
|
1774 } |
|
1775 |
|
1776 else if( message.MessageType() == MIMCVEngineMessage::EMessagePTOP && |
|
1777 message.MessagerType() == MIMCVEngineMessage::EMessageReceived ) |
|
1778 { |
|
1779 // received p2p message and we want to display icon |
|
1780 // insert "to me" icon and separator |
|
1781 CIMCVAppPicture* pic = new( ELeave )CIMCVAppPicture( *iMap,iToMe ); |
|
1782 TPictureHeader header; |
|
1783 header.iPicture = TSwizzle<CPicture>( pic ); |
|
1784 iRichText->CancelInsertCharFormat(); // to prevent ETEXT 31 panic |
|
1785 iRichText->InsertL( iRichText->DocumentLength(), header ); // takes ownership |
|
1786 iRichText->InsertL( iRichText->DocumentLength(), KSeparator ); |
|
1787 } |
|
1788 //============================================================================ |
|
1789 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddNickL() end" )); |
|
1790 return nickSel; |
|
1791 } |
|
1792 |
|
1793 // ----------------------------------------------------------------------------- |
|
1794 // CIMCVAppSmileIconUtility::LoadDefaultBitmapL |
|
1795 // (other items were commented in a header). |
|
1796 // ----------------------------------------------------------------------------- |
|
1797 // |
|
1798 CGulIcon* CIMCVAppRichTextContainer::LoadDefaultBitmapL( TInt aBitmapId, TInt aMaskId, |
|
1799 const TDesC& aFullPath, TBool/* aOverrideBrand */) |
|
1800 { |
|
1801 |
|
1802 IM_CV_LOGS(TXT("CIMCVAppSmileIconUtility::LoadDefaultBitmapL() start") ); |
|
1803 CFbsBitmap* bitmap = NULL; |
|
1804 CFbsBitmap* mask = NULL; |
|
1805 |
|
1806 MAknsSkinInstance* skin = AknsUtils::SkinInstance(); |
|
1807 |
|
1808 TAknsItemID itemId( KAknsIIDNone ); |
|
1809 |
|
1810 AknsUtils::CreateIconLC( skin, |
|
1811 itemId, |
|
1812 bitmap, mask, aFullPath, aBitmapId, aMaskId ); |
|
1813 |
|
1814 CGulIcon* gulIcon = CGulIcon::NewL( bitmap, mask ); |
|
1815 CleanupStack::Pop( 2 ); // bitmap, mask |
|
1816 IM_CV_LOGS(TXT("CIMCVAppSmileIconUtility::LoadDefaultBitmapL() end") ); |
|
1817 return gulIcon; |
|
1818 } |
|
1819 |
|
1820 // ----------------------------------------------------------------------------- |
|
1821 // CIMCVAppRichTextContainer::AddTimeStampL |
|
1822 // (other items were commented in a header). |
|
1823 // ----------------------------------------------------------------------------- |
|
1824 // |
|
1825 TCursorSelection CIMCVAppRichTextContainer::AddTimeStampL( |
|
1826 CIMCVAppMessageWrapper& aMessageWrapper ) |
|
1827 { |
|
1828 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddTimeStampL() start" )); |
|
1829 TInt start = iRichText->DocumentLength(); |
|
1830 |
|
1831 TCursorSelection timeSel( start, start ); |
|
1832 |
|
1833 |
|
1834 // format time |
|
1835 HBufC* timeStamp = HBufC::NewLC( KTimeStampMaxLength + KSpace().Length() ); |
|
1836 TPtr timePtr( timeStamp->Des() ); |
|
1837 |
|
1838 HBufC* timeStampFormat = NULL; |
|
1839 timeStampFormat = StringLoader::LoadLC( R_QTN_TIME_USUAL_WITH_ZERO ); |
|
1840 |
|
1841 TTime time = aMessageWrapper.Message().TimeStamp(); |
|
1842 TRAPD( err, time.FormatL( timePtr, *timeStampFormat ) ); |
|
1843 if( err == KErrOverflow ) |
|
1844 { |
|
1845 // Reserved text space was not enough. |
|
1846 // Adjust the KTimeStampMaxLength! |
|
1847 // in release builds return without timestamp |
|
1848 CleanupStack::PopAndDestroy( 2, timeStamp); // timeStamp, timeStampFormat |
|
1849 return timeSel; |
|
1850 } |
|
1851 |
|
1852 // Convert numbers to local language |
|
1853 AknTextUtils::LanguageSpecificNumberConversion( timePtr ); |
|
1854 |
|
1855 // Set Alignment of Pm/Am from local setting |
|
1856 // This keeps the am/pm text close to the time. |
|
1857 timePtr.Append( AknLayoutUtils::LayoutMirrored() ? |
|
1858 KUnicodeRLM : KUnicodeLRM ); |
|
1859 |
|
1860 // append time to rich text |
|
1861 timePtr.Append( KSpace ); |
|
1862 iRichText->InsertL( start, timePtr ); |
|
1863 |
|
1864 CleanupStack::PopAndDestroy( 2, timeStamp); // timeStamp, timeStampFormat |
|
1865 timeSel.SetSelection( start, iRichText->DocumentLength() - 1 ); |
|
1866 |
|
1867 // bold the time |
|
1868 if( timeSel.Length() > 0 ) |
|
1869 { |
|
1870 BoldL( timeSel ); |
|
1871 } |
|
1872 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddTimeStampL() end" )); |
|
1873 return timeSel; |
|
1874 } |
|
1875 |
|
1876 // ----------------------------------------------------------------------------- |
|
1877 // CIMCVAppRichTextContainer::AddContentL |
|
1878 // (other items were commented in a header). |
|
1879 // ----------------------------------------------------------------------------- |
|
1880 // |
|
1881 void CIMCVAppRichTextContainer::AddContentL( TInt aMsgStart, |
|
1882 CIMCVAppMessageWrapper& aMessageWrapper ) |
|
1883 { |
|
1884 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddContentL() start" )); |
|
1885 MIMCVEngineMessage& message = aMessageWrapper.Message(); |
|
1886 |
|
1887 MIMCVEngineMessage::TContentType type( message.ContentType() ); |
|
1888 switch( type ) |
|
1889 { |
|
1890 case MIMCVEngineMessage::EContentText: |
|
1891 { |
|
1892 // insert text |
|
1893 //If received message is longer than 400 characters it will be truncated in imconnectionprovider |
|
1894 //so append truncation message to inform user that received message is truncated |
|
1895 HBufC* newmsg = HBufC::NewLC(KMsgMaxLength); |
|
1896 TPtr msg = newmsg->Des(); |
|
1897 if(message.Text().Length() > KReceiveMsgMaxLength) |
|
1898 { |
|
1899 msg.Append(message.Text().Left(KReceiveMsgMaxLength)); |
|
1900 HBufC* addText = StringLoader::LoadLC( R_QTN_CONVIEW_TRUNCATED ); |
|
1901 msg.Append(addText->Des()); |
|
1902 CleanupStack::PopAndDestroy(addText);//addText |
|
1903 } |
|
1904 else |
|
1905 { |
|
1906 msg.Append(message.Text()); |
|
1907 } |
|
1908 // TPtrC msg( message.Text() ); |
|
1909 HBufC* tempMsg = NULL; |
|
1910 |
|
1911 TInt paraBreak = msg.Locate( CEditableText::EParagraphDelimiter ); |
|
1912 // Replace all paragraph delimiters with line breaks |
|
1913 // to keep alingment consistent |
|
1914 if ( paraBreak != KErrNotFound ) |
|
1915 { |
|
1916 tempMsg = msg.AllocLC(); |
|
1917 TPtr ptr( tempMsg->Des() ); |
|
1918 ptr.Zero(); |
|
1919 |
|
1920 ReplaceParaDelimsWithLineBreaks( msg, ptr ); |
|
1921 msg.Set( ptr ); |
|
1922 } |
|
1923 |
|
1924 HBufC* numberConv = NULL; |
|
1925 |
|
1926 // Convert numerals to local language |
|
1927 // 1) date item |
|
1928 if( aMessageWrapper.Message().SystemMessageType() == |
|
1929 MIMCVEngineMessage::ESystemMessageDateChange ) |
|
1930 { |
|
1931 // don't touch the original message |
|
1932 numberConv = msg.AllocLC(); |
|
1933 TPtr ptr( numberConv->Des() ); |
|
1934 AknTextUtils::LanguageSpecificNumberConversion( ptr ); |
|
1935 msg.Set( ptr ); |
|
1936 } |
|
1937 |
|
1938 TInt textStart( iRichText->DocumentLength() ); |
|
1939 iRichText->InsertL( textStart, msg ); |
|
1940 |
|
1941 CleanupStack::PopAndDestroy(newmsg);//newmsg |
|
1942 // check for extensions (smileys) |
|
1943 TCursorSelection selection( iRichText->DocumentLength(), |
|
1944 textStart ); |
|
1945 iExtensionsHandler->ConvertSelectionToExtensionL( *iRichText, |
|
1946 selection , |
|
1947 iServiceId ); |
|
1948 |
|
1949 TInt textEnd( iRichText->DocumentLength() ); |
|
1950 |
|
1951 // add nbs to preserve formatting |
|
1952 iRichText->InsertL( iRichText->DocumentLength(), |
|
1953 CEditableText::EZeroWidthNoBreakSpace ); |
|
1954 |
|
1955 // if this is system message, it should be bold |
|
1956 if( message.MessageType() == MIMCVEngineMessage::EMessageSystem ) |
|
1957 { |
|
1958 TCursorSelection sel( textStart, textEnd ); |
|
1959 BoldL( sel ); |
|
1960 // System messages need different kind of alignment |
|
1961 CParaFormat paraFormat; |
|
1962 TParaFormatMask paraFormatMask; |
|
1963 paraFormat.iLeftMarginInTwips = 0; |
|
1964 paraFormatMask.SetAttrib( EAttLeftMargin ); |
|
1965 iRichText->ApplyParaFormatL( ¶Format, paraFormatMask, |
|
1966 textStart, sel.Length() ); |
|
1967 } |
|
1968 else |
|
1969 { |
|
1970 // Apply alignment for "normal" messages |
|
1971 CParaFormat paraFormat; |
|
1972 TParaFormatMask paraFormatMask; |
|
1973 paraFormat.iLeftMarginInTwips = 100; |
|
1974 paraFormatMask.SetAttrib( EAttLeftMargin ); |
|
1975 iRichText->ApplyParaFormatL( ¶Format, paraFormatMask, |
|
1976 textStart, textEnd - textStart ); |
|
1977 } |
|
1978 |
|
1979 // parse text for highlights and store positions to messagewrapper |
|
1980 HBufC* text = HBufC::NewMaxLC( textEnd-textStart ); |
|
1981 TPtr txt( text->Des() ); |
|
1982 iRichText->Extract( txt, textStart, textEnd-textStart ); |
|
1983 ParseTextL( txt, textStart, textStart-aMsgStart, aMessageWrapper ); |
|
1984 CleanupStack::PopAndDestroy( text ); |
|
1985 |
|
1986 // Cleanup |
|
1987 if( numberConv ) |
|
1988 { |
|
1989 CleanupStack::PopAndDestroy( numberConv ); |
|
1990 } |
|
1991 if ( tempMsg ) |
|
1992 { |
|
1993 CleanupStack::PopAndDestroy( tempMsg ); |
|
1994 } |
|
1995 break; |
|
1996 } |
|
1997 |
|
1998 default: |
|
1999 { |
|
2000 // unsupported type |
|
2001 |
|
2002 break; |
|
2003 } |
|
2004 } |
|
2005 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddContentL() end" )); |
|
2006 } |
|
2007 |
|
2008 |
|
2009 // ----------------------------------------------------------------------------- |
|
2010 // CIMCVAppRichTextContainer::UpdateSkinnedTextColourL |
|
2011 // (other items were commented in a header). |
|
2012 // ----------------------------------------------------------------------------- |
|
2013 // |
|
2014 void CIMCVAppRichTextContainer::UpdateSkinnedTextColourL() |
|
2015 { |
|
2016 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateSkinnedTextColourL() start" )); |
|
2017 // Get current text's color |
|
2018 TRgb defaultSkinTextColor( KRgbBlack ); |
|
2019 AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), |
|
2020 defaultSkinTextColor, |
|
2021 KAknsIIDQsnTextColors, |
|
2022 EAknsCIQsnTextColorsCG6 ); |
|
2023 |
|
2024 TCharFormat charFormat; |
|
2025 TCharFormatMask charFormatMask; |
|
2026 charFormat.iFontPresentation.iTextColor = defaultSkinTextColor; |
|
2027 charFormatMask.SetAttrib( EAttColor ); |
|
2028 |
|
2029 // also appended messages should have new colour |
|
2030 TInt richTextDocumentLength = iRichText->DocumentLength(); |
|
2031 |
|
2032 iRichText->ApplyCharFormatL ( charFormat, charFormatMask, 0, richTextDocumentLength); |
|
2033 TCursorSelection cursorSelection(0, richTextDocumentLength); |
|
2034 iTextView->HandleFormatChangedL (cursorSelection); |
|
2035 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateSkinnedTextColourL() end" )); |
|
2036 } |
|
2037 |
|
2038 // ----------------------------------------------------------------------------- |
|
2039 // CIMCVAppRichTextContainer::SkinColoredSelection |
|
2040 // (other items were commented in a header). |
|
2041 // ----------------------------------------------------------------------------- |
|
2042 // |
|
2043 TCursorSelection CIMCVAppRichTextContainer::SkinColoredSelection( |
|
2044 CIMCVAppMessageWrapper& aMessageWrapper, |
|
2045 TBool aUseDefaultColors, |
|
2046 TBool aCustomDefinedColor ) |
|
2047 { |
|
2048 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SkinColoredSelection() start" )); |
|
2049 // This logic determines which part of the message is colored by the theme |
|
2050 if( !aCustomDefinedColor && aUseDefaultColors ) |
|
2051 { |
|
2052 return aMessageWrapper.WholeSelection(); |
|
2053 } |
|
2054 |
|
2055 if( !iColorWholeMessage ) |
|
2056 { |
|
2057 return aMessageWrapper.MessageSelection(); |
|
2058 } |
|
2059 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SkinColoredSelection() end" )); |
|
2060 return TCursorSelection( 0, 0 ); |
|
2061 } |
|
2062 |
|
2063 // ----------------------------------------------------------------------------- |
|
2064 // CIMCVAppRichTextContainer::ReplaceParaDelimsWithLineBreaks |
|
2065 // (other items were commented in a header). |
|
2066 // ----------------------------------------------------------------------------- |
|
2067 // |
|
2068 void CIMCVAppRichTextContainer::ReplaceParaDelimsWithLineBreaks( |
|
2069 const TPtrC& aSource, |
|
2070 TPtr& aTarget ) const |
|
2071 { |
|
2072 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ReplaceParaDelimsWithLineBreaks() start" )); |
|
2073 #ifdef _DEBUG |
|
2074 TPtrC target; |
|
2075 target.Set( aTarget ); |
|
2076 |
|
2077 #endif |
|
2078 |
|
2079 TInt paraBreak = aSource.Mid( aTarget.Length() ).Locate( |
|
2080 CEditableText::EParagraphDelimiter ); |
|
2081 |
|
2082 if ( paraBreak == KErrNotFound ) |
|
2083 { |
|
2084 // No more paragraph delimiters, append what's left |
|
2085 aTarget.Append( aSource.Mid( aTarget.Length() ) ); |
|
2086 // And break away from recursion |
|
2087 return; |
|
2088 } |
|
2089 |
|
2090 aTarget.Append( aSource.Mid( aTarget.Length(), paraBreak ) ); |
|
2091 aTarget.Append( CEditableText::ELineBreak ); |
|
2092 |
|
2093 #ifdef _DEBUG |
|
2094 target.Set( aTarget ); |
|
2095 |
|
2096 #endif |
|
2097 |
|
2098 ReplaceParaDelimsWithLineBreaks( aSource, aTarget ); |
|
2099 IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ReplaceParaDelimsWithLineBreaks() end" )); |
|
2100 } |
|
2101 |
|
2102 // ----------------------------------------------------------------------------- |
|
2103 // CIMCVAppRichTextContainer::GetPrimaryKey |
|
2104 // (other items were commented in a header). |
|
2105 // ----------------------------------------------------------------------------- |
|
2106 // |
|
2107 |
|
2108 const TDesC& CIMCVAppRichTextContainer::GetPrimaryKey() |
|
2109 { |
|
2110 if( iPrimaryKey) |
|
2111 { |
|
2112 return *iPrimaryKey; |
|
2113 } |
|
2114 return KNullDesC; |
|
2115 } |
|
2116 // End of File |
|