|
1 /* |
|
2 * Copyright (c) 2002 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: MsgAttachmentControl implementation |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // ========== INCLUDE FILES ================================ |
|
21 |
|
22 #include <barsread.h> // for TResourceReader |
|
23 #include <txtrich.h> // for CRichText |
|
24 |
|
25 #include <eikenv.h> // for CEikonEnv |
|
26 #include <eikappui.h> // for CEikAppUi |
|
27 #include <eikedwin.h> // for TClipboardFunc |
|
28 #include <eiklabel.h> |
|
29 |
|
30 #include <AknUtils.h> // for AknUtils |
|
31 #include <aknbutton.h> // for CAknButton |
|
32 |
|
33 #include <MsgAttachmentModel.h> |
|
34 #include <MsgAttachmentInfo.h> |
|
35 |
|
36 #include <gulicon.h> |
|
37 #include <AknsUtils.h> |
|
38 #include <AknsConstants.h> |
|
39 #include <aknlayoutscalable_apps.cdl.h> |
|
40 |
|
41 #include <data_caging_path_literals.hrh> |
|
42 #include <msgeditor.mbg> |
|
43 |
|
44 #ifdef RD_TACTILE_FEEDBACK |
|
45 #include <touchfeedback.h> |
|
46 #endif |
|
47 |
|
48 #include "MsgAttachmentControl.h" // for CMsgAttachmentControl |
|
49 #include "MsgExpandableControlEditor.h" // for CMsgExpandableControlEditor |
|
50 #include "MsgBaseControlObserver.h" // for MMsgBaseControlObserver |
|
51 #include "MsgEditorView.h" |
|
52 #include "MsgEditorPanic.h" // for CMsgEditor panics |
|
53 #include "MsgEditorCommon.h" // for KArabicSemicolon |
|
54 #include "MsgEditorCustomDraw.h" // for CMsgEditorCustomDraw |
|
55 |
|
56 // ========== EXTERNAL DATA STRUCTURES ===================== |
|
57 |
|
58 // ========== EXTERNAL FUNCTION PROTOTYPES ================= |
|
59 |
|
60 // ========== CONSTANTS ==================================== |
|
61 |
|
62 // Default color for EAknsCIQsnIconColorsCG13 group icons |
|
63 const TInt KDefaultAttachmentColor = 215; |
|
64 |
|
65 // ========== MACROS ======================================= |
|
66 |
|
67 // ========== LOCAL CONSTANTS AND MACROS =================== |
|
68 |
|
69 const TInt KAttachmentArrayGranularity = 10; |
|
70 |
|
71 _LIT( KAttachmentListSeparator, ", " ); |
|
72 _LIT( KIconMbmFile, "msgeditor.mbm" ); |
|
73 _LIT( KStripList, "\x000A\x000D\x2029\x2028\x0085" ); |
|
74 |
|
75 const TText KZeroWidthJoiner = 0x200D; |
|
76 const TText KLRMarker = 0x200E; |
|
77 const TText KRLMarker = 0x200F; |
|
78 |
|
79 const TInt KScrollStartDelay = 1500000; // 1,5 s |
|
80 const TInt KScrollEndDelay = 500000; // 0,5 s |
|
81 const TInt KScrollRestartDelay = 3000000; // 3 s. |
|
82 const TInt KScrollTickDelay = 135000; // 0,135s |
|
83 const TInt KScrollJumpAreaDivider = 15; |
|
84 |
|
85 // ========== MODULE DATA STRUCTURES ======================= |
|
86 |
|
87 // ========== LOCAL FUNCTION PROTOTYPES ==================== |
|
88 |
|
89 // ========== LOCAL FUNCTIONS ============================== |
|
90 |
|
91 // ========== MEMBER FUNCTIONS ============================= |
|
92 |
|
93 |
|
94 // --------------------------------------------------------- |
|
95 // CMsgAttachmentControl::CMsgAttachmentControl |
|
96 // |
|
97 // Constructor. |
|
98 // --------------------------------------------------------- |
|
99 // |
|
100 CMsgAttachmentControl::CMsgAttachmentControl( |
|
101 MMsgBaseControlObserver& aBaseControlObserver, |
|
102 CMsgEditorView& aView ) : |
|
103 CMsgExpandableControl( aBaseControlObserver ), |
|
104 iScrollPos( EScrollPosBeginning ) |
|
105 { |
|
106 iControlType = EMsgAttachmentControl; |
|
107 iControlId = EMsgComponentIdAttachment; |
|
108 |
|
109 SetMopParent( &aView ); |
|
110 } |
|
111 |
|
112 // --------------------------------------------------------- |
|
113 // CMsgAttachmentControl::ConstructL |
|
114 // |
|
115 // 2nd phase constructor. After base class initialization creates |
|
116 // attachment array that holds the attachment name strings. Empty |
|
117 // caption control is also created for base class purposes. NOTE! This is |
|
118 // something that would be good to get rid off. Initializes editor control |
|
119 // and sets itself as it's edwin event, edwin size event and |
|
120 // control event observer. Creates editor is set as readonly and cursor is |
|
121 // hidden. Focus must stop to this control when navigating. No formatting |
|
122 // is allowed. Label icon and if pen input (i.e. touch screen) is enabled |
|
123 // then also button are created. Initializes marquee scroll timer and |
|
124 // layout related parameters. |
|
125 // --------------------------------------------------------- |
|
126 // |
|
127 void CMsgAttachmentControl::ConstructL() |
|
128 { |
|
129 BaseConstructL(); // Sets margins only. |
|
130 |
|
131 iAttachmentArray = new( ELeave ) CDesCArrayFlat( KAttachmentArrayGranularity ); |
|
132 |
|
133 // Create empty caption. (Needed by base class.) |
|
134 iCaption = new( ELeave ) CEikLabel; |
|
135 |
|
136 // Create editor. |
|
137 iEditor = new( ELeave ) CMsgExpandableControlEditor( this, |
|
138 iControlModeFlags, |
|
139 iBaseControlObserver ); |
|
140 iEditor->SetControlType(iControlType); |
|
141 iEditor->ConstructL(); |
|
142 iEditor->SetObserver( this ); |
|
143 iEditor->SetEdwinSizeObserver( this ); |
|
144 iEditor->AddEdwinObserverL( this ); |
|
145 iEditor->SetReadOnly( ETrue ); |
|
146 iEditor->AddFlagToUserFlags( CEikEdwin::EAvkonDisableCursor ); |
|
147 |
|
148 iControlModeFlags |= EMsgControlModeForceFocusStop; |
|
149 |
|
150 SetPlainTextMode( ETrue ); |
|
151 |
|
152 iLabelIcon = CreateAttachmentIconsL(); |
|
153 |
|
154 #ifdef RD_SCALABLE_UI_V2 |
|
155 if ( AknLayoutUtils::PenEnabled() ) |
|
156 { |
|
157 CreateButtonL(); |
|
158 } |
|
159 #endif // RD_SCALABLE_UI_V2 |
|
160 |
|
161 iScrollTimer = CPeriodic::NewL( EPriorityNormal ); |
|
162 |
|
163 ResolveLayoutsL(); |
|
164 } |
|
165 |
|
166 // ---------------------------------------------------------------------------- |
|
167 // CMsgAttachmentControl::NewL |
|
168 // Symbian two phased constructor |
|
169 // ---------------------------------------------------------------------------- |
|
170 // |
|
171 EXPORT_C CMsgAttachmentControl* CMsgAttachmentControl::NewL( |
|
172 MMsgBaseControlObserver& aBaseControlObserver, |
|
173 CMsgEditorView& aView ) |
|
174 { |
|
175 CMsgAttachmentControl* self = new( ELeave ) CMsgAttachmentControl( aBaseControlObserver, |
|
176 aView ); |
|
177 |
|
178 CleanupStack::PushL( self ); |
|
179 self->ConstructL(); |
|
180 CleanupStack::Pop( self ); |
|
181 |
|
182 return self; |
|
183 } |
|
184 |
|
185 // --------------------------------------------------------- |
|
186 // CMsgAttachmentControl::~CMsgAttachmentControl |
|
187 // |
|
188 // Destructor. |
|
189 // --------------------------------------------------------- |
|
190 // |
|
191 CMsgAttachmentControl::~CMsgAttachmentControl() |
|
192 { |
|
193 if ( iAttachmentArray ) |
|
194 { |
|
195 iAttachmentArray->Reset(); |
|
196 } |
|
197 |
|
198 delete iAttachmentArray; |
|
199 delete iLabelIcon; |
|
200 delete iScrollTimer; |
|
201 } |
|
202 |
|
203 // --------------------------------------------------------- |
|
204 // CMsgAttachmentControl::AppendAttachmentL |
|
205 // |
|
206 // |
|
207 // --------------------------------------------------------- |
|
208 // |
|
209 EXPORT_C void CMsgAttachmentControl::AppendAttachmentL( const TDesC& aName ) |
|
210 { |
|
211 InsertAttachmentL( aName, Count() ); |
|
212 } |
|
213 |
|
214 // --------------------------------------------------------- |
|
215 // CMsgAttachmentControl::InsertAttachmentL |
|
216 // |
|
217 // |
|
218 // --------------------------------------------------------- |
|
219 // |
|
220 EXPORT_C void CMsgAttachmentControl::InsertAttachmentL( const TDesC& aName, TInt aIndex ) |
|
221 { |
|
222 AddToAttachmentArrayL( aName, aIndex ); |
|
223 |
|
224 UpdateControlL(); |
|
225 } |
|
226 |
|
227 // --------------------------------------------------------- |
|
228 // CMsgAttachmentControl::AddAttachmentL |
|
229 // |
|
230 // |
|
231 // --------------------------------------------------------- |
|
232 // |
|
233 EXPORT_C void CMsgAttachmentControl::AddAttachmentsL( const MDesCArray& aNames ) |
|
234 { |
|
235 Reset(); |
|
236 |
|
237 for ( TInt i = 0; i < aNames.MdcaCount(); i++ ) |
|
238 { |
|
239 AddToAttachmentArrayL( aNames.MdcaPoint( i ), Count() ); |
|
240 } |
|
241 |
|
242 UpdateControlL(); |
|
243 } |
|
244 |
|
245 |
|
246 // --------------------------------------------------------- |
|
247 // CMsgAttachmentControl::AddAttachmentL |
|
248 // |
|
249 // |
|
250 // --------------------------------------------------------- |
|
251 // |
|
252 EXPORT_C void CMsgAttachmentControl::AddAttachmentsL( const CMsgAttachmentModel& aModel ) |
|
253 { |
|
254 Reset(); |
|
255 |
|
256 TParse* parser = new( ELeave ) TParse ; |
|
257 CleanupStack::PushL( parser ); |
|
258 |
|
259 for ( TInt i = 0; i < aModel.NumberOfItems(); i++ ) |
|
260 { |
|
261 parser->Set( aModel.AttachmentInfoAt( i ).FileName(),NULL, NULL ); |
|
262 AddToAttachmentArrayL( parser->NameAndExt(), Count() ); |
|
263 } |
|
264 |
|
265 CleanupStack::PopAndDestroy( parser ); |
|
266 UpdateControlL(); |
|
267 } |
|
268 |
|
269 // --------------------------------------------------------- |
|
270 // CMsgAttachmentControl::RemoveAttachmentL |
|
271 // --------------------------------------------------------- |
|
272 // |
|
273 EXPORT_C void CMsgAttachmentControl::RemoveAttachmentL( const TDesC& aName ) |
|
274 { |
|
275 HBufC* convertedFileName = AknTextUtils::ConvertFileNameL( aName ); |
|
276 CleanupStack::PushL( convertedFileName ); |
|
277 |
|
278 TPtr convertedFileNamePtr = convertedFileName->Des(); |
|
279 |
|
280 AknTextUtils::StripCharacters( convertedFileNamePtr, KAknStripListControlChars ); |
|
281 |
|
282 TInt pos( KErrNotFound ); |
|
283 if ( iAttachmentArray->Find( *convertedFileName, pos ) == 0 ) |
|
284 { |
|
285 RemoveAttachmentL( pos ); |
|
286 } |
|
287 |
|
288 CleanupStack::PopAndDestroy( convertedFileName ); |
|
289 } |
|
290 |
|
291 // --------------------------------------------------------- |
|
292 // CMsgAttachmentControl::RemoveAttachmentL |
|
293 // --------------------------------------------------------- |
|
294 // |
|
295 EXPORT_C void CMsgAttachmentControl::RemoveAttachmentL( TInt aIndex ) |
|
296 { |
|
297 iAttachmentArray->Delete( aIndex ); |
|
298 UpdateControlL(); |
|
299 } |
|
300 |
|
301 // --------------------------------------------------------- |
|
302 // CMsgAttachmentControl::Reset |
|
303 // |
|
304 // from CMsgBaseControl. |
|
305 // Same as above but non-leaving version. |
|
306 // --------------------------------------------------------- |
|
307 // |
|
308 EXPORT_C void CMsgAttachmentControl::Reset() |
|
309 { |
|
310 if ( iAttachmentArray ) |
|
311 { |
|
312 iAttachmentArray->Reset(); |
|
313 } |
|
314 if ( iEditor ) |
|
315 { |
|
316 iEditor->Reset(); |
|
317 } |
|
318 } |
|
319 |
|
320 |
|
321 // --------------------------------------------------------- |
|
322 // CMsgAttachmentControl::Count |
|
323 // --------------------------------------------------------- |
|
324 // |
|
325 EXPORT_C TInt CMsgAttachmentControl::Count() const |
|
326 { |
|
327 return iAttachmentArray->MdcaCount(); |
|
328 } |
|
329 |
|
330 // --------------------------------------------------------- |
|
331 // CMsgAttachmentControl::Attachment |
|
332 // --------------------------------------------------------- |
|
333 // |
|
334 EXPORT_C TPtrC CMsgAttachmentControl::Attachment( TInt aIndex ) const |
|
335 { |
|
336 return iAttachmentArray->MdcaPoint( aIndex ); |
|
337 } |
|
338 |
|
339 // --------------------------------------------------------- |
|
340 // CMsgAttachmentControl::ConstructFromResourceL |
|
341 // |
|
342 // Creates this control from resource. |
|
343 // --------------------------------------------------------- |
|
344 // |
|
345 void CMsgAttachmentControl::ConstructFromResourceL( TInt aResourceId ) |
|
346 { |
|
347 TResourceReader reader; |
|
348 iCoeEnv->CreateResourceReaderLC( reader, aResourceId ); |
|
349 |
|
350 // Read some information about control from resource. |
|
351 ReadControlPropertiesFromResourceL( reader ); |
|
352 |
|
353 ConstructL(); |
|
354 |
|
355 CleanupStack::PopAndDestroy(); // reader |
|
356 } |
|
357 |
|
358 // --------------------------------------------------------- |
|
359 // CMsgAttachmentControl::EditPermission |
|
360 // |
|
361 // Checks and returns control's edit permissions. Edit permissions are needed |
|
362 // to check in order to know whether some key press is allowed to pass |
|
363 // to the control or not. |
|
364 // --------------------------------------------------------- |
|
365 // |
|
366 TUint32 CMsgAttachmentControl::EditPermission() const |
|
367 { |
|
368 return CMsgBaseControl::EMsgEditNone; |
|
369 } |
|
370 |
|
371 // --------------------------------------------------------- |
|
372 // CMsgAttachmentControl::NotifyViewEvent |
|
373 // |
|
374 // Builds up text fields for the control i.e. reads verified recipients and |
|
375 // creates corresponding text fields for them. |
|
376 // --------------------------------------------------------- |
|
377 // |
|
378 void CMsgAttachmentControl::NotifyViewEvent( TMsgViewEvent aEvent, TInt aParam ) |
|
379 { |
|
380 if ( IsReadOnly() ) |
|
381 { |
|
382 aParam |= EMsgViewEventAutoHighlight; |
|
383 } |
|
384 |
|
385 if ( aEvent != EMsgViewEventSetCursorFirstPos && |
|
386 aEvent != EMsgViewEventSetCursorLastPos ) |
|
387 { |
|
388 CMsgExpandableControl::NotifyViewEvent( aEvent, aParam ); |
|
389 } |
|
390 } |
|
391 |
|
392 |
|
393 // --------------------------------------------------------- |
|
394 // CMsgAttachmentControl::PrepareForReadOnly |
|
395 // --------------------------------------------------------- |
|
396 // |
|
397 void CMsgAttachmentControl::PrepareForReadOnly( TBool aReadOnly ) |
|
398 { |
|
399 if ( aReadOnly ) |
|
400 { |
|
401 TRAP_IGNORE( iEditor->SetHighlightStyleL( EEikEdwinHighlightLink ) ); |
|
402 } |
|
403 } |
|
404 |
|
405 // --------------------------------------------------------- |
|
406 // CMsgAttachmentControl::CountComponentControls |
|
407 // |
|
408 // Returns a number of controls. |
|
409 // --------------------------------------------------------- |
|
410 // |
|
411 TInt CMsgAttachmentControl::CountComponentControls() const |
|
412 { |
|
413 TInt result( 1 ); |
|
414 |
|
415 if ( iButton ) |
|
416 { |
|
417 result++; |
|
418 } |
|
419 |
|
420 return result; |
|
421 } |
|
422 |
|
423 // --------------------------------------------------------- |
|
424 // CMsgAttachmentControl::ComponentControl |
|
425 // |
|
426 // Returns a control of index aIndex. |
|
427 // --------------------------------------------------------- |
|
428 // |
|
429 CCoeControl* CMsgAttachmentControl::ComponentControl( TInt aIndex ) const |
|
430 { |
|
431 CCoeControl* result = NULL; |
|
432 switch ( aIndex ) |
|
433 { |
|
434 case 0: |
|
435 { |
|
436 result = iEditor; |
|
437 break; |
|
438 } |
|
439 case 1: |
|
440 { |
|
441 result = iButton; |
|
442 break; |
|
443 } |
|
444 default: |
|
445 { |
|
446 break; |
|
447 } |
|
448 } |
|
449 |
|
450 return result; |
|
451 } |
|
452 |
|
453 // --------------------------------------------------------- |
|
454 // CMsgAttachmentControl::OfferKeyEventL |
|
455 // |
|
456 // Handles key events. The most of the keys are passed to the control editor. |
|
457 // --------------------------------------------------------- |
|
458 // |
|
459 TKeyResponse CMsgAttachmentControl::OfferKeyEventL( |
|
460 const TKeyEvent& /*aKeyEvent*/, TEventCode /*aType*/ ) |
|
461 { |
|
462 return EKeyWasNotConsumed; |
|
463 } |
|
464 |
|
465 // --------------------------------------------------------- |
|
466 // CMsgAttachmentControl::HandleResourceChange |
|
467 // |
|
468 // Handles resouce change events. Event are passed to the base |
|
469 // class and if layout has been switched new layouts are resolved |
|
470 // from LAF. |
|
471 // --------------------------------------------------------- |
|
472 // |
|
473 void CMsgAttachmentControl::HandleResourceChange( TInt aType ) |
|
474 { |
|
475 TRAP_IGNORE( |
|
476 { |
|
477 DoHandleResourceChangeBeforeL( aType ); |
|
478 |
|
479 CMsgExpandableControl::HandleResourceChange( aType ); |
|
480 |
|
481 DoHandleResourceChangeAfterL( aType ); |
|
482 } ); |
|
483 } |
|
484 |
|
485 // --------------------------------------------------------- |
|
486 // CMsgAttachmentControl::HandlePointerEventL |
|
487 // |
|
488 // Pointer event handling is disabled on editor |
|
489 // --------------------------------------------------------- |
|
490 // |
|
491 void CMsgAttachmentControl::HandlePointerEventL( const TPointerEvent& aPointerEvent ) |
|
492 { |
|
493 if ( !iEditor->Rect().Contains( aPointerEvent.iPosition ) ) |
|
494 { |
|
495 CMsgExpandableControl::HandlePointerEventL( aPointerEvent ); |
|
496 } |
|
497 #ifdef RD_TACTILE_FEEDBACK |
|
498 else if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) |
|
499 { |
|
500 MTouchFeedback* feedback = MTouchFeedback::Instance(); |
|
501 if ( feedback ) |
|
502 { |
|
503 feedback->InstantFeedback( this, ETouchFeedbackBasic ); |
|
504 } |
|
505 } |
|
506 #endif |
|
507 } |
|
508 |
|
509 // --------------------------------------------------------- |
|
510 // CMsgAttachmentControl::FocusChanged |
|
511 // |
|
512 // This is called when the focus of the control is changed. |
|
513 // --------------------------------------------------------- |
|
514 // |
|
515 void CMsgAttachmentControl::FocusChanged( TDrawNow aDrawNow ) |
|
516 { |
|
517 CMsgExpandableControl::FocusChanged( aDrawNow ); |
|
518 |
|
519 if ( IsReadOnly() ) |
|
520 { |
|
521 TRAP_IGNORE( UpdateFocusL() ); |
|
522 } |
|
523 |
|
524 if ( iAutomaticScrolling ) |
|
525 { |
|
526 StopAutomaticScrolling(); |
|
527 |
|
528 if ( IsFocused() ) |
|
529 { |
|
530 StartAutomaticScrolling( KScrollStartDelay ); |
|
531 } |
|
532 else |
|
533 { |
|
534 // Reset text to the beginning when focus is lost. |
|
535 iScrollPos = EScrollPosBeginning; |
|
536 TRAP_IGNORE( SetTextForEditorL( EFalse, ETrue ) ); |
|
537 |
|
538 // Reset the text view to it's original position. |
|
539 iEditor->TextView()->SetLeftTextMargin( 0 ); |
|
540 } |
|
541 } |
|
542 } |
|
543 |
|
544 // --------------------------------------------------------- |
|
545 // CMsgAttachmentControl::Draw |
|
546 // Attachment icon is drawn to the line indicated by LAF x |
|
547 // coordinate and controls current y coordinate. |
|
548 // Attachment icon is also centered vertically to current |
|
549 // control height. |
|
550 // --------------------------------------------------------- |
|
551 // |
|
552 void CMsgAttachmentControl::Draw( const TRect& /*aRect*/ ) const |
|
553 { |
|
554 if ( !iButton ) |
|
555 { |
|
556 TPoint tlc( iIconLayout.Rect().iTl.iX, Position().iY ); |
|
557 tlc.iY += ( Size().iHeight - iIconLayout.Rect().Size().iHeight ) / 2; |
|
558 |
|
559 SystemGc().BitBltMasked( tlc, |
|
560 iLabelIcon->Bitmap(), |
|
561 iIconLayout.Rect().Size(), |
|
562 iLabelIcon->Mask(), |
|
563 EFalse ); |
|
564 } |
|
565 } |
|
566 |
|
567 // --------------------------------------------------------- |
|
568 // CMsgAttachmentControl::ActivateL |
|
569 // --------------------------------------------------------- |
|
570 // |
|
571 void CMsgAttachmentControl::ActivateL() |
|
572 { |
|
573 CMsgExpandableControl::ActivateL(); |
|
574 |
|
575 // Needs to be called after CEikEdwin::ActivateL as |
|
576 // panics if CEikEdwin::iTextView is not present |
|
577 iEditor->SetWordWrapL( EFalse ); |
|
578 |
|
579 // Cursor is set to the beginning of text. |
|
580 iEditor->SetCursorPosL( 0, EFalse ); |
|
581 |
|
582 if ( iEditor->TextView() ) |
|
583 { |
|
584 const CFont* font = iEditorLayout.Font(); |
|
585 TInt scrollJump( font->WidthZeroInPixels() ); |
|
586 if ( scrollJump == 0 ) |
|
587 { |
|
588 // Font gave us invalid scrollJump have to make |
|
589 // estimate according to scroll area. |
|
590 scrollJump = iEditorLayout.TextRect().Width() / KScrollJumpAreaDivider; |
|
591 } |
|
592 iEditor->TextView()->SetHorizontalScrollJump( scrollJump ); |
|
593 } |
|
594 } |
|
595 |
|
596 // --------------------------------------------------------- |
|
597 // CMsgAttachmentControl::UpdateControlL |
|
598 // --------------------------------------------------------- |
|
599 // |
|
600 void CMsgAttachmentControl::UpdateControlL() |
|
601 { |
|
602 SetTextForEditorL( ETrue, ETrue ); |
|
603 |
|
604 if ( iScrollTimer->IsActive() ) |
|
605 { |
|
606 // Restart scrolling when attachment list is modified. |
|
607 iScrollPos = EScrollPosBeginning; |
|
608 StartAutomaticScrolling( KScrollStartDelay ); |
|
609 } |
|
610 |
|
611 DrawDeferred(); |
|
612 iControlModeFlags |= EMsgControlModeModified; |
|
613 } |
|
614 |
|
615 |
|
616 // --------------------------------------------------------- |
|
617 // CMsgAttachmentControl::SetTextForEditorL |
|
618 // --------------------------------------------------------- |
|
619 // |
|
620 void CMsgAttachmentControl::SetTextForEditorL( TBool aContentChanged, TBool aClipText ) |
|
621 { |
|
622 TInt count = iAttachmentArray->Count(); |
|
623 TInt length = 0; |
|
624 |
|
625 for ( TInt i = 0; i < count; i++ ) |
|
626 { |
|
627 length += iAttachmentArray->MdcaPoint( i ).Length(); |
|
628 length += KAttachmentListSeparator().Length(); |
|
629 } |
|
630 |
|
631 HBufC* buf = HBufC::NewLC( length ); |
|
632 TPtr temp = buf->Des(); |
|
633 |
|
634 for ( TInt j = 0; j < count; j++ ) |
|
635 { |
|
636 temp.Append( iAttachmentArray->MdcaPoint( j ) ); |
|
637 if ( j < count - 1 ) |
|
638 { |
|
639 temp.Append( KAttachmentListSeparator ); |
|
640 } |
|
641 } |
|
642 |
|
643 const CFont* font = iEditorLayout.Font(); |
|
644 |
|
645 TInt clipWidth = 0; |
|
646 |
|
647 if ( iEditor->TextView() ) |
|
648 { |
|
649 clipWidth = iEditor->TextView()->ViewRect().Width(); |
|
650 } |
|
651 else |
|
652 { |
|
653 clipWidth = iEditorLayout.TextRect().Width(); |
|
654 } |
|
655 |
|
656 TBool enableAutomaticScrolling( ETrue ); |
|
657 if ( temp.Length() == 0 ) |
|
658 { |
|
659 // Disable all processing if field is empty. |
|
660 enableAutomaticScrolling = EFalse; |
|
661 aContentChanged = EFalse; |
|
662 } |
|
663 |
|
664 if ( aContentChanged ) |
|
665 { |
|
666 // Attachment array has been updated. |
|
667 TInt fits = font->TextCount( temp, clipWidth ); |
|
668 |
|
669 if ( fits >= temp.Length() ) |
|
670 { |
|
671 // All text fits to the field. No automatic scrolling. |
|
672 enableAutomaticScrolling = EFalse; |
|
673 } |
|
674 } |
|
675 |
|
676 if ( enableAutomaticScrolling ) |
|
677 { |
|
678 EnableAutomaticScrolling(); |
|
679 |
|
680 if ( aClipText ) |
|
681 { |
|
682 ClipTextL( temp, clipWidth ); |
|
683 } |
|
684 } |
|
685 else |
|
686 { |
|
687 DisableAutomaticScrolling(); |
|
688 } |
|
689 |
|
690 // Replaces old text with new text. |
|
691 iEditor->SetTextL( buf ); |
|
692 |
|
693 if ( IsActivated() && iEditor->CursorPos() != 0 ) |
|
694 { |
|
695 // Cursor is set to the beginning of text. |
|
696 // Should not be called for non-activated control. |
|
697 iEditor->SetCursorPosL( 0, EFalse ); |
|
698 } |
|
699 |
|
700 CleanupStack::PopAndDestroy( buf ); |
|
701 } |
|
702 |
|
703 // --------------------------------------------------------- |
|
704 // CMsgAttachmentControl::ResolveLayoutsL |
|
705 // |
|
706 // --------------------------------------------------------- |
|
707 // |
|
708 void CMsgAttachmentControl::ResolveLayoutsL() |
|
709 { |
|
710 TAknLayoutRect msgTextPane; |
|
711 msgTextPane.LayoutRect( MsgEditorCommons::MsgDataPane(), |
|
712 AknLayoutScalable_Apps::msg_text_pane( 0 ).LayoutLine() ); |
|
713 |
|
714 TAknLayoutRect msgHeaderPane; |
|
715 msgHeaderPane.LayoutRect( msgTextPane.Rect(), |
|
716 AknLayoutScalable_Apps::msg_header_pane().LayoutLine() ); |
|
717 |
|
718 iIconLayout.LayoutRect( msgHeaderPane.Rect(), |
|
719 AknLayoutScalable_Apps::msg_header_pane_g1().LayoutLine() ); |
|
720 |
|
721 CMsgExpandableControl::ResolveLayoutsL(); |
|
722 |
|
723 if ( iButton ) |
|
724 { |
|
725 iButton->SetSize( iButton->Size() ); |
|
726 } |
|
727 else |
|
728 { |
|
729 User::LeaveIfError( AknIconUtils::SetSize( iLabelIcon->Bitmap(), |
|
730 iIconLayout.Rect().Size() ) ); |
|
731 } |
|
732 if ( iEditor->MsgEditorCustomDraw() ) |
|
733 { |
|
734 iEditor->MsgEditorCustomDraw()->ResolveLayouts(); |
|
735 } |
|
736 } |
|
737 |
|
738 // --------------------------------------------------------- |
|
739 // CMsgAttachmentControl::CreateAttachmentIconsL |
|
740 // --------------------------------------------------------- |
|
741 // |
|
742 CGulIcon* CMsgAttachmentControl::CreateAttachmentIconsL() |
|
743 { |
|
744 TParse fileParse; |
|
745 fileParse.Set( KIconMbmFile, &KDC_APP_BITMAP_DIR, NULL ); |
|
746 |
|
747 CFbsBitmap* bitmap = NULL; |
|
748 CFbsBitmap* mask = NULL; |
|
749 |
|
750 AknsUtils::CreateColorIconLC( AknsUtils::SkinInstance(), |
|
751 KAknsIIDQgnIndiMceAttach, |
|
752 KAknsIIDQsnIconColors, |
|
753 EAknsCIQsnIconColorsCG13, |
|
754 bitmap, |
|
755 mask, |
|
756 fileParse.FullName(), |
|
757 EMbmMsgeditorQgn_indi_mce_attach, |
|
758 EMbmMsgeditorQgn_indi_mce_attach_mask, |
|
759 AKN_LAF_COLOR( KDefaultAttachmentColor ) ); |
|
760 |
|
761 CGulIcon* result = CGulIcon::NewL( bitmap, mask ); // Ownership transferred |
|
762 CleanupStack::Pop( 2 ); // bitmap, mask |
|
763 |
|
764 return result; |
|
765 } |
|
766 |
|
767 // --------------------------------------------------------- |
|
768 // CMsgAttachmentControl::CreateButtonL |
|
769 // --------------------------------------------------------- |
|
770 // |
|
771 #ifdef RD_SCALABLE_UI_V2 |
|
772 void CMsgAttachmentControl::CreateButtonL() |
|
773 { |
|
774 delete iButton; |
|
775 iButton = NULL; |
|
776 |
|
777 CGulIcon* buttonIcon = CGulIcon::NewL( iLabelIcon->Bitmap(), iLabelIcon->Mask() ); |
|
778 buttonIcon->SetBitmapsOwnedExternally( ETrue ); // bitmaps owned by iLabelIcon |
|
779 |
|
780 CleanupStack::PushL( buttonIcon ); |
|
781 |
|
782 iButton = CAknButton::NewL( buttonIcon, |
|
783 NULL, |
|
784 NULL, |
|
785 NULL, |
|
786 KNullDesC, |
|
787 KNullDesC, |
|
788 KAknButtonSizeFitText, |
|
789 0 ); |
|
790 |
|
791 CleanupStack::Pop( buttonIcon ); // buttonIcon owned by iButton |
|
792 |
|
793 iButton->SetIconScaleMode( EAspectRatioPreserved ); |
|
794 |
|
795 iButton->SetObserver( this ); |
|
796 |
|
797 if ( DrawableWindow() ) |
|
798 { |
|
799 iButton->SetContainerWindowL( Window() ); |
|
800 iButton->ActivateL(); |
|
801 } |
|
802 } |
|
803 #else |
|
804 void CMsgAttachmentControl::CreateButtonL() |
|
805 { |
|
806 } |
|
807 #endif // RD_SCALABLE_UI_V2 |
|
808 |
|
809 |
|
810 // --------------------------------------------------------- |
|
811 // CMsgAttachmentControl::DoScrollTextL |
|
812 // --------------------------------------------------------- |
|
813 // |
|
814 TInt CMsgAttachmentControl::DoScrollTextL( TAny* aObject ) |
|
815 { |
|
816 // cast, and call non-static function |
|
817 CMsgAttachmentControl* control = static_cast<CMsgAttachmentControl*>( aObject ); |
|
818 TRAPD( error ,control->ScrollTextL() ); |
|
819 if ( error != KErrNone ) |
|
820 { |
|
821 control->StopAutomaticScrolling(); |
|
822 User::Leave( error ); |
|
823 } |
|
824 return KErrNone; |
|
825 } |
|
826 |
|
827 // --------------------------------------------------------- |
|
828 // CMsgAttachmentControl::ScrollTextL |
|
829 // --------------------------------------------------------- |
|
830 // |
|
831 void CMsgAttachmentControl::ScrollTextL() |
|
832 { |
|
833 TBool scrollText( ETrue ); |
|
834 if ( iScrollPos == EScrollPosBeginning ) |
|
835 { |
|
836 SetTextForEditorL( EFalse, EFalse ); |
|
837 } |
|
838 else if ( iScrollPos == EScrollPosEnd ) |
|
839 { |
|
840 // Indicates that text has been scrolled to the end and should be restarted. |
|
841 SetTextForEditorL( EFalse, ETrue ); |
|
842 iScrollPos = EScrollPosBeginning; |
|
843 scrollText = EFalse; |
|
844 |
|
845 // Reset the text view to it's original position. |
|
846 iEditor->TextView()->SetLeftTextMargin( 0 ); |
|
847 DrawNow(); |
|
848 |
|
849 StartAutomaticScrolling( KScrollRestartDelay ); |
|
850 } |
|
851 |
|
852 if ( scrollText ) |
|
853 { |
|
854 TInt scrolledPixels = iEditor->TextView()->ScrollDisplayL( TCursorPosition::EFRight ); |
|
855 if ( scrolledPixels == 0 ) |
|
856 { |
|
857 // Indicates that text has been scrolled to the end. |
|
858 iScrollPos = EScrollPosEnd; |
|
859 StartAutomaticScrolling( KScrollEndDelay ); |
|
860 } |
|
861 else |
|
862 { |
|
863 iScrollPos = EScrollPosOther; |
|
864 } |
|
865 } |
|
866 } |
|
867 |
|
868 // --------------------------------------------------------- |
|
869 // CMsgAttachmentControl::DisableAutomaticScrolling |
|
870 // --------------------------------------------------------- |
|
871 // |
|
872 void CMsgAttachmentControl::DisableAutomaticScrolling() |
|
873 { |
|
874 iAutomaticScrolling = EFalse; |
|
875 StopAutomaticScrolling(); |
|
876 } |
|
877 |
|
878 // --------------------------------------------------------- |
|
879 // CMsgAttachmentControl::EnableAutomaticScrolling |
|
880 // --------------------------------------------------------- |
|
881 // |
|
882 void CMsgAttachmentControl::EnableAutomaticScrolling() |
|
883 { |
|
884 iAutomaticScrolling = ETrue; |
|
885 |
|
886 if ( !iScrollTimer->IsActive() && |
|
887 IsFocused() ) |
|
888 { |
|
889 StartAutomaticScrolling( KScrollStartDelay ); |
|
890 } |
|
891 } |
|
892 |
|
893 |
|
894 // --------------------------------------------------------- |
|
895 // CMsgAttachmentControl::StartAutomaticScrolling |
|
896 // --------------------------------------------------------- |
|
897 // |
|
898 void CMsgAttachmentControl::StartAutomaticScrolling( TInt aStartDelay ) |
|
899 { |
|
900 StopAutomaticScrolling(); |
|
901 iScrollTimer->Start( aStartDelay, |
|
902 KScrollTickDelay, |
|
903 TCallBack( DoScrollTextL, this ) ); |
|
904 } |
|
905 |
|
906 // --------------------------------------------------------- |
|
907 // CMsgAttachmentControl::StopAutomaticScrolling |
|
908 // --------------------------------------------------------- |
|
909 // |
|
910 void CMsgAttachmentControl::StopAutomaticScrolling() |
|
911 { |
|
912 iScrollTimer->Cancel(); |
|
913 } |
|
914 |
|
915 // --------------------------------------------------------- |
|
916 // CMsgAttachmentControl::ClipTextL |
|
917 // --------------------------------------------------------- |
|
918 // |
|
919 void CMsgAttachmentControl::ClipTextL( TPtr aText, TInt aClipWidth ) |
|
920 { |
|
921 const CFont* font = iEditorLayout.Font(); |
|
922 |
|
923 TInt fits = font->TextCount( aText, aClipWidth ); |
|
924 |
|
925 if ( fits < aText.Length() ) |
|
926 { |
|
927 // Clipping is actually done only if text is at the beginning. |
|
928 TInt ellipsisWidth = font->CharWidthInPixels( KEllipsis ); |
|
929 |
|
930 fits = font->TextCount( aText, aClipWidth - ellipsisWidth ); |
|
931 |
|
932 // Work out the text directionality before the truncation point. |
|
933 // First put the text in reverse order and then call |
|
934 // TBidiText::TextDirectionality. This effectively tells the |
|
935 // directionality of the last strongly directional character |
|
936 // in the text. |
|
937 HBufC* temp = aText.Left( fits ).AllocL(); |
|
938 TPtr tempPtr = temp->Des(); |
|
939 |
|
940 TInt i = 0; |
|
941 TInt j = tempPtr.Length() - 1; |
|
942 while ( i < j ) |
|
943 { |
|
944 TText t = tempPtr[i]; |
|
945 tempPtr[i++] = tempPtr[j]; |
|
946 tempPtr[j--] = t; |
|
947 } |
|
948 |
|
949 TBidiText::TDirectionality dir = TBidiText::TextDirectionality( tempPtr ); |
|
950 |
|
951 delete temp; |
|
952 |
|
953 TText dirMarker = ( dir == TBidiText::ERightToLeft ) ? KRLMarker : |
|
954 KLRMarker; |
|
955 |
|
956 // Insert zero width joiner if necessary to get the correct glyph form |
|
957 // before truncation. |
|
958 TText lastChar = aText[fits - 1]; |
|
959 TText next = aText[fits]; |
|
960 |
|
961 TInt ellipsisPos = fits; |
|
962 |
|
963 if ( CFont::CharactersJoin( lastChar, KZeroWidthJoiner ) && |
|
964 CFont::CharactersJoin( lastChar, next ) ) |
|
965 { |
|
966 aText[fits] = KZeroWidthJoiner; |
|
967 ellipsisPos++; |
|
968 } |
|
969 |
|
970 aText.SetMax(); |
|
971 |
|
972 aText[ellipsisPos] = KEllipsis; |
|
973 |
|
974 // Inserting direction marker after the ellipsis ensures that |
|
975 // the ellipsis is shown on the correct side of the text |
|
976 // before it. |
|
977 aText[ellipsisPos + 1] = dirMarker; |
|
978 |
|
979 aText.SetLength( ellipsisPos + 2 ); |
|
980 } |
|
981 } |
|
982 |
|
983 // --------------------------------------------------------- |
|
984 // CMsgAttachmentControl::UpdateFocusL |
|
985 // --------------------------------------------------------- |
|
986 // |
|
987 void CMsgAttachmentControl::UpdateFocusL() |
|
988 { |
|
989 TCharFormat charFormat; |
|
990 TCharFormatMask applyMask; |
|
991 |
|
992 iEditor->RichText()->GetCharFormat( charFormat, |
|
993 applyMask, |
|
994 0, |
|
995 iEditor->TextLength() ); |
|
996 |
|
997 if ( !IsFocused() ) |
|
998 { |
|
999 TRgb textColor( KRgbBlack ); |
|
1000 AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), |
|
1001 textColor, |
|
1002 KAknsIIDQsnTextColors, |
|
1003 EAknsCIQsnTextColorsCG6 ); |
|
1004 |
|
1005 charFormat.iFontPresentation.iTextColor = textColor; |
|
1006 applyMask.SetAttrib( EAttColor ); |
|
1007 |
|
1008 charFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightNone; |
|
1009 applyMask.SetAttrib( EAttFontHighlightStyle ); |
|
1010 } |
|
1011 else |
|
1012 { |
|
1013 TRgb textColor( KRgbWhite ); |
|
1014 AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), |
|
1015 textColor, |
|
1016 KAknsIIDQsnHighlightColors, |
|
1017 EAknsCIQsnTextColorsCG3 ); |
|
1018 |
|
1019 charFormat.iFontPresentation.iTextColor = textColor; |
|
1020 applyMask.SetAttrib( EAttColor ); |
|
1021 |
|
1022 TRgb highlightColor( KRgbBlue ); |
|
1023 AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), |
|
1024 highlightColor, |
|
1025 KAknsIIDQsnHighlightColors, |
|
1026 EAknsCIQsnHighlightColorsCG1 ); |
|
1027 |
|
1028 charFormat.iFontPresentation.iHighlightColor = highlightColor; |
|
1029 applyMask.SetAttrib( EAttFontHighlightColor ); |
|
1030 |
|
1031 charFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightNormal; |
|
1032 applyMask.SetAttrib( EAttFontHighlightStyle ); |
|
1033 } |
|
1034 |
|
1035 iEditor->RichText()->ApplyCharFormatL( charFormat, |
|
1036 applyMask, |
|
1037 0, |
|
1038 iEditor->TextLength() ); |
|
1039 } |
|
1040 |
|
1041 // --------------------------------------------------------- |
|
1042 // CMsgAttachmentControl::DoHandleResourceChangeBeforeL |
|
1043 // |
|
1044 // Contains functionality that base class handle resource change |
|
1045 // is depending on to be completed before it can be executed properly. |
|
1046 // --------------------------------------------------------- |
|
1047 // |
|
1048 void CMsgAttachmentControl::DoHandleResourceChangeBeforeL( TInt aType ) |
|
1049 { |
|
1050 switch( aType ) |
|
1051 { |
|
1052 case KEikDynamicLayoutVariantSwitch: |
|
1053 { |
|
1054 #ifdef RD_SCALABLE_UI_V2 |
|
1055 if ( AknLayoutUtils::PenEnabled() ) |
|
1056 { |
|
1057 if ( !iButton ) |
|
1058 { |
|
1059 CreateButtonL(); |
|
1060 } |
|
1061 } |
|
1062 else |
|
1063 { |
|
1064 delete iButton; |
|
1065 iButton = NULL; |
|
1066 } |
|
1067 #endif // RD_SCALABLE_UI_V2 |
|
1068 break; |
|
1069 } |
|
1070 default: |
|
1071 { |
|
1072 break; |
|
1073 } |
|
1074 } |
|
1075 } |
|
1076 |
|
1077 // --------------------------------------------------------- |
|
1078 // CMsgAttachmentControl::DoHandleResourceChangeAfterL |
|
1079 // |
|
1080 // Contains functionality that is dependant of base class handle |
|
1081 // resource change to complete before these can be executed properly. |
|
1082 // --------------------------------------------------------- |
|
1083 // |
|
1084 void CMsgAttachmentControl::DoHandleResourceChangeAfterL( TInt aType ) |
|
1085 { |
|
1086 switch( aType ) |
|
1087 { |
|
1088 case KEikDynamicLayoutVariantSwitch: |
|
1089 { |
|
1090 StopAutomaticScrolling(); |
|
1091 iScrollPos = EScrollPosBeginning; |
|
1092 SetTextForEditorL( EFalse, ETrue ); |
|
1093 |
|
1094 break; |
|
1095 } |
|
1096 case KAknsMessageSkinChange: |
|
1097 { |
|
1098 CGulIcon* icon = CreateAttachmentIconsL(); |
|
1099 CleanupStack::PushL( icon ); |
|
1100 |
|
1101 if ( iButton ) |
|
1102 { |
|
1103 CGulIcon* buttonIcon = CGulIcon::NewL( icon->Bitmap(), icon->Mask() ); |
|
1104 buttonIcon->SetBitmapsOwnedExternally( ETrue ); // bitmaps owned by iLabelIcon |
|
1105 |
|
1106 iButton->State()->SetIcon( buttonIcon ); // buttonIcon ownership transferred |
|
1107 } |
|
1108 |
|
1109 // Make the change here as button will take the old size from |
|
1110 // old icons that must be still valid when setting to button icon. |
|
1111 delete iLabelIcon; |
|
1112 iLabelIcon = icon; |
|
1113 |
|
1114 CleanupStack::Pop( icon ); |
|
1115 |
|
1116 ResolveLayoutsL(); |
|
1117 break; |
|
1118 } |
|
1119 default: |
|
1120 { |
|
1121 break; |
|
1122 } |
|
1123 } |
|
1124 } |
|
1125 |
|
1126 // --------------------------------------------------------- |
|
1127 // CMsgAttachmentControl::AddToAttachmentArrayL |
|
1128 // --------------------------------------------------------- |
|
1129 // |
|
1130 void CMsgAttachmentControl::AddToAttachmentArrayL( const TDesC& aName, TInt aIndex ) |
|
1131 { |
|
1132 HBufC* convertedFileName = |
|
1133 AknTextUtils::ConvertFileNameL( aName ); |
|
1134 CleanupStack::PushL( convertedFileName ); |
|
1135 |
|
1136 TPtr convertedFileNamePtr = convertedFileName->Des(); |
|
1137 |
|
1138 AknTextUtils::StripCharacters( convertedFileNamePtr, KStripList ); |
|
1139 |
|
1140 iAttachmentArray->InsertL( aIndex, *convertedFileName ); |
|
1141 |
|
1142 CleanupStack::PopAndDestroy( convertedFileName ); |
|
1143 } |
|
1144 |
|
1145 // --------------------------------------------------------- |
|
1146 // CMsgAttachmentControl::LayoutButton |
|
1147 // --------------------------------------------------------- |
|
1148 // |
|
1149 void CMsgAttachmentControl::LayoutButton() |
|
1150 { |
|
1151 #ifdef RD_SCALABLE_UI_V2 |
|
1152 CMsgExpandableControl::LayoutButton(); |
|
1153 |
|
1154 if ( iButton ) |
|
1155 { |
|
1156 TMargins8 margins; |
|
1157 TRect buttonRect = iButtonLayout.Rect(); |
|
1158 TRect iconRect = iIconLayout.Rect(); |
|
1159 margins.iTop = iconRect.iTl.iY - buttonRect.iTl.iY; |
|
1160 margins.iBottom = buttonRect.iBr.iY - iconRect.iBr.iY; |
|
1161 margins.iLeft = iconRect.iTl.iX - buttonRect.iTl.iX; |
|
1162 margins.iRight = buttonRect.iBr.iX - iconRect.iBr.iX; |
|
1163 |
|
1164 iButton->SetMargins( margins ); |
|
1165 } |
|
1166 #endif // RD_SCALABLE_UI_V2 |
|
1167 } |
|
1168 |
|
1169 |
|
1170 // End of File |