uifw/EikStd/coctlsrc/EIKLBED.CPP
changeset 0 2f259fa3e83a
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 1997-1999 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:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <gdi.h>
       
    20 #include <badesca.h>        // CDesArray
       
    21 #include <eiklbed.h>		// class CEikListBoxTextEditor header file
       
    22 #include <uikon.hrh>
       
    23 #include <gulutil.h>
       
    24 #include <eikedwin.h>
       
    25 #include <eikenv.h>
       
    26 #include <eikappui.h>
       
    27 #include <txtglobl.h>		// CGlobalText
       
    28 #include <txtfmlyr.h>		// CParaFormatLayer, CCharFormatLayer
       
    29 #include <eikcoctl.rsg>
       
    30 #include <AknTasHook.h>
       
    31 #include "LAFLBED.H" 
       
    32 #include "akntrace.h"
       
    33 enum TTUiklbedPanic
       
    34     {
       
    35     ETUiklbedPanicEndMarkMissing,
       
    36     ETUiklbedPanicEmptyField,
       
    37     ETUiklbedPanicLongInput,
       
    38     };
       
    39 
       
    40 LOCAL_C void Panic(TTUiklbedPanic aPanic)
       
    41     {
       
    42 	_LIT(KTUiklbed,"TUiklbed");
       
    43     User::Panic(KTUiklbed, aPanic);
       
    44     }
       
    45 
       
    46 //
       
    47 // MEikListBoxEditor
       
    48 //
       
    49 
       
    50 EXPORT_C void MEikListBoxEditor::MEikListBoxEditor_Reserved_1()
       
    51 	{
       
    52 	}
       
    53 
       
    54 //
       
    55 // CEikListBoxTextEditor
       
    56 //
       
    57 
       
    58 EXPORT_C CEikListBoxTextEditor::CEikListBoxTextEditor( MListBoxModel* aModel )
       
    59 	: iModel(aModel), iEditor(NULL), iFont(NULL), iItemPos(0), iItemLen(0)
       
    60 	{
       
    61 	_AKNTRACE_FUNC_ENTER;
       
    62 	iFont = CONST_CAST(CFont*,CCoeEnv::Static()->NormalFont());
       
    63 	AKNTASHOOK_ADD( this, "CEikListBoxTextEditor" );
       
    64 	_AKNTRACE_FUNC_EXIT;
       
    65 	}
       
    66 
       
    67 EXPORT_C CEikListBoxTextEditor::~CEikListBoxTextEditor()
       
    68 	{ // need to remove from stack incase listbox was destroyed without calling StopEditingL()
       
    69 	  // safe to call RemoveFromStack even if we're not stacked
       
    70 	  // code here is same as in StopEditingL(), but we can't call
       
    71 	  // a L function from ~ even if it can't leave
       
    72 	_AKNTRACE_FUNC_ENTER;
       
    73 	AKNTASHOOK_REMOVE();
       
    74 	iEikonEnv->EikAppUi()->RemoveFromStack(this);
       
    75 	if(iEditor)
       
    76 		iEditor->SetFocus(EFalse);      // BUG? - cursor remains on screen without this
       
    77 	delete iEditor;
       
    78 	delete iParaFormatLayer;
       
    79 	delete iCharFormatLayer;
       
    80 	_AKNTRACE_FUNC_EXIT;
       
    81 	}
       
    82 
       
    83 EXPORT_C void CEikListBoxTextEditor::Release()
       
    84 	{
       
    85 	delete this;
       
    86 	}
       
    87 
       
    88 EXPORT_C void CEikListBoxTextEditor::SetFont(const CFont* aFont)
       
    89 	{
       
    90 	if (aFont!=NULL)
       
    91 		iFont = CONST_CAST(CFont*,aFont);
       
    92 	}
       
    93 
       
    94 void CEikListBoxTextEditor::UseFontL( CEikEdwin& aEditor, const CFont& aFont )
       
    95 	{
       
    96 	_AKNTRACE_FUNC_ENTER;
       
    97 	CGlobalText* globalText;
       
    98 
       
    99     TCharFormatMask defaultCharFormatMask;
       
   100 	defaultCharFormatMask.SetAttrib(EAttFontTypeface);
       
   101 	defaultCharFormatMask.SetAttrib(EAttFontHeight);
       
   102 	TFontSpec fontspec = aFont.FontSpecInTwips();
       
   103     TCharFormat defaultCharFormat( fontspec.iTypeface.iName, fontspec.iHeight );
       
   104 
       
   105 	iParaFormatLayer=CParaFormatLayer::NewL();
       
   106 	iCharFormatLayer=CCharFormatLayer::NewL(defaultCharFormat,defaultCharFormatMask);
       
   107 	globalText=CGlobalText::NewL(iParaFormatLayer,iCharFormatLayer,CEditableText::ESegmentedStorage,5);
       
   108 	CleanupStack::PushL(globalText);
       
   109 
       
   110 	TCharFormat charFormat;
       
   111 	TCharFormatMask charMask;
       
   112 	iCharFormatLayer->Sense(charFormat,charMask);
       
   113 	if ( fontspec.iFontStyle.Posture()==EPostureItalic )
       
   114 		{
       
   115 		charMask.SetAttrib(EAttFontPosture);
       
   116 		charFormat.iFontSpec.iFontStyle.SetPosture(EPostureItalic);
       
   117 		}
       
   118 	if ( fontspec.iFontStyle.StrokeWeight()==EStrokeWeightBold )
       
   119 		{
       
   120 		charMask.SetAttrib(EAttFontStrokeWeight );
       
   121 		charFormat.iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
       
   122 		}
       
   123 	iCharFormatLayer->SetL(charFormat,charMask);
       
   124 
       
   125 	CPlainText* old=aEditor.Text();
       
   126 	CleanupStack::Pop(); // globalText
       
   127 	CleanupStack::PushL(old);	// old is pushed because we're using EUseText in the subsequent call
       
   128 	aEditor.SetDocumentContentL(*globalText,CEikEdwin::EUseText);
       
   129 	CleanupStack::PopAndDestroy();	// old
       
   130 	_AKNTRACE_FUNC_EXIT;
       
   131 	}
       
   132 
       
   133 EXPORT_C CEikEdwin* CEikListBoxTextEditor::Editor()
       
   134 	{
       
   135 	return iEditor;
       
   136 	}
       
   137 
       
   138 EXPORT_C MListBoxModel* CEikListBoxTextEditor::ListBoxModel()
       
   139 	{
       
   140 	return iModel;
       
   141 	}
       
   142 
       
   143 EXPORT_C void CEikListBoxTextEditor::StartEditingL(const CCoeControl& aContainer, const TRect& aRect, TInt aItemIndex, TInt aMaxLength )
       
   144 	{
       
   145 	_AKNTRACE_FUNC_ENTER;
       
   146 	if (Editor())
       
   147 	    {
       
   148 	    _AKNTRACE_FUNC_EXIT;
       
   149 	    return;     // quit if editing is currently on
       
   150 	    }		
       
   151 
       
   152 	iItemIndex=aItemIndex;
       
   153 	TRect rect=aRect;
       
   154     TPtrC itemtext=EditableItemText(&rect);	// get text (also partly editable)
       
   155 
       
   156 	// create edwin (make it into own window, no wrapping)
       
   157 	TGulBorder border;
       
   158 	LafListBoxTextEditor::GetDefaultBorder(border);
       
   159 	CEikEdwin* editor=new(ELeave) CEikEdwin(border);
       
   160 	CleanupStack::PushL(editor);
       
   161 	TInt edwinFlags=EEikEdwinOwnsWindow | EEikEdwinNoWrap | EEikEdwinNoLineOrParaBreaks | EEikEdwinNoCustomDraw;
       
   162 	editor->CEikEdwin::ConstructL(edwinFlags,0,(iItemLen?iItemLen:aMaxLength),1);
       
   163 	editor->SetContainerWindowL(aContainer);
       
   164 	editor->SetRect(rect);
       
   165 	UseFontL(*editor,*iFont); // need this to change CEikEdwin font...
       
   166 	editor->SetTextL(&itemtext);
       
   167 	editor->SetCursorPosL(editor->TextLength(),ETrue);
       
   168 	editor->SetFocus(ETrue);
       
   169 	editor->ActivateL();
       
   170 	iEikonEnv->EikAppUi()->AddToStackL(this,ECoeStackPriorityDialog,ECoeStackFlagRefusesFocus);
       
   171 	CleanupStack::Pop(); // editor
       
   172 	iEditor=editor;
       
   173 	iCoeEnv->InputCapabilitiesChanged();
       
   174 	_AKNTRACE_FUNC_EXIT;
       
   175 	}
       
   176 
       
   177 /**
       
   178  * Writes the internal state of the control and its components to aStream.
       
   179  * Does nothing in release mode.
       
   180  * Designed to be overidden and base called by subclasses.
       
   181  *
       
   182  * @internal
       
   183  * @since App-Framework_6.1
       
   184  */
       
   185 #ifndef _DEBUG
       
   186 EXPORT_C void CEikListBoxTextEditor::WriteInternalStateL(RWriteStream&) const
       
   187 	{}
       
   188 #else
       
   189 EXPORT_C void CEikListBoxTextEditor::WriteInternalStateL(RWriteStream& aWriteStream) const
       
   190 	{
       
   191 	_LIT(KEikLitLbxEdCtlStart,"<CEikListBoxTextEditor>");
       
   192 	_LIT(KEikLitLbxEdCtlEnd,"<\\CEikListBoxTextEditor>");
       
   193 	_LIT(KEikLitLbxEdObs,"<iEditorObserver>");
       
   194 	_LIT(KEikLitLbxEdObsEnd,"<\\iEditorObserver>");
       
   195 	_LIT(KEikLitLbxEdMdl,"<iModel>");
       
   196 	_LIT(KEikLitLbxEdMdlEnd,"<\\iModel>");
       
   197 	_LIT(KEikLitLbxEdEdr,"<iEditor>");
       
   198 	_LIT(KEikLitLbxEdEdrEnd,"<\\iEditor>");
       
   199 	_LIT(KEikLitLbxEdIndx,"<iItemIndex>");
       
   200 	_LIT(KEikLitLbxEdIndxEnd,"<\\iItemIndex>");
       
   201 	_LIT(KEikLitLbxEdFont,"<iFont>");
       
   202 	_LIT(KEikLitLbxEdFontEnd,"<\\iFont>");
       
   203 	_LIT(KEikLitLbxEdItemPos,"<iItemPos>");
       
   204 	_LIT(KEikLitLbxEdItemPosEnd,"<\\iItemPos>");
       
   205 	_LIT(KEikLitLbxEdItemLen,"<iItemLen>");
       
   206 	_LIT(KEikLitLbxEdItemLenEnd,"<\\iItemLen>");
       
   207 	_LIT(KEikLitLbxEdParaLay,"<iParaFormatLayer>");
       
   208 	_LIT(KEikLitLbxEdParaLayEnd,"<\\iParaFormatLayer>");
       
   209 	_LIT(KEikLitLbxEdCharLay,"<iCharFormatLayer>");
       
   210 	_LIT(KEikLitLbxEdCharLayEnd,"<\\iCharFormatLayer>");
       
   211 	
       
   212 	aWriteStream << KEikLitLbxEdCtlStart;
       
   213 	aWriteStream << KEikLitLbxEdObs;
       
   214 	aWriteStream.WriteInt32L((TInt)iEditorObserver);
       
   215 	aWriteStream << KEikLitLbxEdObsEnd;
       
   216 	aWriteStream << KEikLitLbxEdMdl;
       
   217 	aWriteStream.WriteInt32L((TInt)iModel);
       
   218 	aWriteStream << KEikLitLbxEdMdlEnd;
       
   219 	aWriteStream << KEikLitLbxEdEdr;
       
   220 	iEditor->WriteInternalStateL(aWriteStream); // won't be done as a component
       
   221 	aWriteStream << KEikLitLbxEdEdrEnd;
       
   222 	aWriteStream << KEikLitLbxEdIndx;
       
   223 	aWriteStream.WriteInt32L(iItemIndex);
       
   224 	aWriteStream << KEikLitLbxEdIndxEnd;
       
   225 	aWriteStream << KEikLitLbxEdFont;
       
   226 	const TFontSpec& spec=iFont->FontSpecInTwips();
       
   227 	aWriteStream << spec;
       
   228 	aWriteStream << KEikLitLbxEdFontEnd;
       
   229 	aWriteStream << KEikLitLbxEdItemPos;
       
   230 	aWriteStream.WriteInt32L(iItemPos);
       
   231 	aWriteStream << KEikLitLbxEdItemPosEnd;
       
   232 	aWriteStream << KEikLitLbxEdItemLen;
       
   233 	aWriteStream.WriteInt32L(iItemLen);
       
   234 	aWriteStream << KEikLitLbxEdItemLenEnd;
       
   235 	aWriteStream << KEikLitLbxEdParaLay;
       
   236 	aWriteStream << *iParaFormatLayer;
       
   237 	aWriteStream << KEikLitLbxEdParaLayEnd;
       
   238 	aWriteStream << KEikLitLbxEdCharLay;
       
   239 	aWriteStream << *iCharFormatLayer;
       
   240 	aWriteStream << KEikLitLbxEdCharLayEnd;
       
   241 	CCoeControl::WriteInternalStateL(aWriteStream);
       
   242 	aWriteStream << KEikLitLbxEdCtlEnd;
       
   243 	}
       
   244 #endif
       
   245 
       
   246 EXPORT_C TPtrC CEikListBoxTextEditor::ItemText()
       
   247 	{
       
   248 	return static_cast<MTextListBoxModel*>(ListBoxModel())->ItemText(ItemIndex());
       
   249 	}
       
   250 
       
   251 TPtrC CEikListBoxTextEditor::EditableItemText(TRect* aRect)
       
   252 	{
       
   253 	_AKNTRACE_FUNC_ENTER;
       
   254     TPtrC itemtext = ItemText();
       
   255 	if (iItemPos==0)	// not yet set (and even if set, cannot be zero)
       
   256 		{
       
   257 		iItemPos = itemtext.Locate('\n');	// loacte partly editable item start
       
   258 	    if (iItemPos != KErrNotFound)
       
   259 			{
       
   260 			iItemPos++;		// jump over mark character
       
   261 			iItemLen = itemtext.Mid( iItemPos ).Locate('\n');	// locate string end
       
   262 			if ( iItemLen == KErrNotFound )
       
   263 				Panic( ETUiklbedPanicEndMarkMissing );
       
   264 			if ( iItemLen==0 )
       
   265 				Panic( ETUiklbedPanicEmptyField );
       
   266 			TPtrC head = itemtext.Left( iItemPos );
       
   267 			TPtrC body = itemtext.Mid( iItemPos, iItemLen );
       
   268 			if ( aRect ) // adjust the rect if it is given
       
   269 				{
       
   270 				aRect->iTl.iX += iFont->TextWidthInPixels( head );
       
   271 				aRect->iBr.iX = aRect->iTl.iX + iFont->TextWidthInPixels( body ) + 4;
       
   272 				}
       
   273 			_AKNTRACE_FUNC_EXIT;
       
   274 			return body;
       
   275 			}
       
   276 		iItemPos = 0; // partly editable text not found
       
   277 		}
       
   278 	_AKNTRACE_FUNC_EXIT;
       
   279 	return itemtext;
       
   280 	}
       
   281 	
       
   282 EXPORT_C void CEikListBoxTextEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent) 
       
   283     { 
       
   284     CAknControl::HandlePointerEventL(aPointerEvent); 
       
   285     }	
       
   286 
       
   287 EXPORT_C void* CEikListBoxTextEditor::ExtensionInterface( TUid /*aInterface*/ )
       
   288     {
       
   289     return NULL;
       
   290     }
       
   291 
       
   292 /**
       
   293  * Stops editing the current item, if editing was taking place. Does not Leave.
       
   294  *
       
   295  * @since Uikon1.2
       
   296  */
       
   297 EXPORT_C void CEikListBoxTextEditor::StopEditingL()
       
   298 	{
       
   299 	iEikonEnv->EikAppUi()->RemoveFromStack(this);
       
   300 	if ( Editor() == NULL ) return; // quit if editing is not currently on
       
   301 	iEditor->SetFocus(EFalse);      // BUG? - cursor remains on screen without this
       
   302 	delete iEditor;
       
   303 	iEditor=NULL;
       
   304 	iCoeEnv->InputCapabilitiesChanged();
       
   305 	}
       
   306 
       
   307 EXPORT_C TBool CEikListBoxTextEditor::UpdateModelL()
       
   308 	// virtual - needs to be rewritten if editing other than single column text list
       
   309 	{
       
   310 	_AKNTRACE_FUNC_ENTER;
       
   311 	if (!Editor()) 
       
   312 	    {
       
   313 	    _AKNTRACE_FUNC_EXIT;
       
   314 	    return EFalse;   // quit if editing is not currently on
       
   315 	    }
       
   316 	const MDesCArray* matchableTextArray=ListBoxModel()->MatchableTextArray();
       
   317 	CDesCArray* textArray=(CDesCArray*)matchableTextArray;
       
   318 
       
   319     TPtrC itemtext = ItemText();
       
   320     if ( iItemPos ) // partly editable item?
       
   321         {
       
   322         HBufC* itemBuffer= HBufC::New(itemtext.Length());
       
   323         CleanupStack::PushL( itemBuffer );
       
   324         TPtr itemPointer = itemBuffer->Des();
       
   325 
       
   326         itemPointer.Append( itemtext.Left( iItemPos ) );
       
   327 
       
   328         HBufC* ptr=iEditor->GetTextInHBufL();
       
   329 		TPtrC newText;
       
   330 		if (ptr)
       
   331 			{
       
   332 			newText.Set(ptr->Des());
       
   333 			}
       
   334         TInt addSpaces = iItemLen - newText.Length();
       
   335         for (TInt index=0; ((addSpaces>0) && (index<addSpaces)); index++)
       
   336 			itemPointer.Append(_L(" "));
       
   337 
       
   338         itemPointer.Append( newText );
       
   339         itemPointer.Append( itemtext.Right( itemtext.Length()-iItemPos-iItemLen ) );
       
   340 
       
   341         delete ptr;
       
   342 		textArray->InsertL( ItemIndex(), *itemBuffer );
       
   343         CleanupStack::PopAndDestroy(); // itemBuffer
       
   344 
       
   345         textArray->Delete( ItemIndex()+1 );
       
   346         }
       
   347     else // replace the whole list item
       
   348         {
       
   349 		HBufC* newText = iEditor->GetTextInHBufL();
       
   350 		if (!newText) return ETrue; // if user tries to insert an empty text...
       
   351 
       
   352 		CleanupStack::PushL(newText);
       
   353 		textArray->InsertL(ItemIndex(),*newText);
       
   354 		CleanupStack::PopAndDestroy(); // newText
       
   355 
       
   356 		textArray->Delete( ItemIndex() + 1 );
       
   357 		}
       
   358     _AKNTRACE_FUNC_EXIT;
       
   359 	return ETrue;
       
   360 	}
       
   361 
       
   362 EXPORT_C TInt CEikListBoxTextEditor::ItemIndex() const
       
   363 	{
       
   364 	return iItemIndex;
       
   365 	}
       
   366 
       
   367 EXPORT_C TKeyResponse CEikListBoxTextEditor::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
       
   368 	{
       
   369 	_AKNTRACE_FUNC_ENTER;
       
   370 	_AKNTRACE( "aKeyEvent.iCode is %d", aKeyEvent.iCode );
       
   371 	_AKNTRACE( "aKeyEvent.iScanCode is %d", aKeyEvent.iScanCode );
       
   372 	_AKNTRACE( "aType is %d", aType );
       
   373 	if (!Editor() || aType!=EEventKey)
       
   374 		{
       
   375 		_AKNTRACE_FUNC_EXIT;
       
   376 		return EKeyWasNotConsumed;
       
   377 		}
       
   378 
       
   379 	if(iEditorObserver && iEditorObserver->HandleListBoxEditorEventL(this,aKeyEvent)==EKeyWasConsumed)
       
   380 		{ // gives owning dialogs or listboxes a chance to intecept keys prior to or instead of passing to editor
       
   381 		// eg the CCknFileSaveAsDialog needs to check if a file exists when the enter key is pressed
       
   382 		// and prevent the Enter key being passed on to the editor, or intecept the up/down keys to
       
   383 		// allow scrolling out of the editor
       
   384 		_AKNTRACE_FUNC_EXIT;
       
   385 		return EKeyWasConsumed;
       
   386 		}
       
   387 	const TInt code=aKeyEvent.iCode;
       
   388 	if (aKeyEvent.iModifiers&(EModifierCtrl|EModifierShift)==(EModifierCtrl|EModifierShift))
       
   389 		{
       
   390 		TBuf<24> buf;
       
   391 		iCoeEnv->ReadResource(buf,R_EIK_EDWIN_SHIFT_CTRL_HOTKEYS);
       
   392 		const TInt pos=buf.Locate(TChar(code+'a'-1));
       
   393 		if (pos==CEikEdwin::EHotKeyInsertChar)
       
   394 			{
       
   395 			_AKNTRACE_FUNC_EXIT;
       
   396 			return EKeyWasConsumed;
       
   397 			}
       
   398 		}
       
   399 	switch (code)
       
   400 		{
       
   401 		case EKeyEnter:     // stop editing and update data
       
   402 		case EKeyOK:
       
   403 			UpdateModelL();
       
   404 			StopEditingL();
       
   405 			break;
       
   406 		case EKeyEscape:    // stop editing and don't update data
       
   407 			StopEditingL();
       
   408 			break;
       
   409 		default:
       
   410 			Editor()->OfferKeyEventL(aKeyEvent,aType);
       
   411 		}
       
   412 	_AKNTRACE_FUNC_EXIT;
       
   413 	return EKeyWasConsumed;
       
   414 	}
       
   415 
       
   416 EXPORT_C void CEikListBoxTextEditor::SetListBoxEditorObserver(MListBoxEditorObserver* aObserver)
       
   417 	{
       
   418 	iEditorObserver=aObserver;
       
   419 	}
       
   420 
       
   421 EXPORT_C void CEikListBoxTextEditor::MEikListBoxEditor_Reserved_1()
       
   422 	{
       
   423 	}