|
1 /* |
|
2 * Copyright (c) 2010 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: Easy dialing test application. |
|
15 * |
|
16 */ |
|
17 |
|
18 // INCLUDE FILES |
|
19 #include "edta_screentextbuffer.h" |
|
20 #include "edta_debugprint.h" |
|
21 #include "edta.pan" |
|
22 |
|
23 #include <coemain.h> |
|
24 #include <aknsbasicbackgroundcontrolcontext.h> |
|
25 #include <eiksbfrm.h> |
|
26 #include <eikenv.h> |
|
27 #include <eikdef.h> |
|
28 #include <aknappui.h> |
|
29 #include <aknutils.h> |
|
30 |
|
31 |
|
32 const TInt KLineWidthCent = 90; // Percent of total screen width |
|
33 const TInt KHeightMarginCent = 7; // Percent of total height |
|
34 const TInt KBottomMarginCent = 3; // Percent of total height |
|
35 const TInt KLineHeightCent = 135; // How many percent is the line height of font height |
|
36 const TInt KCent = 100; |
|
37 const TInt KInitialScreenBufferSize = 20; // This many lines is initially allocated to the screen buffer. |
|
38 const TInt KInitialScreenStartAmount = 5; // This many screen starts are initially allocated to screen buffer. |
|
39 |
|
40 |
|
41 CEdtaScreenTextBuffer* CEdtaScreenTextBuffer::NewL( const TRect& aRect ) |
|
42 { |
|
43 CEdtaScreenTextBuffer* self = CEdtaScreenTextBuffer::NewLC( aRect ); |
|
44 CleanupStack::Pop( self ); |
|
45 return self; |
|
46 } |
|
47 |
|
48 CEdtaScreenTextBuffer* CEdtaScreenTextBuffer::NewLC( const TRect& aRect ) |
|
49 { |
|
50 CEdtaScreenTextBuffer* self = new ( ELeave ) CEdtaScreenTextBuffer; |
|
51 CleanupStack::PushL( self ); |
|
52 self->ConstructL( aRect ); |
|
53 return self; |
|
54 } |
|
55 |
|
56 // constructors |
|
57 CEdtaScreenTextBuffer::CEdtaScreenTextBuffer() |
|
58 { |
|
59 } |
|
60 |
|
61 void CEdtaScreenTextBuffer::ConstructL( const TRect& aRect ) |
|
62 { |
|
63 CreateWindowL(); |
|
64 CalculateL(aRect); |
|
65 ActivateL(); |
|
66 } |
|
67 |
|
68 // destructor |
|
69 CEdtaScreenTextBuffer::~CEdtaScreenTextBuffer() |
|
70 { |
|
71 delete iSBFrame; |
|
72 delete iScreenStarts; |
|
73 |
|
74 if ( iText ) |
|
75 { |
|
76 iText->ResetAndDestroy(); |
|
77 delete iText; |
|
78 } |
|
79 } |
|
80 |
|
81 void CEdtaScreenTextBuffer::SizeChanged() |
|
82 { |
|
83 // TRAP_IGNORE( CalculateL( Rect() ) ); |
|
84 // DrawDeferred(); |
|
85 } |
|
86 |
|
87 |
|
88 // ----------------------------------------------------------------------------- |
|
89 // CEdtaScreenTextBuffer::Draw() |
|
90 // ----------------------------------------------------------------------------- |
|
91 void CEdtaScreenTextBuffer::Draw( const TRect& aRect ) const |
|
92 { |
|
93 // DebugPrintF(_L("CEdtaScreenTextBuffer::Draw, rect: %d, %d - %d, %d"), aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY ); |
|
94 |
|
95 __ASSERT_DEBUG( iText, Panic(EEdtaFieldNotInitialized,_L("CEdtaScreenTextBuffer::Draw: iText == NULL") )); |
|
96 __ASSERT_DEBUG( iScreenStarts, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::Draw: iScreenStarts == NULL") )); |
|
97 __ASSERT_DEBUG( iScreenStarts->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::Draw: iScreenStarts has zero elements") )); |
|
98 |
|
99 CWindowGc& gc = SystemGc(); |
|
100 |
|
101 gc.SetBrushColor( KRgbWhite ); |
|
102 gc.SetBrushStyle( CGraphicsContext::ESolidBrush ); |
|
103 gc.Clear( aRect ); |
|
104 |
|
105 if ( IsFocused() ) |
|
106 { |
|
107 TRect frame( aRect ); |
|
108 frame.Shrink(3,3); |
|
109 frame.iBr.iX -= 10; |
|
110 gc.SetPenColor(KRgbBlack); |
|
111 gc.SetPenSize( TSize(2,2) ); |
|
112 TSize cornerRounding(8,8); |
|
113 gc.DrawRoundRect( frame, cornerRounding ); |
|
114 } |
|
115 |
|
116 gc.UseFont( iFont ); |
|
117 |
|
118 // index of the first line on the screen in the text array |
|
119 TInt firstLine = 0 ; |
|
120 if((iScreenStarts ) && (iScreenStarts->Count() > iCurrentScreen)) |
|
121 { |
|
122 firstLine = ( (*iScreenStarts)[ iCurrentScreen ] ); |
|
123 } |
|
124 else |
|
125 { |
|
126 firstLine = (*iScreenStarts)[ iScreenStarts->Count() - 1 ]; |
|
127 } |
|
128 |
|
129 // index of the last line on the screen in the text array |
|
130 TInt lastLine( firstLine + iLinesPerScreen - 1 ); |
|
131 |
|
132 gc.SetBrushStyle( CGraphicsContext::ENullBrush ); |
|
133 |
|
134 TPoint position( iTopBaseLineX, iTopBaseLineY ); |
|
135 TPoint topLeft; |
|
136 TSize rectSize( iLineWidth, iBaseLineDelta +iFont->DescentInPixels() ); |
|
137 |
|
138 for ( TInt index = firstLine; index < iText->Count() && index <= lastLine; index++, position.iY += iBaseLineDelta ) |
|
139 { |
|
140 HBufC* text = (*iText)[ index ]; |
|
141 |
|
142 if ( text ) |
|
143 { |
|
144 topLeft = TPoint( position.iX, position.iY-iBaseLineDelta ); |
|
145 gc.SetPenColor(KRgbBlack); |
|
146 gc.DrawText( *text, TRect( topLeft, rectSize ), iBaseLineDelta, iTextAlign ); |
|
147 } |
|
148 } |
|
149 |
|
150 gc.DiscardFont(); |
|
151 |
|
152 // DebugPrintF(_L("CEdtaScreenTextBuffer::Draw exit")); |
|
153 } |
|
154 |
|
155 |
|
156 // ----------------------------------------------------------------------------- |
|
157 // CEdtaScreenTextBuffer::ActivateL() |
|
158 // ----------------------------------------------------------------------------- |
|
159 void CEdtaScreenTextBuffer::ActivateL() |
|
160 { |
|
161 CCoeControl::ActivateL(); |
|
162 UpdateScrollIndicatorL(); |
|
163 } |
|
164 |
|
165 |
|
166 // ----------------------------------------------------------------------------- |
|
167 // CEdtaScreenTextBuffer::SetTextL() |
|
168 // ----------------------------------------------------------------------------- |
|
169 void CEdtaScreenTextBuffer::WriteLineL(TRefByValue<const TDesC> aText,... ) |
|
170 { |
|
171 TBuf<KEdtaMaxLineWidth> bufLine; |
|
172 VA_LIST list; |
|
173 VA_START(list,aText); |
|
174 bufLine.FormatList(aText,list); |
|
175 |
|
176 if(!bufLine.Length()) |
|
177 { |
|
178 iText->AppendL( NULL ); |
|
179 } |
|
180 else |
|
181 { |
|
182 HBufC* line = HBufC::NewLC(bufLine.Length()); |
|
183 *line = bufLine; |
|
184 iText->AppendL( line ); |
|
185 CleanupStack::Pop(line); |
|
186 } |
|
187 |
|
188 // Updating scrollbars and screen starts etc are moved to UpdateScrollIndicatorL() |
|
189 |
|
190 // if text, last line is shown again in next screen |
|
191 iDoNotShowLastLineAgain = EFalse; |
|
192 |
|
193 DrawDeferred(); //New |
|
194 UpdateScrollIndicatorL(); |
|
195 } |
|
196 |
|
197 |
|
198 // ----------------------------------------------------------------------------- |
|
199 // CEdtaScreenTextBuffer::DeleteLastLine() |
|
200 // ----------------------------------------------------------------------------- |
|
201 void CEdtaScreenTextBuffer::DeleteLastLine(TInt aCount) |
|
202 { |
|
203 __ASSERT_DEBUG( iText, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::DeleteLastLine: iText == NULL") )); |
|
204 __ASSERT_DEBUG( iText->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::DeleteLastLine: iText has zero elements") )); |
|
205 |
|
206 while (aCount > 0) |
|
207 { |
|
208 // Avoiding memory leaks |
|
209 TInt lastIndex = iText->Count() - 1; |
|
210 |
|
211 // The first item in iText cannot be deleted, since UpdateScrollIndicatorL |
|
212 // relies on there being at least one item. |
|
213 if (lastIndex > 0) |
|
214 { |
|
215 HBufC* text = (*iText)[ lastIndex ]; |
|
216 delete text; |
|
217 iText->Delete(lastIndex); |
|
218 } |
|
219 --aCount; |
|
220 } |
|
221 } |
|
222 |
|
223 |
|
224 |
|
225 // ----------------------------------------------------------------------------- |
|
226 // CEdtaScreenTextBuffer::OfferKeyEventL() |
|
227 // ----------------------------------------------------------------------------- |
|
228 TKeyResponse CEdtaScreenTextBuffer::OfferKeyEventL( const TKeyEvent& aKeyEvent, |
|
229 TEventCode aType ) |
|
230 { |
|
231 __ASSERT_DEBUG(iScreenStarts, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::OfferKeyEventL: iScreenStarts == NULL") )); |
|
232 __ASSERT_DEBUG(iScreenStarts->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::OfferKeyEventL: iScreenStarts has zero elements") )); |
|
233 |
|
234 if ( aType == EEventKey && iScreenStarts->Count() > 1 ) |
|
235 { |
|
236 switch ( aKeyEvent.iCode ) |
|
237 { |
|
238 case EKeyUpArrow: |
|
239 if ( iCurrentScreen > 0 ) |
|
240 { |
|
241 iCurrentScreen--; |
|
242 DrawNow(); |
|
243 UpdateScrollIndicatorL(); |
|
244 } |
|
245 break; |
|
246 |
|
247 case EKeyDownArrow: |
|
248 if ( iCurrentScreen < iScreenStarts->Count() - 1 ) |
|
249 { |
|
250 iCurrentScreen++; |
|
251 DrawNow(); |
|
252 UpdateScrollIndicatorL(); |
|
253 } |
|
254 break; |
|
255 |
|
256 default: |
|
257 return EKeyWasNotConsumed; |
|
258 } |
|
259 } |
|
260 |
|
261 return EKeyWasConsumed; |
|
262 } |
|
263 |
|
264 |
|
265 |
|
266 // ----------------------------------------------------------------------------- |
|
267 // CEdtaScreenTextBuffer::FocusChanged() |
|
268 // ----------------------------------------------------------------------------- |
|
269 void CEdtaScreenTextBuffer::FocusChanged(TDrawNow aDrawNow) |
|
270 { |
|
271 if ( aDrawNow == EDrawNow ) |
|
272 { |
|
273 DrawNow(); |
|
274 } |
|
275 } |
|
276 |
|
277 |
|
278 // ----------------------------------------------------------------------------- |
|
279 // CEdtaScreenTextBuffer::HandleScrollEventL() |
|
280 // ----------------------------------------------------------------------------- |
|
281 void CEdtaScreenTextBuffer::HandleScrollEventL ( CEikScrollBar* aScrollBar, TEikScrollEvent aEventType) |
|
282 { |
|
283 //Only on page up/down,scroll up/down and drag events |
|
284 switch (aEventType) |
|
285 { |
|
286 case EEikScrollPageDown: |
|
287 case EEikScrollPageUp: |
|
288 case EEikScrollThumbDragVert: |
|
289 case EEikScrollUp: |
|
290 case EEikScrollDown: |
|
291 |
|
292 iCurrentScreen = aScrollBar->ThumbPosition(); |
|
293 |
|
294 //Refresh now |
|
295 DrawNow(); |
|
296 UpdateScrollIndicatorL(); |
|
297 break; |
|
298 } |
|
299 } |
|
300 |
|
301 // ----------------------------------------------------------------------------- |
|
302 // CEdtaScreenTextBuffer::UpdateScrollIndicatorL() |
|
303 // |
|
304 // This function assumes that |
|
305 // - iText exists and has at least one element. |
|
306 // - iScreenStarts exist and has at least one element. |
|
307 // These conditions are met if CalculateL / ConstructL has been called. |
|
308 // ----------------------------------------------------------------------------- |
|
309 void CEdtaScreenTextBuffer::UpdateScrollIndicatorL() |
|
310 { |
|
311 __ASSERT_DEBUG( iText, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::UpdateScrollIndicatorL: iText == NULL") )); |
|
312 __ASSERT_DEBUG( iText->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::UpdateScrollIndicatorL: iText has zero elements") )); |
|
313 __ASSERT_DEBUG( iScreenStarts, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::UpdateScrollIndicatorL: iScreenStarts == NULL") )); |
|
314 __ASSERT_DEBUG( iScreenStarts->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::UpdateScrollIndicatorL: iScreenStarts has zero elements") )); |
|
315 |
|
316 TInt lastLine( iText->Count() - 1 ); |
|
317 TInt screenStart( (*iScreenStarts)[ iScreenStarts->Count() - 1 ] ); |
|
318 |
|
319 TBool firstNewScreenHandled( EFalse ); |
|
320 |
|
321 while ( lastLine >= screenStart + iLinesPerScreen ) |
|
322 { |
|
323 if ( !firstNewScreenHandled && iDoNotShowLastLineAgain ) |
|
324 { |
|
325 screenStart++; |
|
326 firstNewScreenHandled = ETrue; |
|
327 } |
|
328 |
|
329 // If the shows screen is the last on, scroll the view along with new lines. |
|
330 if (iCurrentScreen == iScreenStarts->Count() - 1) |
|
331 { |
|
332 iCurrentScreen++; |
|
333 } |
|
334 |
|
335 screenStart += iLinesPerScreen - 1; |
|
336 iScreenStarts->AppendL( screenStart ); |
|
337 } |
|
338 |
|
339 if ( !iSBFrame ) |
|
340 { |
|
341 iSBFrame = new( ELeave ) CEikScrollBarFrame( this, NULL, ETrue ); |
|
342 |
|
343 iSBFrame->CreateDoubleSpanScrollBarsL(ETrue, EFalse); // non-window owning scrollbar |
|
344 iSBFrame->SetTypeOfVScrollBar(CEikScrollBarFrame::EDoubleSpan); |
|
345 |
|
346 iSBFrame->SetScrollBarFrameObserver(this); |
|
347 iSBFrame->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff,CEikScrollBarFrame::EAuto); |
|
348 } |
|
349 |
|
350 TEikScrollBarModel vSbarModel; |
|
351 vSbarModel.iThumbPosition = iCurrentScreen; |
|
352 vSbarModel.iScrollSpan = iScreenStarts->Count(); |
|
353 vSbarModel.iThumbSpan = 1; |
|
354 |
|
355 TRect rect(Rect()); |
|
356 TEikScrollBarFrameLayout layout; |
|
357 layout.iTilingMode = TEikScrollBarFrameLayout::EInclusiveRectConstant; |
|
358 |
|
359 // For EDoubleSpan type scrollbar |
|
360 if (vSbarModel.iThumbPosition + vSbarModel.iThumbSpan > vSbarModel.iScrollSpan) |
|
361 { |
|
362 // Not let scrollbar values overflow |
|
363 vSbarModel.iThumbPosition = vSbarModel.iScrollSpan - vSbarModel.iThumbSpan; |
|
364 } |
|
365 |
|
366 TAknDoubleSpanScrollBarModel vDsSbarModel(vSbarModel); |
|
367 iSBFrame->TileL(NULL, &vDsSbarModel, rect, rect, layout); |
|
368 iSBFrame->SetVFocusPosToThumbPos(vDsSbarModel.FocusPosition()); |
|
369 } |
|
370 |
|
371 |
|
372 // ----------------------------------------------------------------------------- |
|
373 // CEdtaScreenTextBuffer::CalculateL() |
|
374 // Needs to be called in construction, and whenever layout changes. |
|
375 // Screen orientation change, etc. |
|
376 // ----------------------------------------------------------------------------- |
|
377 void CEdtaScreenTextBuffer::CalculateL(const TRect& aRect) |
|
378 { |
|
379 // DebugPrintF(_L("CEdtaScreenTextBuffer::CalculateL, rect: %d, %d - %d, %d"), aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY ); |
|
380 |
|
381 TRect rect(0,0,0,0); |
|
382 |
|
383 iCurrentScreen = 0; |
|
384 |
|
385 iFont = AknLayoutUtils::FontFromId(EAknLogicalFontSecondaryFont); |
|
386 |
|
387 // Calculate various text positioning parameters |
|
388 iBaseLineDelta = iFont->HeightInPixels() * KLineHeightCent / KCent; |
|
389 |
|
390 TInt mainPaneWidth( aRect.iBr.iX - aRect.iTl.iX ); |
|
391 TInt mainPaneHeight( aRect.iBr.iY - aRect.iTl.iY ); |
|
392 // Line width is 90% (by default) of client rect, and horizontal margins 10% |
|
393 iLineWidth = mainPaneWidth * KLineWidthCent / KCent; |
|
394 |
|
395 iTopBaseLineX = ( mainPaneWidth - iLineWidth ) / 2; |
|
396 |
|
397 // top margin is 7% (by default) of the client rect |
|
398 TInt topMargin = mainPaneHeight * KHeightMarginCent / KCent; |
|
399 iTopBaseLineY = topMargin + iFont->AscentInPixels(); |
|
400 |
|
401 // minimum bottom margin is 3% (by default) of the client rect |
|
402 TInt bottomMargin = mainPaneHeight * KBottomMarginCent / KCent; |
|
403 iLinesPerScreen = |
|
404 ( mainPaneHeight - topMargin - bottomMargin ) / iBaseLineDelta; |
|
405 |
|
406 iTextAlign = CGraphicsContext::ELeft; |
|
407 |
|
408 // Text must not be deleted, otherwise all accumulated data will be lost. |
|
409 if ( !iText ) |
|
410 { |
|
411 // Every text line on screen is one entry in this array |
|
412 iText = new( ELeave ) CArrayPtrFlat<HBufC>( KInitialScreenBufferSize ); |
|
413 iText->AppendL(NULL); // Extra newline for visual reasons |
|
414 } |
|
415 |
|
416 if ( iScreenStarts ) |
|
417 { |
|
418 delete iScreenStarts; |
|
419 iScreenStarts = NULL; |
|
420 } |
|
421 |
|
422 |
|
423 // This array contains indices for lines that start the subsequent |
|
424 // screens, for custom scrolling |
|
425 iScreenStarts = new( ELeave ) CArrayFixFlat<TInt>( KInitialScreenStartAmount ); |
|
426 // Initialisation: first screen starts at line 0. |
|
427 iScreenStarts->AppendL( 0 ); |
|
428 |
|
429 if ( iSBFrame ) |
|
430 { |
|
431 delete iSBFrame; |
|
432 iSBFrame = NULL; |
|
433 } |
|
434 |
|
435 UpdateScrollIndicatorL(); |
|
436 } |
|
437 |
|
438 |
|
439 // ----------------------------------------------------------------------------- |
|
440 // CEdtaScreenTextBuffer::HandleResourceChange() |
|
441 // ----------------------------------------------------------------------------- |
|
442 void CEdtaScreenTextBuffer::HandleResourceChange(TInt aType) |
|
443 { |
|
444 switch ( aType ) |
|
445 { |
|
446 case KEikDynamicLayoutVariantSwitch : |
|
447 { |
|
448 TRAPD( error, CalculateL( iAvkonAppUi->ClientRect() )); |
|
449 |
|
450 if( error != KErrNone ) |
|
451 { |
|
452 DebugPrintF(_L("CEdtaScreenTextBuffer::HandleResourceChange: CalculateL -method failed: %d"), error ); |
|
453 } |
|
454 else |
|
455 { |
|
456 DrawNow(); |
|
457 } |
|
458 } |
|
459 break; |
|
460 |
|
461 case KAknsMessageSkinChange : |
|
462 { |
|
463 __ASSERT_DEBUG(iSBFrame, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::HandleResourceChange: iSBFrame == NULL") )); |
|
464 |
|
465 TRAPD( error, |
|
466 { |
|
467 iSBFrame->CreateDoubleSpanScrollBarsL(ETrue, EFalse); // window owning scrollbar |
|
468 iSBFrame->SetTypeOfVScrollBar(CEikScrollBarFrame::EDoubleSpan); |
|
469 iSBFrame->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff,CEikScrollBarFrame::EOn); |
|
470 UpdateScrollIndicatorL(); |
|
471 } |
|
472 ); |
|
473 |
|
474 if( error != KErrNone ) |
|
475 { |
|
476 DebugPrintF(_L("CEdtaScreenTextBuffer::HandleResourceChange: Create ScrollBars failed: %d"), error ); |
|
477 __ASSERT_DEBUG( error == KErrNone, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::HandleResourceChange => Skin change caused panic") )); |
|
478 } |
|
479 } |
|
480 |
|
481 default: |
|
482 { |
|
483 CCoeControl::HandleResourceChange(aType); |
|
484 } |
|
485 break; |
|
486 } |
|
487 } |
|
488 |
|
489 |
|
490 // --------------------------------------------------------- |
|
491 // CEdtaScreenTextBuffer::MopSupplyObject() |
|
492 // Pass skin information if need. |
|
493 // --------------------------------------------------------- |
|
494 TTypeUid::Ptr CEdtaScreenTextBuffer::MopSupplyObject(TTypeUid aId) |
|
495 { |
|
496 return CCoeControl::MopSupplyObject(aId); |
|
497 } |
|
498 |
|
499 |
|
500 // End of file |